@md-plugins/md-plugin-codeblocks 0.1.0-beta.16 → 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 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 Prism.js for syntax highlighting and allows customization for various use cases.
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 **Prism.js**.
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 Prism languages configuration array. This allows you to override or add custom language definitions.
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 Prism languages configuration array. This allows you to override or add custom language definitions.
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 prism from 'prismjs';
2
- import loadLanguages from 'prismjs/components/index.js';
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
- // `<pre v-pre class="${preClass}${langClass}"${preAttrs}>` +
182
- `<pre v-pre class="${preClass}"${preAttrs}>` + renderCodeBlock(html, codeClass) + `</pre><${copyButtonComponent}${langProp} />`
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.16",
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
- "prismjs": "^1.30.0",
43
- "@md-plugins/shared": "0.1.0-beta.16"
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",