rehype-highlight-code-lines 1.2.0 → 1.2.2
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 +20 -4
- package/dist/{esm/index.d.ts → index.d.ts} +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/{esm/index.js → index.js} +9 -6
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +27 -21
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/tsconfig.tsbuildinfo +0 -1
- package/src/index.ts +0 -506
package/README.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
**A robust Next.js newsletter `Next.js Weekly` is sponsoring me** 💖
|
|
2
|
+
[](https://nextjsweekly.com/)
|
|
3
|
+
|
|
4
|
+
### [Become a sponsor](https://github.com/sponsors/ipikuka) 🚀
|
|
5
|
+
|
|
6
|
+
If you find **`rehype-highlight-code-lines`** useful in your projects, consider supporting my work.
|
|
7
|
+
Your sponsorship means a lot 💖
|
|
8
|
+
|
|
9
|
+
My sponsors are going to be featured here and on [my sponsor wall](https://github.com/sponsors/ipikuka).
|
|
10
|
+
|
|
11
|
+
A warm thanks 🙌 to [@ErfanEbrahimnia](https://github.com/ErfanEbrahimnia), [@recepkyk](https://github.com/recepkyk), and [@LSeaburg](https://github.com/LSeaburg) for the support!
|
|
12
|
+
|
|
13
|
+
Thank you for supporting open source! 🙌
|
|
14
|
+
|
|
1
15
|
# rehype-highlight-code-lines
|
|
2
16
|
|
|
3
17
|
[![npm version][badge-npm-version]][url-npm-package]
|
|
@@ -18,7 +32,7 @@ This package is a **[unified][unified]** (**[rehype][rehype]**) plugin that **wr
|
|
|
18
32
|
|
|
19
33
|
**`rehype-highlight-code-lines`** is ideal for adding line numbers to code blocks and highlighting specific lines.
|
|
20
34
|
|
|
21
|
-
**`rehype-highlight-code-lines`** is **NOT** code highlighter and **does NOT** provide code highlighting! You can use a code highlighter for example **[rehype-highlight][rehype-highlight]** to highlight the code, then use
|
|
35
|
+
**`rehype-highlight-code-lines`** is **NOT** code highlighter and **does NOT** provide code highlighting! You can use a code highlighter for example **[rehype-highlight][rehype-highlight]** to highlight the code, then use **`rehype-highlight-code-lines`** **after**.
|
|
22
36
|
|
|
23
37
|
> [!IMPORTANT]
|
|
24
38
|
> If your code highlighter already provides numbering and highlighting code lines, don't use **`rehype-highlight-code-lines`**!
|
|
@@ -320,8 +334,8 @@ use(rehypeHighlightLines, {
|
|
|
320
334
|

|
|
321
335
|
|
|
322
336
|
**Here you can find some demo applications below which the `rehype-highlight` and `rehype-highlight-code-lines` are used together:**
|
|
323
|
-
+ [demo blog application](https://
|
|
324
|
-
+ [demo blog application](https://
|
|
337
|
+
+ [demo blog application](https://nmrc-in-app-router.vercel.app) using `next-mdx-remote-client` within `Next.js app router`
|
|
338
|
+
+ [demo blog application](https://nmrc-in-pages-router.vercel.app) using `next-mdx-remote-client` within `Next.js pages router`
|
|
325
339
|
|
|
326
340
|
## Styling
|
|
327
341
|
|
|
@@ -414,7 +428,7 @@ This plugin works with `rehype-parse` version 1+, `rehype-stringify` version 1+,
|
|
|
414
428
|
|
|
415
429
|
## Security
|
|
416
430
|
|
|
417
|
-
Use of
|
|
431
|
+
Use of **`rehype-highlight-code-lines`** involves rehype (hast), but doesn't lead to cross-site scripting (XSS) attacks.
|
|
418
432
|
|
|
419
433
|
## My Plugins
|
|
420
434
|
|
|
@@ -436,6 +450,8 @@ I like to contribute the Unified / Remark / MDX ecosystem, so I recommend you to
|
|
|
436
450
|
– Remark plugin to expose the table of contents via `vfile.data` or via an option reference
|
|
437
451
|
- [`remark-mdx-remove-esm`](https://www.npmjs.com/package/remark-mdx-remove-esm)
|
|
438
452
|
– Remark plugin to remove import and/or export statements (mdxjsEsm)
|
|
453
|
+
- [`remark-mdx-remove-expressions`](https://www.npmjs.com/package/remark-mdx-remove-expressions)
|
|
454
|
+
– Remark plugin to remove MDX expressions within curlybraces {} in MDX content
|
|
439
455
|
|
|
440
456
|
### My Rehype Plugins
|
|
441
457
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAiC,MAAM,MAAM,CAAC;AAQhE,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,IAAI;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;KACf;IACD,UAAU,UAAU;QAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;KACxC;CACF;AAMD,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAkBF,wBAAgB,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAE7E;AAgCD;;;;GAIG;AACH,QAAA,MAAM,MAAM,EAAE,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,EAAE,IAAI,CAyalD,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -65,8 +65,8 @@ const plugin = (options) => {
|
|
|
65
65
|
newTree.push(elementContent);
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
|
+
/* v8 ignore next -- @preserve */
|
|
68
69
|
// @ts-expect-error className is different from other key of properties, and expected to be an array or undefined
|
|
69
|
-
// /* v8 ignore next */
|
|
70
70
|
const classNames = className.concat(elementContent.properties.className || []);
|
|
71
71
|
if (elementContent.children.length === 1 &&
|
|
72
72
|
elementContent.children[0].type !== "element") {
|
|
@@ -157,6 +157,8 @@ const plugin = (options) => {
|
|
|
157
157
|
if (!REGEX_LINE_BREAKS_IN_THE_BEGINNING.test(textNode.value))
|
|
158
158
|
return;
|
|
159
159
|
const match = REGEX_LINE_BREAKS_IN_THE_BEGINNING.exec(textNode.value);
|
|
160
|
+
// classic V8 coverage false negative
|
|
161
|
+
/* v8 ignore next -- @preserve */
|
|
160
162
|
if (match) {
|
|
161
163
|
code.children.unshift({ type: "text", value: match[0] });
|
|
162
164
|
textNode.value = textNode.value.replace(REGEX_LINE_BREAKS_IN_THE_BEGINNING, "");
|
|
@@ -207,7 +209,8 @@ const plugin = (options) => {
|
|
|
207
209
|
// this happens always in code fence if there is extra blank line at the end
|
|
208
210
|
}
|
|
209
211
|
else {
|
|
210
|
-
|
|
212
|
+
lineNumber++;
|
|
213
|
+
replacement.push(createLine(line, lineNumber, directiveLineNumbering, directiveLineHighlighting), { type: "text", value: match[0] });
|
|
211
214
|
}
|
|
212
215
|
start = index + 1;
|
|
213
216
|
textStart = match.index + match[0].length;
|
|
@@ -227,7 +230,8 @@ const plugin = (options) => {
|
|
|
227
230
|
replacement.push(...remainingLine);
|
|
228
231
|
}
|
|
229
232
|
else {
|
|
230
|
-
|
|
233
|
+
lineNumber++;
|
|
234
|
+
replacement.push(createLine(remainingLine, lineNumber, directiveLineNumbering, directiveLineHighlighting));
|
|
231
235
|
}
|
|
232
236
|
}
|
|
233
237
|
// Replace children with new array.
|
|
@@ -265,10 +269,9 @@ const plugin = (options) => {
|
|
|
265
269
|
return;
|
|
266
270
|
}
|
|
267
271
|
// for type narrowing
|
|
272
|
+
/* v8 ignore if -- @preserve */
|
|
268
273
|
if (!isStringArray(code.properties.className) &&
|
|
269
|
-
code.properties.className !== undefined
|
|
270
|
-
/* v8 ignore next 3 */
|
|
271
|
-
) {
|
|
274
|
+
code.properties.className !== undefined) {
|
|
272
275
|
return;
|
|
273
276
|
}
|
|
274
277
|
/** the part of correcting language and meta */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Plugin } from \"unified\";\nimport type { Root, Element, Text, ElementContent } from \"hast\";\nimport { visit, type VisitorResult } from \"unist-util-visit\";\nimport rangeParser from \"parse-numeric-range\";\n\ntype Prettify<T> = { [K in keyof T]: T[K] } & {};\n\ntype PartiallyRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;\n\ndeclare module \"hast\" {\n interface Data {\n meta?: string;\n }\n interface Properties {\n dataStartNumbering?: string;\n dataHighlightLines?: string;\n metastring?: string | null | undefined;\n }\n}\n\ntype ElementWithTextNode = Element & {\n children: [Text];\n};\n\nexport type HighlightLinesOptions = {\n showLineNumbers?: boolean;\n keepOuterBlankLine?: boolean;\n};\n\nconst DEFAULT_SETTINGS: HighlightLinesOptions = {\n showLineNumbers: false,\n keepOuterBlankLine: false,\n};\n\ntype PartiallyRequiredHighlightLinesOptions = Prettify<\n PartiallyRequired<HighlightLinesOptions, \"showLineNumbers\">\n>;\n\ntype GutterOptions = {\n directiveLineNumbering: boolean | number;\n directiveLineHighlighting: number[];\n directiveKeepOuterBlankLine: boolean;\n};\n\n// a simple util for our use case, like clsx package\nexport function clsx(arr: (string | false | null | undefined | 0)[]): string[] {\n return arr.filter((item): item is string => !!item);\n}\n\n// check if it is a string array\nfunction isStringArray(value: unknown): value is string[] {\n return (\n // type-coverage:ignore-next-line\n Array.isArray(value) && value.every((item) => typeof item === \"string\")\n );\n}\n\n// check if it is Element which first child is text\nfunction isElementWithTextNode(node: ElementContent | undefined): node is ElementWithTextNode {\n return (\n node?.type === \"element\" &&\n node.children.length === 1 &&\n node.children[0].type === \"text\" &&\n \"value\" in node.children[0]\n );\n}\n\nfunction hasClassName(node: ElementContent | undefined, className: string): boolean {\n return (\n node?.type === \"element\" &&\n isStringArray(node.properties.className) &&\n node.properties.className.some((cls) => cls.includes(className))\n );\n}\n\n// match all common types of line breaks\nconst REGEX_LINE_BREAKS = /\\r?\\n|\\r/g;\nconst REGEX_LINE_BREAKS_IN_THE_BEGINNING = /^(\\r?\\n|\\r)+/;\n\n/**\n *\n * add line numbers to code blocks and allow highlighting of desired code lines\n *\n */\nconst plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {\n const settings = Object.assign(\n {},\n DEFAULT_SETTINGS,\n options,\n ) as PartiallyRequiredHighlightLinesOptions;\n\n /**\n *\n * check code element children need flattening or not\n *\n */\n function hasFlatteningNeed(code: Element): boolean {\n const elementContents = code.children;\n\n // type ElementContent = Comment | Element | Text\n for (const elemenContent of elementContents) {\n if (elemenContent.type === \"element\" && Boolean(elemenContent.children.length))\n if (elemenContent.children.some((ec) => ec.type === \"element\")) return true;\n }\n\n return false;\n }\n\n /**\n *\n * flatten deeper nodes into first level <span> and text, especially for languages like jsx, tsx\n * mutates the code, recursively\n * inspired from https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/src/highlight.js\n *\n */\n function flattenCodeTree(code: Element, className: string[] = []): ElementContent[] {\n const newTree: ElementContent[] = [];\n\n for (const elementContent of code.children) {\n if (elementContent.type === \"comment\" || elementContent.type === \"text\") {\n newTree.push(elementContent);\n } else {\n /* v8 ignore next -- @preserve */\n // @ts-expect-error className is different from other key of properties, and expected to be an array or undefined\n const classNames = className.concat(elementContent.properties.className || []);\n\n if (\n elementContent.children.length === 1 &&\n elementContent.children[0].type !== \"element\"\n ) {\n elementContent.properties.className = classNames;\n newTree.push(elementContent);\n } else {\n newTree.push(...flattenCodeTree(elementContent, classNames));\n }\n }\n }\n\n // Mutate the original code object\n code.children = newTree;\n return newTree;\n }\n\n /**\n *\n * construct the line element\n *\n */\n const createLine = (\n children: ElementContent[],\n lineNumber: number,\n directiveLineNumbering: boolean | number,\n directiveLineHighlighting: number[],\n ): Element => {\n const firstChild = children[0];\n const isAddition = hasClassName(firstChild, \"addition\");\n const isDeletion = hasClassName(firstChild, \"deletion\");\n\n return {\n type: \"element\",\n tagName: \"span\", // now it is always \"span\"\n children,\n properties: {\n className: clsx([\n \"code-line\",\n (directiveLineNumbering || directiveLineNumbering === 0) && \"numbered-code-line\",\n directiveLineHighlighting.includes(lineNumber) && \"highlighted-code-line\",\n isAddition && \"inserted\",\n isDeletion && \"deleted\",\n ]),\n dataLineNumber:\n typeof directiveLineNumbering === \"number\"\n ? directiveLineNumbering - 1 + lineNumber\n : directiveLineNumbering\n ? lineNumber\n : undefined,\n },\n };\n };\n\n /**\n *\n * handle elements which is multi line comment in code\n * mutates the code\n *\n */\n function handleMultiLineComments(code: Element): undefined {\n for (let index = 0; index < code.children.length; index++) {\n const replacement: ElementContent[] = [];\n\n const child = code.children[index];\n\n if (!isElementWithTextNode(child)) continue;\n\n const textNode = child.children[0];\n if (!REGEX_LINE_BREAKS.test(textNode.value)) continue;\n const comments = textNode.value.split(REGEX_LINE_BREAKS);\n\n for (let i = 0; i < comments.length; i++) {\n const newChild = structuredClone(child);\n newChild.children[0].value = comments[i];\n replacement.push(newChild);\n\n if (i < comments.length - 1) {\n replacement.push({ type: \"text\", value: \"\\n\" }); // eol\n }\n }\n\n code.children = [\n ...code.children.slice(0, index),\n ...replacement,\n ...code.children.slice(index + 1),\n ];\n }\n }\n\n /**\n *\n * handle eol characters in the beginning of the only first element\n * (because gutter function does not check the first element in the HAST whether contain eol at the beginning)\n * mutates the code\n *\n */\n function handleFirstElementContent(code: Element): undefined {\n const elementNode = code.children[0];\n if (!isElementWithTextNode(elementNode)) return;\n\n const textNode = elementNode.children[0];\n if (!REGEX_LINE_BREAKS_IN_THE_BEGINNING.test(textNode.value)) return;\n\n const match = REGEX_LINE_BREAKS_IN_THE_BEGINNING.exec(textNode.value);\n\n // classic V8 coverage false negative\n /* v8 ignore next -- @preserve */\n if (match) {\n code.children.unshift({ type: \"text\", value: match[0] });\n\n textNode.value = textNode.value.replace(REGEX_LINE_BREAKS_IN_THE_BEGINNING, \"\");\n }\n }\n\n /**\n *\n * finds the code lines from HAST of code element and costructs the lines\n * mutates the code\n *\n */\n function gutter(\n code: Element,\n {\n directiveLineNumbering,\n directiveLineHighlighting,\n directiveKeepOuterBlankLine,\n }: GutterOptions,\n ) {\n hasFlatteningNeed(code) && flattenCodeTree(code);\n\n handleFirstElementContent(code);\n handleMultiLineComments(code);\n\n const replacement: ElementContent[] = [];\n let start = 0;\n let startTextRemainder = \"\";\n let lineNumber = 0;\n\n for (let index = 0; index < code.children.length; index++) {\n const child = code.children[index];\n if (child.type !== \"text\") continue;\n\n let textStart = 0;\n const matches = Array.from(child.value.matchAll(REGEX_LINE_BREAKS));\n\n for (const [iteration, match] of matches.entries()) {\n // Nodes in this line. (current child (index) is exclusive)\n const line = code.children.slice(start, index);\n\n // Prepend text from a partial matched earlier text.\n if (startTextRemainder) {\n line.unshift({ type: \"text\", value: startTextRemainder });\n startTextRemainder = \"\";\n }\n\n // Append text from this text.\n if (match.index > textStart) {\n line.push({ type: \"text\", value: child.value.slice(textStart, match.index) });\n }\n\n const isFirstIteration = index === 0 && iteration === 0;\n const isLastIteration =\n index === code.children.length - 1 && iteration === matches.length - 1;\n\n if (isFirstIteration && !directiveKeepOuterBlankLine && line.length === 0) {\n // do nothing, intentionally\n // this happens in code fence if there is extra blank line at the beginning or\n // this happens in code html if there is eol right after <code> opening tag\n // replacement.push({ type: \"text\", value: match[0] }); // cancelled\n } else if (isLastIteration && !directiveKeepOuterBlankLine && line.length === 0) {\n // do nothing, intentionally\n // this happens always in code fence if there is extra blank line at the end\n } else {\n lineNumber++;\n\n replacement.push(\n createLine(line, lineNumber, directiveLineNumbering, directiveLineHighlighting),\n { type: \"text\", value: match[0] },\n );\n }\n\n start = index + 1;\n textStart = match.index + match[0].length;\n }\n\n // If we matched, make sure to not drop the text after the last line ending.\n if (start === index + 1) {\n startTextRemainder = child.value.slice(textStart);\n }\n }\n\n const remainingLine = code.children.slice(start);\n\n // Prepend text from a partial matched earlier text.\n if (startTextRemainder) {\n remainingLine.unshift({ type: \"text\", value: startTextRemainder });\n }\n\n if (remainingLine.length > 0) {\n if (remainingLine[0].type === \"text\" && remainingLine[0].value.trim() === \"\") {\n replacement.push(...remainingLine);\n } else {\n lineNumber++;\n\n replacement.push(\n createLine(\n remainingLine,\n lineNumber,\n directiveLineNumbering,\n directiveLineHighlighting,\n ),\n );\n }\n }\n\n // Replace children with new array.\n code.children = replacement;\n }\n\n /**\n *\n * get the programming language analyzing the classNames\n *\n */\n function getLanguage(classNames: string[] | undefined): string | undefined {\n if (!classNames) return;\n\n const isLanguageString = (element: string): boolean =>\n element.startsWith(\"language-\") || element.startsWith(\"lang-\");\n\n const languageString = classNames.find(isLanguageString);\n\n if (!languageString) return;\n\n const language = languageString.slice(languageString.indexOf(\"-\") + 1).toLowerCase();\n\n return language;\n }\n\n /**\n * Transform.\n *\n * @param {Root} tree\n * Tree.\n * @returns {undefined}\n * Nothing.\n */\n return (tree: Root): undefined => {\n visit(tree, \"element\", function (code, index, parent): VisitorResult {\n if (!parent || index === undefined || code.tagName !== \"code\") {\n return;\n }\n\n if (parent.type !== \"element\" || parent.tagName !== \"pre\") {\n return;\n }\n\n // for type narrowing\n /* v8 ignore if -- @preserve */\n if (\n !isStringArray(code.properties.className) &&\n code.properties.className !== undefined\n ) {\n return;\n }\n\n /** the part of correcting language and meta */\n\n let meta = (code.data?.meta || code.properties?.metastring || \"\").toLowerCase().trim();\n\n const language = getLanguage(code.properties.className);\n\n if (\n language &&\n (language.startsWith(\"{\") ||\n language.startsWith(\"showlinenumbers\") ||\n language.startsWith(\"nolinenumbers\") ||\n language.startsWith(\"keepouterblankline\"))\n ) {\n // add directives to meta\n meta = (language + \" \" + meta).trim();\n\n // remove classnames like hljs, lang-{1,3}, language-showLineNumbers, because of false positive\n code.properties.className = undefined;\n }\n\n /** the part of getting directives from code.properties.className */\n\n const keywords = [\"showlinenumbers\", \"nolinenumbers\", \"keepouterblankline\"];\n\n const directives = code.properties.className\n ?.map((cls) => cls.toLowerCase().replaceAll(\"-\", \"\"))\n .filter((cls) => keywords.includes(cls));\n\n /** the part of defining the line numbering directive */\n\n const directiveNoLineNumbers =\n meta.includes(\"nolinenumbers\") || Boolean(directives?.includes(\"nolinenumbers\"));\n\n const directiveShowLineNumbers =\n settings.showLineNumbers ||\n meta.includes(\"showlinenumbers\") ||\n Boolean(directives?.includes(\"showlinenumbers\"));\n\n let directiveLineNumbering: boolean | number = directiveNoLineNumbers\n ? false\n : directiveShowLineNumbers;\n\n // find the number where the line number starts, if exists\n const REGEX1 = /showlinenumbers=(?<start>\\d+)/;\n const start = REGEX1.exec(meta)?.groups?.start;\n\n if (!directiveNoLineNumbers && !isNaN(Number(start))) {\n directiveLineNumbering = Number(start);\n }\n\n // get the number where the line number starts, if exists\n const { dataStartNumbering } = code.properties;\n\n if (\n !directiveNoLineNumbers &&\n dataStartNumbering !== \"\" &&\n !isNaN(Number(dataStartNumbering))\n ) {\n directiveLineNumbering = Number(dataStartNumbering);\n }\n\n /** the part of defining the line highlighting directive */\n\n // find number range string within curly braces and parse it\n const directiveLineHighlighting: number[] = [];\n const REGEX2 = /{(?<lines>[\\d\\s,-]+)}/;\n const strLineNumbers = REGEX2.exec(meta)?.groups?.lines?.replace(/\\s/g, \"\");\n\n if (strLineNumbers) {\n const range = rangeParser(strLineNumbers);\n directiveLineHighlighting.push(...range);\n }\n\n // get number range string within properties and parse it\n const { dataHighlightLines } = code.properties;\n\n if (dataHighlightLines) {\n const range = rangeParser(dataHighlightLines.replace(/\\s/g, \"\"));\n directiveLineHighlighting.push(...range);\n }\n\n /** the part of defining the directive for outer blank lines */\n\n // find the directive for trimming blank lines\n const directiveKeepOuterBlankLine =\n settings.keepOuterBlankLine ||\n /keepouterblankline/.test(meta) ||\n Boolean(directives?.includes(\"keepouterblankline\"));\n\n /** the part of cleaning the code properties */\n\n const classnamesFiltered = code.properties.className?.filter(\n (cls) => !keywords.includes(cls.toLowerCase().replaceAll(\"-\", \"\")),\n );\n\n code.properties.className = classnamesFiltered?.length ? classnamesFiltered : undefined;\n\n [\"dataStartNumbering\", \"dataHighlightLines\", \"metastring\"].forEach((property) => {\n if (property in code.properties) code.properties[property] = undefined;\n });\n\n /** the part of main logic */\n\n // if nothing to do for line numbering or line highlihting, just return;\n if (directiveLineNumbering === false && directiveLineHighlighting.length === 0) {\n return;\n }\n\n // add container for each line mutating the code element\n gutter(code, {\n directiveLineNumbering,\n directiveLineHighlighting,\n directiveKeepOuterBlankLine,\n });\n });\n };\n};\n\nexport default plugin;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../src/index.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rehype-highlight-code-lines",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Rehype plugin to add line numbers to code blocks and allow highlighting of desired code lines",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
9
15
|
"scripts": {
|
|
10
16
|
"build": "rimraf dist && tsc --build && type-coverage",
|
|
11
17
|
"format": "npm run prettier && npm run lint",
|
|
12
18
|
"prettier": "prettier --write .",
|
|
13
19
|
"lint": "eslint .",
|
|
14
|
-
"test": "vitest
|
|
20
|
+
"test": "vitest run",
|
|
15
21
|
"test:watch": "vitest",
|
|
16
22
|
"test:file1": "vitest test.md.spec.ts",
|
|
17
23
|
"test:file2": "vitest test.html.spec.ts",
|
|
@@ -19,13 +25,12 @@
|
|
|
19
25
|
"test:file4": "vitest from-rehype-highlight/test.rhcl2.spec.ts",
|
|
20
26
|
"test:file5": "vitest test.raw.spec.ts",
|
|
21
27
|
"test:file6": "vitest test.debug.spec.ts",
|
|
28
|
+
"test-coverage": "vitest run --coverage",
|
|
22
29
|
"prepack": "npm run build",
|
|
23
|
-
"prepublishOnly": "npm run
|
|
24
|
-
"test-coverage": "vitest run --coverage"
|
|
30
|
+
"prepublishOnly": "npm run format && npm run test-coverage"
|
|
25
31
|
},
|
|
26
32
|
"files": [
|
|
27
33
|
"dist/",
|
|
28
|
-
"src/",
|
|
29
34
|
"LICENSE",
|
|
30
35
|
"README.md"
|
|
31
36
|
],
|
|
@@ -56,16 +61,17 @@
|
|
|
56
61
|
"url": "https://github.com/ipikuka/rehype-highlight-code-lines/issues"
|
|
57
62
|
},
|
|
58
63
|
"devDependencies": {
|
|
59
|
-
"@eslint/js": "^
|
|
64
|
+
"@eslint/js": "^10.0.1",
|
|
60
65
|
"@types/dedent": "^0.7.2",
|
|
61
|
-
"@types/node": "^24.
|
|
62
|
-
"@vitest/coverage-v8": "^
|
|
63
|
-
"@vitest/eslint-plugin": "^1.
|
|
64
|
-
"dedent": "^1.7.
|
|
65
|
-
"eslint": "^
|
|
66
|
+
"@types/node": "^24.10.13",
|
|
67
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
68
|
+
"@vitest/eslint-plugin": "^1.6.9",
|
|
69
|
+
"dedent": "^1.7.1",
|
|
70
|
+
"eslint": "^10.0.0",
|
|
66
71
|
"eslint-config-prettier": "^10.1.8",
|
|
67
|
-
"eslint-plugin-prettier": "^5.5.
|
|
68
|
-
"
|
|
72
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
73
|
+
"globals": "^17.3.0",
|
|
74
|
+
"prettier": "^3.8.1",
|
|
69
75
|
"rehype": "^13.0.2",
|
|
70
76
|
"rehype-highlight": "^7.0.2",
|
|
71
77
|
"rehype-parse": "^9.0.1",
|
|
@@ -74,19 +80,19 @@
|
|
|
74
80
|
"remark-gfm": "^4.0.1",
|
|
75
81
|
"remark-parse": "^11.0.0",
|
|
76
82
|
"remark-rehype": "^11.1.2",
|
|
77
|
-
"rimraf": "^6.
|
|
83
|
+
"rimraf": "^6.1.3",
|
|
78
84
|
"type-coverage": "^2.29.7",
|
|
79
|
-
"typescript": "^5.9.
|
|
80
|
-
"typescript-eslint": "^8.
|
|
85
|
+
"typescript": "^5.9.3",
|
|
86
|
+
"typescript-eslint": "^8.56.0",
|
|
81
87
|
"unified": "^11.0.5",
|
|
82
88
|
"unist-util-remove-position": "^5.0.0",
|
|
83
89
|
"vfile": "^6.0.3",
|
|
84
|
-
"vitest": "^
|
|
90
|
+
"vitest": "^4.0.18"
|
|
85
91
|
},
|
|
86
92
|
"dependencies": {
|
|
87
93
|
"@types/hast": "^3.0.4",
|
|
88
94
|
"parse-numeric-range": "^1.3.0",
|
|
89
|
-
"unist-util-visit": "^5.
|
|
95
|
+
"unist-util-visit": "^5.1.0"
|
|
90
96
|
},
|
|
91
97
|
"peerDependencies": {
|
|
92
98
|
"unified": "^11"
|
package/dist/esm/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"root":["../../src/index.ts"],"version":"5.9.2"}
|
package/src/index.ts
DELETED
|
@@ -1,506 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from "unified";
|
|
2
|
-
import type { Root, Element, Text, ElementContent } from "hast";
|
|
3
|
-
import { visit, type VisitorResult } from "unist-util-visit";
|
|
4
|
-
import rangeParser from "parse-numeric-range";
|
|
5
|
-
|
|
6
|
-
type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
|
7
|
-
|
|
8
|
-
type PartiallyRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
|
|
9
|
-
|
|
10
|
-
declare module "hast" {
|
|
11
|
-
interface Data {
|
|
12
|
-
meta?: string;
|
|
13
|
-
}
|
|
14
|
-
interface Properties {
|
|
15
|
-
dataStartNumbering?: string;
|
|
16
|
-
dataHighlightLines?: string;
|
|
17
|
-
metastring?: string | null | undefined;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
type ElementWithTextNode = Element & {
|
|
22
|
-
children: [Text];
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type HighlightLinesOptions = {
|
|
26
|
-
showLineNumbers?: boolean;
|
|
27
|
-
keepOuterBlankLine?: boolean;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const DEFAULT_SETTINGS: HighlightLinesOptions = {
|
|
31
|
-
showLineNumbers: false,
|
|
32
|
-
keepOuterBlankLine: false,
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
type PartiallyRequiredHighlightLinesOptions = Prettify<
|
|
36
|
-
PartiallyRequired<HighlightLinesOptions, "showLineNumbers">
|
|
37
|
-
>;
|
|
38
|
-
|
|
39
|
-
type GutterOptions = {
|
|
40
|
-
directiveLineNumbering: boolean | number;
|
|
41
|
-
directiveLineHighlighting: number[];
|
|
42
|
-
directiveKeepOuterBlankLine: boolean;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// a simple util for our use case, like clsx package
|
|
46
|
-
export function clsx(arr: (string | false | null | undefined | 0)[]): string[] {
|
|
47
|
-
return arr.filter((item): item is string => !!item);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// check if it is a string array
|
|
51
|
-
function isStringArray(value: unknown): value is string[] {
|
|
52
|
-
return (
|
|
53
|
-
// type-coverage:ignore-next-line
|
|
54
|
-
Array.isArray(value) && value.every((item) => typeof item === "string")
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// check if it is Element which first child is text
|
|
59
|
-
function isElementWithTextNode(node: ElementContent | undefined): node is ElementWithTextNode {
|
|
60
|
-
return (
|
|
61
|
-
node?.type === "element" &&
|
|
62
|
-
node.children.length === 1 &&
|
|
63
|
-
node.children[0].type === "text" &&
|
|
64
|
-
"value" in node.children[0]
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function hasClassName(node: ElementContent | undefined, className: string): boolean {
|
|
69
|
-
return (
|
|
70
|
-
node?.type === "element" &&
|
|
71
|
-
isStringArray(node.properties.className) &&
|
|
72
|
-
node.properties.className.some((cls) => cls.includes(className))
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// match all common types of line breaks
|
|
77
|
-
const REGEX_LINE_BREAKS = /\r?\n|\r/g;
|
|
78
|
-
const REGEX_LINE_BREAKS_IN_THE_BEGINNING = /^(\r?\n|\r)+/;
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
*
|
|
82
|
-
* add line numbers to code blocks and allow highlighting of desired code lines
|
|
83
|
-
*
|
|
84
|
-
*/
|
|
85
|
-
const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
86
|
-
const settings = Object.assign(
|
|
87
|
-
{},
|
|
88
|
-
DEFAULT_SETTINGS,
|
|
89
|
-
options,
|
|
90
|
-
) as PartiallyRequiredHighlightLinesOptions;
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
* check code element children need flattening or not
|
|
95
|
-
*
|
|
96
|
-
*/
|
|
97
|
-
function hasFlatteningNeed(code: Element): boolean {
|
|
98
|
-
const elementContents = code.children;
|
|
99
|
-
|
|
100
|
-
// type ElementContent = Comment | Element | Text
|
|
101
|
-
for (const elemenContent of elementContents) {
|
|
102
|
-
if (elemenContent.type === "element" && Boolean(elemenContent.children.length))
|
|
103
|
-
if (elemenContent.children.some((ec) => ec.type === "element")) return true;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
*
|
|
111
|
-
* flatten deeper nodes into first level <span> and text, especially for languages like jsx, tsx
|
|
112
|
-
* mutates the code, recursively
|
|
113
|
-
* inspired from https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/src/highlight.js
|
|
114
|
-
*
|
|
115
|
-
*/
|
|
116
|
-
function flattenCodeTree(code: Element, className: string[] = []): ElementContent[] {
|
|
117
|
-
const newTree: ElementContent[] = [];
|
|
118
|
-
|
|
119
|
-
for (const elementContent of code.children) {
|
|
120
|
-
if (elementContent.type === "comment" || elementContent.type === "text") {
|
|
121
|
-
newTree.push(elementContent);
|
|
122
|
-
} else {
|
|
123
|
-
// @ts-expect-error className is different from other key of properties, and expected to be an array or undefined
|
|
124
|
-
// /* v8 ignore next */
|
|
125
|
-
const classNames = className.concat(elementContent.properties.className || []);
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
elementContent.children.length === 1 &&
|
|
129
|
-
elementContent.children[0].type !== "element"
|
|
130
|
-
) {
|
|
131
|
-
elementContent.properties.className = classNames;
|
|
132
|
-
newTree.push(elementContent);
|
|
133
|
-
} else {
|
|
134
|
-
newTree.push(...flattenCodeTree(elementContent, classNames));
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Mutate the original code object
|
|
140
|
-
code.children = newTree;
|
|
141
|
-
return newTree;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
*
|
|
146
|
-
* construct the line element
|
|
147
|
-
*
|
|
148
|
-
*/
|
|
149
|
-
const createLine = (
|
|
150
|
-
children: ElementContent[],
|
|
151
|
-
lineNumber: number,
|
|
152
|
-
directiveLineNumbering: boolean | number,
|
|
153
|
-
directiveLineHighlighting: number[],
|
|
154
|
-
): Element => {
|
|
155
|
-
const firstChild = children[0];
|
|
156
|
-
const isAddition = hasClassName(firstChild, "addition");
|
|
157
|
-
const isDeletion = hasClassName(firstChild, "deletion");
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
type: "element",
|
|
161
|
-
tagName: "span", // now it is always "span"
|
|
162
|
-
children,
|
|
163
|
-
properties: {
|
|
164
|
-
className: clsx([
|
|
165
|
-
"code-line",
|
|
166
|
-
(directiveLineNumbering || directiveLineNumbering === 0) && "numbered-code-line",
|
|
167
|
-
directiveLineHighlighting.includes(lineNumber) && "highlighted-code-line",
|
|
168
|
-
isAddition && "inserted",
|
|
169
|
-
isDeletion && "deleted",
|
|
170
|
-
]),
|
|
171
|
-
dataLineNumber:
|
|
172
|
-
typeof directiveLineNumbering === "number"
|
|
173
|
-
? directiveLineNumbering - 1 + lineNumber
|
|
174
|
-
: directiveLineNumbering
|
|
175
|
-
? lineNumber
|
|
176
|
-
: undefined,
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
*
|
|
183
|
-
* handle elements which is multi line comment in code
|
|
184
|
-
* mutates the code
|
|
185
|
-
*
|
|
186
|
-
*/
|
|
187
|
-
function handleMultiLineComments(code: Element): undefined {
|
|
188
|
-
for (let index = 0; index < code.children.length; index++) {
|
|
189
|
-
const replacement: ElementContent[] = [];
|
|
190
|
-
|
|
191
|
-
const child = code.children[index];
|
|
192
|
-
|
|
193
|
-
if (!isElementWithTextNode(child)) continue;
|
|
194
|
-
|
|
195
|
-
const textNode = child.children[0];
|
|
196
|
-
if (!REGEX_LINE_BREAKS.test(textNode.value)) continue;
|
|
197
|
-
const comments = textNode.value.split(REGEX_LINE_BREAKS);
|
|
198
|
-
|
|
199
|
-
for (let i = 0; i < comments.length; i++) {
|
|
200
|
-
const newChild = structuredClone(child);
|
|
201
|
-
newChild.children[0].value = comments[i];
|
|
202
|
-
replacement.push(newChild);
|
|
203
|
-
|
|
204
|
-
if (i < comments.length - 1) {
|
|
205
|
-
replacement.push({ type: "text", value: "\n" }); // eol
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
code.children = [
|
|
210
|
-
...code.children.slice(0, index),
|
|
211
|
-
...replacement,
|
|
212
|
-
...code.children.slice(index + 1),
|
|
213
|
-
];
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
*
|
|
219
|
-
* handle eol characters in the beginning of the only first element
|
|
220
|
-
* (because gutter function does not check the first element in the HAST whether contain eol at the beginning)
|
|
221
|
-
* mutates the code
|
|
222
|
-
*
|
|
223
|
-
*/
|
|
224
|
-
function handleFirstElementContent(code: Element): undefined {
|
|
225
|
-
const elementNode = code.children[0];
|
|
226
|
-
if (!isElementWithTextNode(elementNode)) return;
|
|
227
|
-
|
|
228
|
-
const textNode = elementNode.children[0];
|
|
229
|
-
if (!REGEX_LINE_BREAKS_IN_THE_BEGINNING.test(textNode.value)) return;
|
|
230
|
-
|
|
231
|
-
const match = REGEX_LINE_BREAKS_IN_THE_BEGINNING.exec(textNode.value);
|
|
232
|
-
|
|
233
|
-
if (match) {
|
|
234
|
-
code.children.unshift({ type: "text", value: match[0] });
|
|
235
|
-
|
|
236
|
-
textNode.value = textNode.value.replace(REGEX_LINE_BREAKS_IN_THE_BEGINNING, "");
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
*
|
|
242
|
-
* finds the code lines from HAST of code element and costructs the lines
|
|
243
|
-
* mutates the code
|
|
244
|
-
*
|
|
245
|
-
*/
|
|
246
|
-
function gutter(
|
|
247
|
-
code: Element,
|
|
248
|
-
{
|
|
249
|
-
directiveLineNumbering,
|
|
250
|
-
directiveLineHighlighting,
|
|
251
|
-
directiveKeepOuterBlankLine,
|
|
252
|
-
}: GutterOptions,
|
|
253
|
-
) {
|
|
254
|
-
hasFlatteningNeed(code) && flattenCodeTree(code);
|
|
255
|
-
|
|
256
|
-
handleFirstElementContent(code);
|
|
257
|
-
handleMultiLineComments(code);
|
|
258
|
-
|
|
259
|
-
const replacement: ElementContent[] = [];
|
|
260
|
-
let start = 0;
|
|
261
|
-
let startTextRemainder = "";
|
|
262
|
-
let lineNumber = 0;
|
|
263
|
-
|
|
264
|
-
for (let index = 0; index < code.children.length; index++) {
|
|
265
|
-
const child = code.children[index];
|
|
266
|
-
if (child.type !== "text") continue;
|
|
267
|
-
|
|
268
|
-
let textStart = 0;
|
|
269
|
-
const matches = Array.from(child.value.matchAll(REGEX_LINE_BREAKS));
|
|
270
|
-
|
|
271
|
-
for (const [iteration, match] of matches.entries()) {
|
|
272
|
-
// Nodes in this line. (current child (index) is exclusive)
|
|
273
|
-
const line = code.children.slice(start, index);
|
|
274
|
-
|
|
275
|
-
// Prepend text from a partial matched earlier text.
|
|
276
|
-
if (startTextRemainder) {
|
|
277
|
-
line.unshift({ type: "text", value: startTextRemainder });
|
|
278
|
-
startTextRemainder = "";
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// Append text from this text.
|
|
282
|
-
if (match.index > textStart) {
|
|
283
|
-
line.push({ type: "text", value: child.value.slice(textStart, match.index) });
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const isFirstIteration = index === 0 && iteration === 0;
|
|
287
|
-
const isLastIteration =
|
|
288
|
-
index === code.children.length - 1 && iteration === matches.length - 1;
|
|
289
|
-
|
|
290
|
-
if (isFirstIteration && !directiveKeepOuterBlankLine && line.length === 0) {
|
|
291
|
-
// do nothing, intentionally
|
|
292
|
-
// this happens in code fence if there is extra blank line at the beginning or
|
|
293
|
-
// this happens in code html if there is eol right after <code> opening tag
|
|
294
|
-
// replacement.push({ type: "text", value: match[0] }); // cancelled
|
|
295
|
-
} else if (isLastIteration && !directiveKeepOuterBlankLine && line.length === 0) {
|
|
296
|
-
// do nothing, intentionally
|
|
297
|
-
// this happens always in code fence if there is extra blank line at the end
|
|
298
|
-
} else {
|
|
299
|
-
replacement.push(
|
|
300
|
-
createLine(line, ++lineNumber, directiveLineNumbering, directiveLineHighlighting),
|
|
301
|
-
{ type: "text", value: match[0] },
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
start = index + 1;
|
|
306
|
-
textStart = match.index + match[0].length;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// If we matched, make sure to not drop the text after the last line ending.
|
|
310
|
-
if (start === index + 1) {
|
|
311
|
-
startTextRemainder = child.value.slice(textStart);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const remainingLine = code.children.slice(start);
|
|
316
|
-
|
|
317
|
-
// Prepend text from a partial matched earlier text.
|
|
318
|
-
if (startTextRemainder) {
|
|
319
|
-
remainingLine.unshift({ type: "text", value: startTextRemainder });
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if (remainingLine.length > 0) {
|
|
323
|
-
if (remainingLine[0].type === "text" && remainingLine[0].value.trim() === "") {
|
|
324
|
-
replacement.push(...remainingLine);
|
|
325
|
-
} else {
|
|
326
|
-
replacement.push(
|
|
327
|
-
createLine(
|
|
328
|
-
remainingLine,
|
|
329
|
-
++lineNumber,
|
|
330
|
-
directiveLineNumbering,
|
|
331
|
-
directiveLineHighlighting,
|
|
332
|
-
),
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// Replace children with new array.
|
|
338
|
-
code.children = replacement;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
*
|
|
343
|
-
* get the programming language analyzing the classNames
|
|
344
|
-
*
|
|
345
|
-
*/
|
|
346
|
-
function getLanguage(classNames: string[] | undefined): string | undefined {
|
|
347
|
-
if (!classNames) return;
|
|
348
|
-
|
|
349
|
-
const isLanguageString = (element: string): boolean =>
|
|
350
|
-
element.startsWith("language-") || element.startsWith("lang-");
|
|
351
|
-
|
|
352
|
-
const languageString = classNames.find(isLanguageString);
|
|
353
|
-
|
|
354
|
-
if (!languageString) return;
|
|
355
|
-
|
|
356
|
-
const language = languageString.slice(languageString.indexOf("-") + 1).toLowerCase();
|
|
357
|
-
|
|
358
|
-
return language;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Transform.
|
|
363
|
-
*
|
|
364
|
-
* @param {Root} tree
|
|
365
|
-
* Tree.
|
|
366
|
-
* @returns {undefined}
|
|
367
|
-
* Nothing.
|
|
368
|
-
*/
|
|
369
|
-
return (tree: Root): undefined => {
|
|
370
|
-
visit(tree, "element", function (code, index, parent): VisitorResult {
|
|
371
|
-
if (!parent || index === undefined || code.tagName !== "code") {
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
if (parent.type !== "element" || parent.tagName !== "pre") {
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// for type narrowing
|
|
380
|
-
if (
|
|
381
|
-
!isStringArray(code.properties.className) &&
|
|
382
|
-
code.properties.className !== undefined
|
|
383
|
-
/* v8 ignore next 3 */
|
|
384
|
-
) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/** the part of correcting language and meta */
|
|
389
|
-
|
|
390
|
-
let meta = (code.data?.meta || code.properties?.metastring || "").toLowerCase().trim();
|
|
391
|
-
|
|
392
|
-
const language = getLanguage(code.properties.className);
|
|
393
|
-
|
|
394
|
-
if (
|
|
395
|
-
language &&
|
|
396
|
-
(language.startsWith("{") ||
|
|
397
|
-
language.startsWith("showlinenumbers") ||
|
|
398
|
-
language.startsWith("nolinenumbers") ||
|
|
399
|
-
language.startsWith("keepouterblankline"))
|
|
400
|
-
) {
|
|
401
|
-
// add directives to meta
|
|
402
|
-
meta = (language + " " + meta).trim();
|
|
403
|
-
|
|
404
|
-
// remove classnames like hljs, lang-{1,3}, language-showLineNumbers, because of false positive
|
|
405
|
-
code.properties.className = undefined;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/** the part of getting directives from code.properties.className */
|
|
409
|
-
|
|
410
|
-
const keywords = ["showlinenumbers", "nolinenumbers", "keepouterblankline"];
|
|
411
|
-
|
|
412
|
-
const directives = code.properties.className
|
|
413
|
-
?.map((cls) => cls.toLowerCase().replaceAll("-", ""))
|
|
414
|
-
.filter((cls) => keywords.includes(cls));
|
|
415
|
-
|
|
416
|
-
/** the part of defining the line numbering directive */
|
|
417
|
-
|
|
418
|
-
const directiveNoLineNumbers =
|
|
419
|
-
meta.includes("nolinenumbers") || Boolean(directives?.includes("nolinenumbers"));
|
|
420
|
-
|
|
421
|
-
const directiveShowLineNumbers =
|
|
422
|
-
settings.showLineNumbers ||
|
|
423
|
-
meta.includes("showlinenumbers") ||
|
|
424
|
-
Boolean(directives?.includes("showlinenumbers"));
|
|
425
|
-
|
|
426
|
-
let directiveLineNumbering: boolean | number = directiveNoLineNumbers
|
|
427
|
-
? false
|
|
428
|
-
: directiveShowLineNumbers;
|
|
429
|
-
|
|
430
|
-
// find the number where the line number starts, if exists
|
|
431
|
-
const REGEX1 = /showlinenumbers=(?<start>\d+)/;
|
|
432
|
-
const start = REGEX1.exec(meta)?.groups?.start;
|
|
433
|
-
|
|
434
|
-
if (!directiveNoLineNumbers && !isNaN(Number(start))) {
|
|
435
|
-
directiveLineNumbering = Number(start);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// get the number where the line number starts, if exists
|
|
439
|
-
const { dataStartNumbering } = code.properties;
|
|
440
|
-
|
|
441
|
-
if (
|
|
442
|
-
!directiveNoLineNumbers &&
|
|
443
|
-
dataStartNumbering !== "" &&
|
|
444
|
-
!isNaN(Number(dataStartNumbering))
|
|
445
|
-
) {
|
|
446
|
-
directiveLineNumbering = Number(dataStartNumbering);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/** the part of defining the line highlighting directive */
|
|
450
|
-
|
|
451
|
-
// find number range string within curly braces and parse it
|
|
452
|
-
const directiveLineHighlighting: number[] = [];
|
|
453
|
-
const REGEX2 = /{(?<lines>[\d\s,-]+)}/;
|
|
454
|
-
const strLineNumbers = REGEX2.exec(meta)?.groups?.lines?.replace(/\s/g, "");
|
|
455
|
-
|
|
456
|
-
if (strLineNumbers) {
|
|
457
|
-
const range = rangeParser(strLineNumbers);
|
|
458
|
-
directiveLineHighlighting.push(...range);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// get number range string within properties and parse it
|
|
462
|
-
const { dataHighlightLines } = code.properties;
|
|
463
|
-
|
|
464
|
-
if (dataHighlightLines) {
|
|
465
|
-
const range = rangeParser(dataHighlightLines.replace(/\s/g, ""));
|
|
466
|
-
directiveLineHighlighting.push(...range);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
/** the part of defining the directive for outer blank lines */
|
|
470
|
-
|
|
471
|
-
// find the directive for trimming blank lines
|
|
472
|
-
const directiveKeepOuterBlankLine =
|
|
473
|
-
settings.keepOuterBlankLine ||
|
|
474
|
-
/keepouterblankline/.test(meta) ||
|
|
475
|
-
Boolean(directives?.includes("keepouterblankline"));
|
|
476
|
-
|
|
477
|
-
/** the part of cleaning the code properties */
|
|
478
|
-
|
|
479
|
-
const classnamesFiltered = code.properties.className?.filter(
|
|
480
|
-
(cls) => !keywords.includes(cls.toLowerCase().replaceAll("-", "")),
|
|
481
|
-
);
|
|
482
|
-
|
|
483
|
-
code.properties.className = classnamesFiltered?.length ? classnamesFiltered : undefined;
|
|
484
|
-
|
|
485
|
-
["dataStartNumbering", "dataHighlightLines", "metastring"].forEach((property) => {
|
|
486
|
-
if (property in code.properties) code.properties[property] = undefined;
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
/** the part of main logic */
|
|
490
|
-
|
|
491
|
-
// if nothing to do for line numbering or line highlihting, just return;
|
|
492
|
-
if (directiveLineNumbering === false && directiveLineHighlighting.length === 0) {
|
|
493
|
-
return;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
// add container for each line mutating the code element
|
|
497
|
-
gutter(code, {
|
|
498
|
-
directiveLineNumbering,
|
|
499
|
-
directiveLineHighlighting,
|
|
500
|
-
directiveKeepOuterBlankLine,
|
|
501
|
-
});
|
|
502
|
-
});
|
|
503
|
-
};
|
|
504
|
-
};
|
|
505
|
-
|
|
506
|
-
export default plugin;
|