mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-25 15:01:49 +00:00
55 lines
1.9 KiB
TypeScript
55 lines
1.9 KiB
TypeScript
import { remark } from 'remark';
|
|
import gfm from 'remark-gfm';
|
|
import type { Options as RemarkGithubOptions } from 'remark-github';
|
|
import github from 'remark-github';
|
|
import { regEx } from './regex.ts';
|
|
|
|
// Generic replacements/link-breakers
|
|
export function sanitizeMarkdown(markdown: string): string {
|
|
let res = markdown;
|
|
// Put a zero width space after every # followed by a digit
|
|
res = res.replace(regEx(/(\W)#(\d)/gi), '$1#​$2');
|
|
// Put a zero width space after every @ symbol to prevent unintended hyperlinking,
|
|
// but leave URLs, code blocks (triple backticks), and inline code spans untouched
|
|
res = res
|
|
.split(regEx(/(```[\s\S]*?```|`[^`\n]*?`|https?:\/\/[^\s<]+)/gi))
|
|
.map((part) =>
|
|
part.startsWith('`') || regEx(/^https?:\/\//i).test(part)
|
|
? part
|
|
: part.replace(regEx(/@/g), '@​'),
|
|
)
|
|
.join('');
|
|
res = res.replace(regEx(/([a-z]@)​/gi), '$1');
|
|
res = res.replace(regEx(/\/compare\/@​/g), '/compare/@');
|
|
res = res.replace(regEx(/(\(https:\/\/[^)]*?)\.\.\.@​/g), '$1...@');
|
|
res = res.replace(regEx(/([\s(])#(\d+)([)\s]?)/g), '$1#​$2$3');
|
|
// convert escaped backticks back to `
|
|
const backTickRe = regEx(/`([^/]*?)`/g);
|
|
res = res.replace(backTickRe, '`$1`');
|
|
res = res.replace(regEx(/`#​(\d+)`/g), '`#$1`');
|
|
res = res.replace(
|
|
regEx(/(?<before>[^\n]\n)(?<title>#.*)/g),
|
|
'$<before>\n$<title>',
|
|
);
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param content content to process
|
|
* @param options github options
|
|
* @returns linkified content
|
|
*/
|
|
export async function linkify(
|
|
content: string,
|
|
options: RemarkGithubOptions,
|
|
): Promise<string> {
|
|
// https://github.com/syntax-tree/mdast-util-to-markdown#optionsbullet
|
|
const output = await remark()
|
|
.use({ settings: { bullet: '-' } })
|
|
.use(gfm)
|
|
.use(github, { mentionStrong: false, ...options })
|
|
.process(content);
|
|
return output.toString();
|
|
}
|