@md-plugins/md-plugin-codeblocks 0.1.0-beta.17 → 0.1.0-beta.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +158 -24
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# md-plugin-codeblocks
|
|
2
2
|
|
|
3
|
-
A **Markdown-It** plugin that enhances code block rendering by providing syntax highlighting, line numbering, and support for advanced features like tabbed code blocks. It integrates with
|
|
3
|
+
A **Markdown-It** plugin that enhances code block rendering by providing syntax highlighting, line numbering, and support for advanced features like tabbed code blocks. It integrates with Shiki for syntax highlighting and allows customization for various use cases.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **Syntax Highlighting**: Automatically highlights code blocks using **
|
|
7
|
+
- **Syntax Highlighting**: Automatically highlights code blocks using **Shiki**.
|
|
8
8
|
- **Line Numbering**: Optionally adds line numbers to code blocks.
|
|
9
9
|
- **Magic Comments**: Supports special comments like `[[! highlight]]`, `[[! add]]`, and `[[! rem]]` for inline code annotations.
|
|
10
10
|
- **Tabbed Code Blocks**: Enables the creation of tabbed code blocks for multi-language or multi-file examples.
|
package/dist/index.d.mts
CHANGED
|
@@ -46,7 +46,7 @@ interface CodeblockPluginOptions {
|
|
|
46
46
|
*/
|
|
47
47
|
pageScripts?: string[];
|
|
48
48
|
/**
|
|
49
|
-
* Optional
|
|
49
|
+
* Optional Shiki languages configuration array. This allows you to override or add custom language definitions.
|
|
50
50
|
* Each item can have a `name`, optional `aliases`, and `customCopy` boolean.
|
|
51
51
|
*/
|
|
52
52
|
langList?: Lang[];
|
package/dist/index.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ interface CodeblockPluginOptions {
|
|
|
46
46
|
*/
|
|
47
47
|
pageScripts?: string[];
|
|
48
48
|
/**
|
|
49
|
-
* Optional
|
|
49
|
+
* Optional Shiki languages configuration array. This allows you to override or add custom language definitions.
|
|
50
50
|
* Each item can have a `name`, optional `aliases`, and `customCopy` boolean.
|
|
51
51
|
*/
|
|
52
52
|
langList?: Lang[];
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { addClassToHast } from 'shiki/core';
|
|
2
|
+
import { createHighlighter } from 'shiki';
|
|
3
|
+
import { transformerNotationHighlight, transformerNotationDiff, transformerNotationFocus, transformerNotationErrorLevel, transformerNotationWordHighlight } from '@shikijs/transformers';
|
|
3
4
|
|
|
4
5
|
function resolvePluginOptions(options, key, defaults) {
|
|
5
6
|
if (options && typeof options === "object" && key in options) {
|
|
@@ -8,11 +9,155 @@ function resolvePluginOptions(options, key, defaults) {
|
|
|
8
9
|
return { ...defaults, ...options };
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
const shikiLangs = [
|
|
13
|
+
"bash",
|
|
14
|
+
"css",
|
|
15
|
+
"diff",
|
|
16
|
+
"html",
|
|
17
|
+
"javascript",
|
|
18
|
+
"json",
|
|
19
|
+
"nginx",
|
|
20
|
+
"sass",
|
|
21
|
+
"scss",
|
|
22
|
+
"typescript",
|
|
23
|
+
"vue",
|
|
24
|
+
"xml",
|
|
25
|
+
"yaml"
|
|
26
|
+
];
|
|
27
|
+
const shikiLangAlias = {
|
|
28
|
+
js: "javascript",
|
|
29
|
+
markup: "html",
|
|
30
|
+
shell: "bash",
|
|
31
|
+
sh: "bash",
|
|
32
|
+
ts: "typescript",
|
|
33
|
+
yml: "yaml"
|
|
34
|
+
};
|
|
35
|
+
const highlighter = await createHighlighter({
|
|
36
|
+
themes: ["github-light", "github-dark"],
|
|
37
|
+
langs: shikiLangs,
|
|
38
|
+
langAlias: shikiLangAlias
|
|
39
|
+
});
|
|
40
|
+
const supportedLangSet = new Set(highlighter.getLoadedLanguages());
|
|
41
|
+
const themeOptions = {
|
|
42
|
+
themes: {
|
|
43
|
+
light: "github-light",
|
|
44
|
+
dark: "github-dark"
|
|
45
|
+
},
|
|
46
|
+
defaultColor: false
|
|
47
|
+
};
|
|
48
|
+
function normalizeShikiLang(lang) {
|
|
49
|
+
return supportedLangSet.has(lang) ? lang : "text";
|
|
50
|
+
}
|
|
51
|
+
function buildCodeBlockTransformers({
|
|
52
|
+
codeClass,
|
|
53
|
+
lineList,
|
|
54
|
+
maxheight,
|
|
55
|
+
preClass
|
|
56
|
+
}) {
|
|
57
|
+
return [
|
|
58
|
+
preClassTransformer(preClass, maxheight),
|
|
59
|
+
codeClassTransformer(codeClass),
|
|
60
|
+
transformerNotationHighlight(),
|
|
61
|
+
transformerNotationDiff(),
|
|
62
|
+
transformerNotationFocus(),
|
|
63
|
+
transformerNotationErrorLevel(),
|
|
64
|
+
transformerNotationWordHighlight(),
|
|
65
|
+
lineDecorTransformer(lineList)
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
function preClassTransformer(preClass, maxheight) {
|
|
69
|
+
return {
|
|
70
|
+
name: "md-plugins:pre-class",
|
|
71
|
+
pre(node) {
|
|
72
|
+
addClassToHast(node, preClass);
|
|
73
|
+
if (maxheight !== void 0) {
|
|
74
|
+
const style = typeof node.properties?.style === "string" ? node.properties.style : "";
|
|
75
|
+
node.properties = {
|
|
76
|
+
...node.properties,
|
|
77
|
+
style: `${style}${style.length > 0 ? ";" : ""}max-height:${maxheight}`
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function codeClassTransformer(codeClass) {
|
|
84
|
+
return {
|
|
85
|
+
name: "md-plugins:code-class",
|
|
86
|
+
code(node) {
|
|
87
|
+
if (codeClass !== void 0 && codeClass.length > 0) {
|
|
88
|
+
addClassToHast(node, codeClass);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function lineDecorTransformer(lineList) {
|
|
94
|
+
return {
|
|
95
|
+
name: "md-plugins:line-decor",
|
|
96
|
+
code(codeNode) {
|
|
97
|
+
const lines = codeNode.children.filter(
|
|
98
|
+
(child) => child.type === "element" && child.tagName === "span" && lineHasClass(child, "line")
|
|
99
|
+
);
|
|
100
|
+
lines.forEach((line, index) => {
|
|
101
|
+
const target = lineList[index];
|
|
102
|
+
const classList = [...target?.classList ?? []];
|
|
103
|
+
const prefix = target?.prefix ?? [];
|
|
104
|
+
if (this.options.lang === "diff") {
|
|
105
|
+
const first = lineTextContent(line).charAt(0);
|
|
106
|
+
if (first === "+") {
|
|
107
|
+
classList.push("line-add");
|
|
108
|
+
} else if (first === "-") {
|
|
109
|
+
classList.push("line-rem");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (classList.length > 0) {
|
|
113
|
+
line.children?.unshift({
|
|
114
|
+
type: "element",
|
|
115
|
+
tagName: "span",
|
|
116
|
+
properties: { class: ["c-line", ...classList] },
|
|
117
|
+
children: []
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (prefix.length > 0) {
|
|
121
|
+
line.children?.unshift({
|
|
122
|
+
type: "element",
|
|
123
|
+
tagName: "span",
|
|
124
|
+
properties: { class: "c-lpref" },
|
|
125
|
+
children: [{ type: "text", value: prefix.join(" ") }]
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function lineHasClass(line, className) {
|
|
133
|
+
const classValue = line.properties?.class;
|
|
134
|
+
if (typeof classValue === "string") {
|
|
135
|
+
return classValue.split(/\s+/).includes(className);
|
|
136
|
+
}
|
|
137
|
+
if (Array.isArray(classValue)) {
|
|
138
|
+
return classValue.includes(className);
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
function lineTextContent(line) {
|
|
143
|
+
let acc = "";
|
|
144
|
+
const walk = (node) => {
|
|
145
|
+
if (node.type === "text") {
|
|
146
|
+
acc += node.value ?? "";
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
node.children?.forEach(walk);
|
|
150
|
+
};
|
|
151
|
+
line.children?.forEach(walk);
|
|
152
|
+
return acc;
|
|
153
|
+
}
|
|
154
|
+
|
|
11
155
|
const defaultLangList = [
|
|
12
156
|
{ name: "markup" },
|
|
13
157
|
{ name: "bash", customCopy: true },
|
|
14
158
|
{ name: "javascript", aliases: "javascript|js" },
|
|
15
159
|
{ name: "typescript", aliases: "typescript|ts" },
|
|
160
|
+
{ name: "yaml", aliases: "yaml|yml" },
|
|
16
161
|
{ name: "sass" },
|
|
17
162
|
{ name: "scss" },
|
|
18
163
|
{ name: "css" },
|
|
@@ -20,6 +165,7 @@ const defaultLangList = [
|
|
|
20
165
|
{ name: "xml" },
|
|
21
166
|
{ name: "nginx" },
|
|
22
167
|
{ name: "html" },
|
|
168
|
+
{ name: "vue" },
|
|
23
169
|
{ name: "diff" }
|
|
24
170
|
// special grammars
|
|
25
171
|
];
|
|
@@ -54,7 +200,6 @@ const codeblocksPlugin = (md, options) => {
|
|
|
54
200
|
pageScripts = DEFAULT_CODEBLOCK_PLUGIN_OPTIONS.pageScripts,
|
|
55
201
|
langList = defaultLangList
|
|
56
202
|
} = resolvedOptions;
|
|
57
|
-
loadLanguages(langList.map((l) => l.name));
|
|
58
203
|
const customCopyLangList = langList.filter((l) => l.customCopy === true).map((l) => l.name);
|
|
59
204
|
const langMatch = langList.map((l) => l.aliases || l.name).join("|");
|
|
60
205
|
const definitionLineRE = new RegExp(
|
|
@@ -152,13 +297,6 @@ const codeblocksPlugin = (md, options) => {
|
|
|
152
297
|
}
|
|
153
298
|
return acc;
|
|
154
299
|
}
|
|
155
|
-
function renderCodeBlock(html, codeClass2) {
|
|
156
|
-
return `<code${codeClass2 ? ` class="${codeClass2}"` : ""}>${html}</code>`;
|
|
157
|
-
}
|
|
158
|
-
function getPrismHighlightedContent(rawContent, lang) {
|
|
159
|
-
const content = rawContent.trim();
|
|
160
|
-
return prism.highlight(content, prism.languages[lang], lang);
|
|
161
|
-
}
|
|
162
300
|
function getHighlightedContent(rawContent, attrs) {
|
|
163
301
|
const { lang, maxheight } = attrs;
|
|
164
302
|
let content = rawContent.trim();
|
|
@@ -166,21 +304,17 @@ const codeblocksPlugin = (md, options) => {
|
|
|
166
304
|
if (lang !== "markup") {
|
|
167
305
|
content = content.trim().replace(magicCommentGlobalRE, "");
|
|
168
306
|
}
|
|
169
|
-
const html = getPrismHighlightedContent(content, lang).split("\n").map((line, lineIndex) => {
|
|
170
|
-
const target = lineList[lineIndex];
|
|
171
|
-
if (target === void 0) return line;
|
|
172
|
-
let lineHtml = "";
|
|
173
|
-
lineHtml += target.classList.length !== 0 ? `<span class="c-line ${target.classList.join(" ")}"></span>` : "";
|
|
174
|
-
lineHtml += target.prefix.length !== 0 ? `<span class="c-lpref">${target.prefix.join(" ")}</span>` : "";
|
|
175
|
-
lineHtml += line;
|
|
176
|
-
return lineHtml;
|
|
177
|
-
}).join("\n");
|
|
178
|
-
const preAttrs = maxheight !== void 0 ? ` style="max-height:${maxheight}"` : "";
|
|
179
307
|
const langProp = customCopyLangList.includes(lang) === true ? ` lang="${lang}"` : "";
|
|
180
|
-
return (
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
308
|
+
return highlighter.codeToHtml(content, {
|
|
309
|
+
lang: normalizeShikiLang(lang),
|
|
310
|
+
...themeOptions,
|
|
311
|
+
transformers: buildCodeBlockTransformers({
|
|
312
|
+
codeClass,
|
|
313
|
+
lineList,
|
|
314
|
+
maxheight,
|
|
315
|
+
preClass: preClass ?? "markdown-code"
|
|
316
|
+
})
|
|
317
|
+
}).replace("<pre ", "<pre v-pre ") + `<${copyButtonComponent}${langProp} />`;
|
|
184
318
|
}
|
|
185
319
|
function parseAttrs(rawAttrs) {
|
|
186
320
|
if (rawAttrs === null) return {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@md-plugins/md-plugin-codeblocks",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.18",
|
|
4
4
|
"description": "A markdown-it plugin for code blocks.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown-it",
|
|
@@ -35,16 +35,17 @@
|
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@shikijs/transformers": "^4.1.0",
|
|
40
|
+
"shiki": "^4.1.0"
|
|
41
|
+
},
|
|
38
42
|
"devDependencies": {
|
|
39
43
|
"@types/markdown-it": "^14.1.2",
|
|
40
|
-
"@types/prismjs": "^1.26.6",
|
|
41
44
|
"markdown-it": "^14.2.0",
|
|
42
|
-
"
|
|
43
|
-
"@md-plugins/shared": "0.1.0-beta.17"
|
|
45
|
+
"@md-plugins/shared": "0.1.0-beta.18"
|
|
44
46
|
},
|
|
45
47
|
"peerDependencies": {
|
|
46
|
-
"markdown-it": "^14.2.0"
|
|
47
|
-
"prismjs": "^1.29.0"
|
|
48
|
+
"markdown-it": "^14.2.0"
|
|
48
49
|
},
|
|
49
50
|
"scripts": {
|
|
50
51
|
"build": "unbuild",
|