-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
80 lines (61 loc) · 1.97 KB
/
index.js
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
'use strict';
const Prism = require('prismjs');
const {render} = require('posthtml-render');
const loadLanguages = require('prismjs/components/');
function createPrismPlugin(options) {
return function (tree) {
const highlightCodeTags = node => tree.match.call(node, {tag: 'code'}, highlightNode);
if (options.inline) {
highlightCodeTags(tree);
} else {
tree.match({tag: 'pre'}, highlightCodeTags);
}
};
}
function highlightNode(node) {
const attrs = node.attrs || {};
const classList = `${attrs.class || ''}`.trimStart();
if ('prism-ignore' in attrs) {
delete node.attrs['prism-ignore'];
return node;
}
if (classList.includes('prism-ignore')) {
node.attrs.class = node.attrs.class.replace('prism-ignore', '').trim();
return node;
}
const lang = getExplicitLanguage(classList);
if (lang && !classList.includes(`language-${lang}`)) {
attrs.class = `${classList || ''} language-${lang}`.trimStart();
}
node.attrs = attrs;
if (node.content) {
const html = (node.content[0].tag && !node.content[0].content) ? `<${node.content[0].tag}>` : render(node.content);
node.content = mapStringOrNode(html, lang);
}
return node;
}
function mapStringOrNode(stringOrNode, lang = null) {
if (typeof stringOrNode === 'string') {
if (lang) {
if (!Object.keys(Prism.languages).includes(lang)) {
loadLanguages.silent = true;
loadLanguages([lang]);
}
return Prism.highlight(stringOrNode, Prism.languages[lang], lang);
}
return Prism.highlight(stringOrNode, Prism.languages.markup, 'markup');
}
highlightNode(stringOrNode);
return stringOrNode;
}
function getExplicitLanguage(classList) {
const matches = classList.match(/(?:lang|language)-(\w*)/);
return matches === null ? null : matches[1];
}
module.exports = options => {
options = options || {};
options.inline = options.inline || false;
return function (tree) {
return createPrismPlugin(options)(tree);
};
};