aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/util/markdown.ts
blob: 35e963af819f1dca47b53e5ceb79835e1648dafe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import remark from 'remark';
import github from 'remark-github';
import { regEx } from './regex';

// 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
  res = res.replace(regEx(/@/g), '@​');
  res = res.replace(regEx(/(`\[?@)​/g), '$1');
  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: github.RemarkGithubOptions,
): Promise<string> {
  // https://github.com/syntax-tree/mdast-util-to-markdown#optionsbullet
  const output = await remark()
    .use({ settings: { bullet: '-' } })
    .use(github, { mentionStrong: false, ...options })
    .process(content);
  return output.toString();
}