-
Notifications
You must be signed in to change notification settings - Fork 3.3k
/
Copy pathmarkdown.ts
113 lines (105 loc) · 3.36 KB
/
markdown.ts
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import MarkdownIt from 'markdown-it';
import markdownItContainer from 'markdown-it-container';
import markdownItDefinitionList from 'markdown-it-deflist';
import markdownItFootnote from 'markdown-it-footnote';
import markdownItAttrs from 'markdown-it-attrs';
import markdownItAnchor from 'markdown-it-anchor';
import { slugify } from '../utils/slugify.js';
export const markdown = (() => {
const markdown = new MarkdownIt({ html: true })
.use(markdownItDefinitionList)
.use(markdownItFootnote)
.use(markdownItAttrs, {
leftDelimiter: '{:',
rightDelimiter: '}',
allowedAttributes: ['id', 'class', /^data-.*$/],
})
.use(markdownItAnchor, {
slugify: (s) => slugify(s),
level: 2,
tabIndex: false,
permalink: markdownItAnchor.permalink.linkAfterHeader({
style: 'aria-label',
assistiveText: title => `Link to '${title}' section`,
symbol: '#',
class: 'heading-link',
wrapper: ['<div class="heading-wrapper">', '</div>']
}),
});
_registerAsides(markdown);
_setUpTables(markdown);
return markdown;
})();
/**
* Wrap all tables in a div with `table-wrapper` class.
*/
function _setUpTables(markdown: MarkdownIt): void {
markdown.renderer.rules = {
...markdown.renderer.rules,
table_open: function (tokens, idx, _options, _env, self) {
const token = tokens[idx]!;
// Render added attributes from `{:.table .table-striped}` syntax.
return `<div class="table-wrapper">\n<table ${self.renderAttrs(token)}>\n`;
},
table_close: () => '</table>\n</div>',
};
}
/**
* Register a custom aside/admonition.
*
* @param markdown
* @param id The name to use in Markdown to create the aside.
* @param defaultTitle The title to use if no title is specified in Markdown.
* @param icon The material icon to use in the aside.
* @param style The classes to add to the aside.
*/
function _registerAside(markdown: MarkdownIt, id: string, defaultTitle: string | null, icon: string | null, style: string): void {
markdown.use(markdownItContainer, id, {
render: function (tokens: any[], index: number) {
if (tokens[index].nesting === 1) {
const parsedArgs = /\s+(.*)/.exec(tokens[index].info);
const title = parsedArgs?.[1] ?? defaultTitle ?? '';
return `<aside class="alert ${style}">
<div class="alert-header">
${icon !== null ? `<i class="material-symbols" aria-hidden="true">${icon}</i>` : ''}
<span>${title ?? ''}</span>
</div>
<div class="alert-content">
`;
} else {
return '</div></aside>\n';
}
},
});
}
/**
* Registers the custom asides/admonitions used on the site.
*/
function _registerAsides(markdown: MarkdownIt): void {
_registerAside(markdown, 'note', 'Note', 'info', 'alert-info');
_registerAside(
markdown,
'flutter-note',
'Flutter note',
'flutter',
'alert-info',
);
_registerAside(
markdown,
'version-note',
'Version note',
'merge_type',
'alert-info',
);
_registerAside(markdown, 'tip', 'Tip', 'lightbulb', 'alert-success');
_registerAside(markdown, 'recommend', 'Recommended', 'bolt', 'alert-success');
_registerAside(markdown, 'important', 'Important', 'error', 'alert-important');
_registerAside(
markdown,
'warning',
'Warning',
'warning',
'alert-warning',
);
_registerAside(markdown, 'secondary', null, null, 'alert-secondary');
}