rehype-highlight-code-lines 1.0.5 → 1.0.8
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 +39 -4
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +153 -63
- package/dist/esm/index.js.map +1 -1
- package/package.json +14 -8
- package/src/index.ts +202 -99
package/README.md
CHANGED
|
@@ -140,6 +140,8 @@ All options are **optional** and have **default values**.
|
|
|
140
140
|
```typescript
|
|
141
141
|
type HighlightLinesOptions = {
|
|
142
142
|
showLineNumbers?: boolean; // default is "false"
|
|
143
|
+
lineContainerTagName?: "span" | "div"; // deprecated, always span
|
|
144
|
+
trimBlankLines?: boolean; // default is "false"
|
|
143
145
|
};
|
|
144
146
|
|
|
145
147
|
use(rehypeHighlightLines, HighlightLinesOptions);
|
|
@@ -173,20 +175,53 @@ Sometimes you may want to start the line numbering from a specific number. In th
|
|
|
173
175
|
|
|
174
176
|
**\`\`\`showLineNumbers=8**
|
|
175
177
|
|
|
176
|
-
#### `lineContainerTagName`
|
|
178
|
+
#### `lineContainerTagName` (Deprecated)
|
|
177
179
|
|
|
178
|
-
**It is
|
|
180
|
+
**It is marked as `@deprecated` and will be removed in the next versions.
|
|
179
181
|
|
|
180
|
-
It was a **union**
|
|
182
|
+
It was a **union** option which was **"div" | "span"** for providing custom HTML tag name for code lines.
|
|
181
183
|
|
|
182
184
|
By default, it is `span` which is **inline** level container. If you set it as `div`, the container will still be `span` after deprecation.
|
|
183
185
|
|
|
184
186
|
```javascript
|
|
185
187
|
use(rehypeHighlightLines, {
|
|
186
|
-
lineContainerTagName: "div", // @deprecated, always "span"
|
|
188
|
+
lineContainerTagName: "div", // @deprecated, effectless, always "span"
|
|
187
189
|
});
|
|
188
190
|
```
|
|
189
191
|
|
|
192
|
+
#### `trimBlankLines`
|
|
193
|
+
|
|
194
|
+
It is a **boolean** option. It is designed to delete one blank/empty line at the beginning and one at the end of the code block, if happened due to html parsing `<pre><code /></pre>`.
|
|
195
|
+
|
|
196
|
+
By default, it is `false`.
|
|
197
|
+
|
|
198
|
+
Let's assume you want to highlight `pre`, and `code` element in markdown (not code fence).
|
|
199
|
+
|
|
200
|
+
```markdown
|
|
201
|
+
Here is markdown content
|
|
202
|
+
|
|
203
|
+
<pre><code class="language-javascript">
|
|
204
|
+
console.log("rehype-highlight-code-lines");
|
|
205
|
+
</code></pre>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
For above markdown, the parsed result (for example via `rehype-parse` and `rehype-stringfy`) is going to contain empty/blank code lines due to nature of `pre` preserving whitespaces. In order to prevent having unintentionally blank lines, use the option `trimBlankLines`.
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
use(rehypeHighlightLines, {
|
|
212
|
+
trimBlankLines: true,
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Actually, the trimming could have been the default behaviour. However, some developers may intentionally include empty lines at the beginning and at the end in code fences for specific reasons and may want to preserve them.
|
|
217
|
+
````markdown
|
|
218
|
+
```javascript
|
|
219
|
+
|
|
220
|
+
console.log("rehype-highlight-code-lines");
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
````
|
|
224
|
+
|
|
190
225
|
### Examples:
|
|
191
226
|
|
|
192
227
|
```typescript
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { Plugin } from "unified";
|
|
2
2
|
import type { Root } from "hast";
|
|
3
|
+
declare module "hast" {
|
|
4
|
+
interface Data {
|
|
5
|
+
meta?: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
3
8
|
export type HighlightLinesOptions = {
|
|
4
9
|
showLineNumbers?: boolean;
|
|
5
10
|
/**
|
|
@@ -7,6 +12,7 @@ export type HighlightLinesOptions = {
|
|
|
7
12
|
* will be removed in the next versions
|
|
8
13
|
*/
|
|
9
14
|
lineContainerTagName?: "div" | "span";
|
|
15
|
+
trimBlankLines?: boolean;
|
|
10
16
|
};
|
|
11
17
|
export declare function clsx(arr: (string | false | null | undefined | 0)[]): string[];
|
|
12
18
|
/**
|
package/dist/esm/index.js
CHANGED
|
@@ -3,11 +3,30 @@ import rangeParser from "parse-numeric-range";
|
|
|
3
3
|
const DEFAULT_SETTINGS = {
|
|
4
4
|
showLineNumbers: false,
|
|
5
5
|
lineContainerTagName: "span",
|
|
6
|
+
trimBlankLines: false,
|
|
6
7
|
};
|
|
7
8
|
// a simple util for our use case, like clsx package
|
|
8
9
|
export function clsx(arr) {
|
|
9
10
|
return arr.filter((item) => !!item);
|
|
10
11
|
}
|
|
12
|
+
// check if it is string array
|
|
13
|
+
function isStringArray(value) {
|
|
14
|
+
return (
|
|
15
|
+
// type-coverage:ignore-next-line
|
|
16
|
+
Array.isArray(value) && value.every((item) => typeof item === "string"));
|
|
17
|
+
}
|
|
18
|
+
// check if it is Element which first child is text
|
|
19
|
+
function isElementWithTextNode(node) {
|
|
20
|
+
return (node?.type === "element" && node.children[0]?.type === "text" && "value" in node.children[0]);
|
|
21
|
+
}
|
|
22
|
+
function hasClassName(node, className) {
|
|
23
|
+
return (node?.type === "element" &&
|
|
24
|
+
isStringArray(node.properties.className) &&
|
|
25
|
+
node.properties.className.some((cls) => cls.includes(className)));
|
|
26
|
+
}
|
|
27
|
+
// match all common types of line breaks
|
|
28
|
+
const REGEX_LINE_BREAKS = /\r?\n|\r/g;
|
|
29
|
+
const REGEX_LINE_BREAKS_IN_THE_BEGINNING = /^(\r?\n|\r)+/;
|
|
11
30
|
/**
|
|
12
31
|
*
|
|
13
32
|
* add line numbers to code blocks and allow highlighting of desired code lines
|
|
@@ -20,19 +39,20 @@ const plugin = (options) => {
|
|
|
20
39
|
* check code element children need flattening or not
|
|
21
40
|
*
|
|
22
41
|
*/
|
|
23
|
-
function
|
|
42
|
+
function hasFlatteningNeed(code) {
|
|
24
43
|
const elementContents = code.children;
|
|
25
44
|
// type ElementContent = Comment | Element | Text
|
|
26
45
|
for (const elemenContent of elementContents) {
|
|
27
|
-
if (elemenContent.type === "element")
|
|
28
|
-
if (elemenContent.children.
|
|
46
|
+
if (elemenContent.type === "element" && Boolean(elemenContent.children.length))
|
|
47
|
+
if (elemenContent.children.some((ec) => ec.type === "element"))
|
|
29
48
|
return true;
|
|
30
49
|
}
|
|
31
50
|
return false;
|
|
32
51
|
}
|
|
33
52
|
/**
|
|
34
53
|
*
|
|
35
|
-
* flatten
|
|
54
|
+
* flatten deeper nodes into first level <span> and text, especially for languages like jsx, tsx
|
|
55
|
+
* mutates the code, recursively
|
|
36
56
|
* inspired from https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/src/highlight.js
|
|
37
57
|
*
|
|
38
58
|
*/
|
|
@@ -65,14 +85,10 @@ const plugin = (options) => {
|
|
|
65
85
|
* construct the line element
|
|
66
86
|
*
|
|
67
87
|
*/
|
|
68
|
-
const createLine = (children, lineNumber,
|
|
88
|
+
const createLine = (children, lineNumber, directiveShowLineNumbers, directiveHighlightLines) => {
|
|
69
89
|
const firstChild = children[0];
|
|
70
|
-
const isAddition = firstChild
|
|
71
|
-
|
|
72
|
-
firstChild.properties.className.some((cls) => typeof cls === "string" && cls.includes("addition"));
|
|
73
|
-
const isDeletion = firstChild?.type === "element" &&
|
|
74
|
-
Array.isArray(firstChild.properties.className) &&
|
|
75
|
-
firstChild.properties.className.some((cls) => typeof cls === "string" && cls.includes("deletion"));
|
|
90
|
+
const isAddition = hasClassName(firstChild, "addition");
|
|
91
|
+
const isDeletion = hasClassName(firstChild, "deletion");
|
|
76
92
|
return {
|
|
77
93
|
type: "element",
|
|
78
94
|
tagName: "span", // now it is always "span"
|
|
@@ -81,40 +97,110 @@ const plugin = (options) => {
|
|
|
81
97
|
className: clsx([
|
|
82
98
|
"code-line",
|
|
83
99
|
directiveShowLineNumbers && "numbered-code-line",
|
|
84
|
-
|
|
100
|
+
directiveHighlightLines.includes(lineNumber) && "highlighted-code-line",
|
|
85
101
|
isAddition && "inserted",
|
|
86
102
|
isDeletion && "deleted",
|
|
87
103
|
]),
|
|
88
|
-
dataLineNumber: directiveShowLineNumbers
|
|
104
|
+
dataLineNumber: typeof directiveShowLineNumbers === "number"
|
|
105
|
+
? directiveShowLineNumbers - 1 + lineNumber
|
|
106
|
+
: directiveShowLineNumbers
|
|
107
|
+
? lineNumber
|
|
108
|
+
: undefined,
|
|
89
109
|
},
|
|
90
110
|
};
|
|
91
111
|
};
|
|
92
|
-
// match all common types of line breaks
|
|
93
|
-
const REGEX_LINE_BREAKS = /\r?\n|\r/g;
|
|
94
112
|
/**
|
|
95
113
|
*
|
|
96
|
-
*
|
|
114
|
+
* handle elements which is multi line comment in code
|
|
115
|
+
* mutates the code
|
|
116
|
+
*
|
|
117
|
+
*/
|
|
118
|
+
function handleMultiLineComments(code) {
|
|
119
|
+
for (let index = 0; index < code.children.length; index++) {
|
|
120
|
+
const replacement = [];
|
|
121
|
+
const child = code.children[index];
|
|
122
|
+
if (!isElementWithTextNode(child))
|
|
123
|
+
continue;
|
|
124
|
+
if (!hasClassName(child, "comment"))
|
|
125
|
+
continue;
|
|
126
|
+
const textNode = child.children[0];
|
|
127
|
+
if (!REGEX_LINE_BREAKS.test(textNode.value))
|
|
128
|
+
continue;
|
|
129
|
+
const comments = textNode.value.split(REGEX_LINE_BREAKS);
|
|
130
|
+
for (let i = 0; i < comments.length; i++) {
|
|
131
|
+
const newChild = structuredClone(child);
|
|
132
|
+
newChild.children[0].value = comments[i];
|
|
133
|
+
replacement.push(newChild);
|
|
134
|
+
if (i < comments.length - 1) {
|
|
135
|
+
replacement.push({ type: "text", value: "\n" }); // eol
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
code.children = [
|
|
139
|
+
...code.children.slice(0, index),
|
|
140
|
+
...replacement,
|
|
141
|
+
...code.children.slice(index + 1),
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
* handle eol characters in the beginning of the only first element
|
|
148
|
+
* (because gutter function does not check the first element in the HAST whether contain eol at the beginning)
|
|
149
|
+
* mutates the code
|
|
97
150
|
*
|
|
98
151
|
*/
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
152
|
+
function handleFirstElementContent(code) {
|
|
153
|
+
const elementNode = code.children[0];
|
|
154
|
+
if (!isElementWithTextNode(elementNode))
|
|
155
|
+
return;
|
|
156
|
+
const textNode = elementNode.children[0];
|
|
157
|
+
if (!REGEX_LINE_BREAKS_IN_THE_BEGINNING.test(textNode.value))
|
|
158
|
+
return;
|
|
159
|
+
const match = REGEX_LINE_BREAKS_IN_THE_BEGINNING.exec(textNode.value);
|
|
160
|
+
if (match) {
|
|
161
|
+
code.children.unshift({ type: "text", value: match[0] });
|
|
162
|
+
textNode.value = textNode.value.replace(REGEX_LINE_BREAKS_IN_THE_BEGINNING, "");
|
|
163
|
+
}
|
|
102
164
|
}
|
|
103
|
-
|
|
165
|
+
/**
|
|
166
|
+
*
|
|
167
|
+
* handle trimming blank line for the last text node
|
|
168
|
+
*
|
|
169
|
+
*/
|
|
170
|
+
function handleTrimmingBlankLines(code, directiveTrimBlankLines) {
|
|
171
|
+
if (!directiveTrimBlankLines)
|
|
172
|
+
return;
|
|
173
|
+
const lastChild = code.children[code.children.length - 1];
|
|
174
|
+
if (lastChild.type === "text") {
|
|
175
|
+
if (/(\r?\n|\r)(\1)$/.test(lastChild.value)) {
|
|
176
|
+
lastChild.value = lastChild.value.replace(/(\r?\n|\r)(\1)$/, "$1");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
*
|
|
182
|
+
* extract the lines from HAST of code element
|
|
183
|
+
* mutates the code
|
|
184
|
+
*
|
|
185
|
+
*/
|
|
186
|
+
function gutter(code, { directiveShowLineNumbers, directiveHighlightLines, directiveTrimBlankLines, }) {
|
|
187
|
+
hasFlatteningNeed(code) && flattenCodeTree(code); // mutates the code
|
|
188
|
+
handleMultiLineComments(code); // mutates the code
|
|
189
|
+
handleFirstElementContent(code); // mutates the code
|
|
190
|
+
handleTrimmingBlankLines(code, directiveTrimBlankLines);
|
|
104
191
|
const replacement = [];
|
|
105
|
-
let index = -1;
|
|
106
192
|
let start = 0;
|
|
107
193
|
let startTextRemainder = "";
|
|
108
194
|
let lineNumber = 0;
|
|
109
|
-
|
|
110
|
-
const child =
|
|
195
|
+
for (let index = 0; index < code.children.length; index++) {
|
|
196
|
+
const child = code.children[index];
|
|
111
197
|
if (child.type !== "text")
|
|
112
198
|
continue;
|
|
113
199
|
let textStart = 0;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// Nodes in this line. (current child is exclusive)
|
|
117
|
-
const line =
|
|
200
|
+
const matches = Array.from(child.value.matchAll(REGEX_LINE_BREAKS));
|
|
201
|
+
matches.forEach((match, iteration) => {
|
|
202
|
+
// Nodes in this line. (current child (index) is exclusive)
|
|
203
|
+
const line = code.children.slice(start, index);
|
|
118
204
|
// Prepend text from a partial matched earlier text.
|
|
119
205
|
if (startTextRemainder) {
|
|
120
206
|
line.unshift({ type: "text", value: startTextRemainder });
|
|
@@ -125,36 +211,35 @@ const plugin = (options) => {
|
|
|
125
211
|
const value = child.value.slice(textStart, match.index);
|
|
126
212
|
line.push({ type: "text", value });
|
|
127
213
|
}
|
|
128
|
-
|
|
214
|
+
const isFirstIteration = index === 0 && iteration === 0;
|
|
215
|
+
if (isFirstIteration && directiveTrimBlankLines && line.length === 0) {
|
|
216
|
+
replacement.push({ type: "text", value: match[0] }); // eol
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
129
219
|
lineNumber += 1;
|
|
130
|
-
replacement.push(createLine(line, lineNumber,
|
|
220
|
+
replacement.push(createLine(line, lineNumber, directiveShowLineNumbers, directiveHighlightLines), { type: "text", value: match[0] });
|
|
131
221
|
}
|
|
132
|
-
// Add eol
|
|
133
|
-
replacement.push({ type: "text", value: match[0] });
|
|
134
222
|
start = index + 1;
|
|
135
223
|
textStart = match.index + match[0].length;
|
|
136
|
-
|
|
137
|
-
match = REGEX_LINE_BREAKS.exec(child.value);
|
|
138
|
-
}
|
|
224
|
+
});
|
|
139
225
|
// If we matched, make sure to not drop the text after the last line ending.
|
|
140
226
|
if (start === index + 1) {
|
|
141
227
|
startTextRemainder = child.value.slice(textStart);
|
|
142
228
|
}
|
|
143
229
|
}
|
|
144
|
-
const line =
|
|
230
|
+
const line = code.children.slice(start);
|
|
145
231
|
// Prepend text from a partial matched earlier text.
|
|
146
232
|
if (startTextRemainder) {
|
|
147
233
|
line.unshift({ type: "text", value: startTextRemainder });
|
|
148
234
|
startTextRemainder = "";
|
|
149
235
|
}
|
|
150
|
-
if (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
replacement.push(createLine(line, lineNumber,
|
|
154
|
-
}
|
|
236
|
+
if (line.length > 0) {
|
|
237
|
+
directiveTrimBlankLines
|
|
238
|
+
? replacement.push(...line)
|
|
239
|
+
: replacement.push(createLine(line, ++lineNumber, directiveShowLineNumbers, directiveHighlightLines));
|
|
155
240
|
}
|
|
156
241
|
// Replace children with new array.
|
|
157
|
-
|
|
242
|
+
code.children = replacement;
|
|
158
243
|
}
|
|
159
244
|
/**
|
|
160
245
|
*
|
|
@@ -183,53 +268,58 @@ const plugin = (options) => {
|
|
|
183
268
|
* Nothing.
|
|
184
269
|
*/
|
|
185
270
|
return (tree) => {
|
|
186
|
-
visit(tree, "element", function (
|
|
187
|
-
if (!parent || index === undefined ||
|
|
271
|
+
visit(tree, "element", function (code, index, parent) {
|
|
272
|
+
if (!parent || index === undefined || code.tagName !== "code") {
|
|
188
273
|
return;
|
|
189
274
|
}
|
|
190
275
|
if (parent.type !== "element" || parent.tagName !== "pre") {
|
|
191
276
|
return;
|
|
192
277
|
}
|
|
193
|
-
const code = node;
|
|
194
278
|
const classNames = code.properties.className;
|
|
195
279
|
// only for type narrowing
|
|
196
280
|
/* v8 ignore next */
|
|
197
|
-
if (!
|
|
281
|
+
if (!isStringArray(classNames) && classNames !== undefined)
|
|
198
282
|
return;
|
|
199
|
-
let meta = code.data?.meta?.toLowerCase().trim()
|
|
283
|
+
let meta = code.data?.meta?.toLowerCase().trim() ?? "";
|
|
200
284
|
const language = getLanguage(classNames);
|
|
201
285
|
if (language?.startsWith("{") ||
|
|
202
286
|
language?.startsWith("showlinenumbers") ||
|
|
203
|
-
language?.startsWith("nolinenumbers")
|
|
287
|
+
language?.startsWith("nolinenumbers") ||
|
|
288
|
+
language?.startsWith("trimblanklines")) {
|
|
204
289
|
// add specifiers to meta
|
|
205
290
|
meta = (language + " " + meta).trim();
|
|
206
|
-
//
|
|
291
|
+
// correct the code's meta
|
|
292
|
+
code.data && (code.data.meta = meta);
|
|
293
|
+
// remove all classnames like hljs, lang-{1,3}, language-showLineNumbers, because of false positive
|
|
207
294
|
code.properties.className = undefined;
|
|
208
295
|
}
|
|
209
|
-
|
|
296
|
+
let directiveShowLineNumbers = meta.includes("nolinenumbers")
|
|
210
297
|
? false
|
|
211
298
|
: settings.showLineNumbers || meta.includes("showlinenumbers");
|
|
212
|
-
let startingNumber = 1;
|
|
213
299
|
// find the number where the line number starts, if exists
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
startingNumber = Number(start);
|
|
219
|
-
}
|
|
300
|
+
const REGEX1 = /showlinenumbers=(?<start>\d+)/i;
|
|
301
|
+
const start = REGEX1.exec(meta)?.groups?.start;
|
|
302
|
+
if (start && !isNaN(Number(start)))
|
|
303
|
+
directiveShowLineNumbers = Number(start);
|
|
220
304
|
// find number range string within curly braces and parse it
|
|
221
305
|
const REGEX2 = /{(?<lines>[\d\s,-]+)}/g;
|
|
222
306
|
const strLineNumbers = REGEX2.exec(meta)?.groups?.lines?.replace(/\s/g, "");
|
|
223
|
-
const
|
|
224
|
-
//
|
|
225
|
-
|
|
307
|
+
const directiveHighlightLines = strLineNumbers ? rangeParser(strLineNumbers) : [];
|
|
308
|
+
// find the directive for trimming blank lines
|
|
309
|
+
const REGEX3 = /trimblanklines/i;
|
|
310
|
+
const directiveTrimBlankLines = settings.trimBlankLines || REGEX3.test(meta);
|
|
311
|
+
// if nothing to do for numbering, highlihting or trimming blank lines, just return;
|
|
312
|
+
if (directiveShowLineNumbers === false &&
|
|
313
|
+
directiveHighlightLines.length === 0 &&
|
|
314
|
+
directiveTrimBlankLines === false) {
|
|
226
315
|
return;
|
|
227
|
-
// flatten deeper nodes into first level <span> and text, especially for languages like jsx, tsx
|
|
228
|
-
if (checkCodeTreeForFlatteningNeed(code)) {
|
|
229
|
-
flattenCodeTree(code);
|
|
230
316
|
}
|
|
231
317
|
// add container for each line mutating the code element
|
|
232
|
-
gutter(code,
|
|
318
|
+
gutter(code, {
|
|
319
|
+
directiveShowLineNumbers,
|
|
320
|
+
directiveHighlightLines,
|
|
321
|
+
directiveTrimBlankLines,
|
|
322
|
+
});
|
|
233
323
|
});
|
|
234
324
|
};
|
|
235
325
|
};
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAsB,MAAM,kBAAkB,CAAC;AAC7D,OAAO,WAAW,MAAM,qBAAqB,CAAC;AAe9C,MAAM,gBAAgB,GAA0B;IAC9C,eAAe,EAAE,KAAK;IACtB,oBAAoB,EAAE,MAAM;CAC7B,CAAC;AAUF,oDAAoD;AACpD,MAAM,UAAU,IAAI,CAAC,GAA8C;IACjE,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,MAAM,GAA2C,CAAC,OAAO,EAAE,EAAE;IACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAC5B,EAAE,EACF,gBAAgB,EAChB,OAAO,CACkC,CAAC;IAE5C;;;;OAIG;IACH,SAAS,8BAA8B,CAAC,IAAa;QACnD,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC;QAEtC,iDAAiD;QACjD,KAAK,MAAM,aAAa,IAAI,eAAe,EAAE,CAAC;YAC5C,IAAI,aAAa,CAAC,IAAI,KAAK,SAAS;gBAClC,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS;oBACpF,OAAO,IAAI,CAAC;QAClB,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;OAKG;IACH,SAAS,eAAe,CAAC,IAAa,EAAE,YAAsB,EAAE;QAC9D,MAAM,OAAO,GAAqB,EAAE,CAAC;QAErC,KAAK,MAAM,cAAc,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC3C,IAAI,cAAc,CAAC,IAAI,KAAK,SAAS,IAAI,cAAc,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxE,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,iHAAiH;gBACjH,uBAAuB;gBACvB,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;gBAE/E,IACE,cAAc,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;oBACpC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,EAC7C,CAAC;oBACD,cAAc,CAAC,UAAU,CAAC,SAAS,GAAG,UAAU,CAAC;oBACjD,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,MAAM,UAAU,GAAG,CACjB,QAA0B,EAC1B,UAAkB,EAClB,cAAsB,EACtB,wBAAiC,EACjC,oBAA8B,EACrB,EAAE;QACX,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE/B,MAAM,UAAU,GACd,UAAU,EAAE,IAAI,KAAK,SAAS;YAC9B,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC;YAC9C,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAClC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC7D,CAAC;QAEJ,MAAM,UAAU,GACd,UAAU,EAAE,IAAI,KAAK,SAAS;YAC9B,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC;YAC9C,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAClC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC7D,CAAC;QAEJ,OAAO;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,MAAM,EAAE,0BAA0B;YAC3C,QAAQ;YACR,UAAU,EAAE;gBACV,SAAS,EAAE,IAAI,CAAC;oBACd,WAAW;oBACX,wBAAwB,IAAI,oBAAoB;oBAChD,oBAAoB,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,uBAAuB;oBACpE,UAAU,IAAI,UAAU;oBACxB,UAAU,IAAI,SAAS;iBACxB,CAAC;gBACF,cAAc,EAAE,wBAAwB,CAAC,CAAC,CAAC,cAAc,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS;aACvF;SACF,CAAC;IACJ,CAAC,CAAC;IAEF,wCAAwC;IACxC,MAAM,iBAAiB,GAAG,WAAW,CAAC;IAEtC;;;;OAIG;IACH,SAAS,WAAW,CAAC,IAAsB;QACzC,OAAO,CACL,IAAI,CAAC,MAAM,KAAK,CAAC;YACjB,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAC9E,CAAC;IACJ,CAAC;IAED,SAAS,MAAM,CACb,IAAa,EACb,wBAAiC,EACjC,cAAsB,EACtB,oBAA8B;QAE9B,MAAM,WAAW,GAAqB,EAAE,CAAC;QAEzC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;QACf,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,kBAAkB,GAAG,EAAE,CAAC;QAC5B,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEnC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAS;YAEpC,IAAI,SAAS,GAAG,CAAC,CAAC;YAClB,IAAI,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAEhD,OAAO,KAAK,KAAK,IAAI,EAAE,CAAC;gBACtB,mDAAmD;gBACnD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBAE/C,oDAAoD;gBACpD,IAAI,kBAAkB,EAAE,CAAC;oBACvB,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;oBAC1D,kBAAkB,GAAG,EAAE,CAAC;gBAC1B,CAAC;gBAED,8BAA8B;gBAC9B,IAAI,KAAK,CAAC,KAAK,GAAG,SAAS,EAAE,CAAC;oBAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;oBACxD,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;gBACrC,CAAC;gBAED,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;oBACvB,UAAU,IAAI,CAAC,CAAC;oBAChB,WAAW,CAAC,IAAI,CACd,UAAU,CACR,IAAI,EACJ,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,oBAAoB,CACrB,CACF,CAAC;gBACJ,CAAC;gBAED,UAAU;gBACV,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAEpD,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;gBAClB,SAAS,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBAE1C,oBAAoB;gBACpB,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC;YAED,4EAA4E;YAC5E,IAAI,KAAK,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;gBACxB,kBAAkB,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAExC,oDAAoD;QACpD,IAAI,kBAAkB,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC1D,kBAAkB,GAAG,EAAE,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,UAAU,IAAI,CAAC,CAAC;gBAChB,WAAW,CAAC,IAAI,CACd,UAAU,CACR,IAAI,EACJ,UAAU,EACV,cAAc,EACd,wBAAwB,EACxB,oBAAoB,CACrB,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,mCAAmC;QACnC,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACH,SAAS,WAAW,CAAC,UAA2C;QAC9D,MAAM,gBAAgB,GAAG,CAAC,OAAwB,EAAqB,EAAE;YACvE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACxF,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAE1D,IAAI,cAAc,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;YAC5C,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/C,CAAC;QAED,IAAI,cAAc,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;YAChD,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/C,CAAC;QAED,OAAO,cAAc,CAAC;IACxB,CAAC;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,IAAU,EAAa,EAAE;QAC/B,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,IAAI,EAAE,KAAK,EAAE,MAAM;YAClD,IAAI,CAAC,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;gBAC9D,OAAO;YACT,CAAC;YAED,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC1D,OAAO;YACT,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC;YAElB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAE7C,0BAA0B;YAC1B,oBAAoB;YACpB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,UAAU,KAAK,SAAS;gBAAE,OAAO;YAEnE,IAAI,IAAI,GAAI,IAAI,CAAC,IAAiB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;YAErE,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;YAEzC,IACE,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC;gBACzB,QAAQ,EAAE,UAAU,CAAC,iBAAiB,CAAC;gBACvC,QAAQ,EAAE,UAAU,CAAC,eAAe,CAAC,EACrC,CAAC;gBACD,yBAAyB;gBACzB,IAAI,GAAG,CAAC,QAAQ,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;gBAEtC,iFAAiF;gBACjF,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC;YACxC,CAAC;YAED,MAAM,wBAAwB,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;gBAC7D,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,QAAQ,CAAC,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;YAEjE,IAAI,cAAc,GAAG,CAAC,CAAC;YAEvB,0DAA0D;YAC1D,IAAI,wBAAwB,EAAE,CAAC;gBAC7B,MAAM,MAAM,GAAG,gCAAgC,CAAC;gBAChD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC;gBAC/C,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBAAE,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YACrE,CAAC;YAED,4DAA4D;YAC5D,MAAM,MAAM,GAAG,wBAAwB,CAAC;YACxC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC5E,MAAM,oBAAoB,GAAG,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAE/E,8DAA8D;YAC9D,IAAI,CAAC,wBAAwB,IAAI,oBAAoB,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAE3E,gGAAgG;YAChG,IAAI,8BAA8B,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,eAAe,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;YAED,wDAAwD;YACxD,MAAM,CAAC,IAAI,EAAE,wBAAwB,EAAE,cAAc,EAAE,oBAAoB,CAAC,CAAC;QAC/E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rehype-highlight-code-lines",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Rehype plugin to add line numbers to code blocks and allow highlighting of desired code lines",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/esm/index.js",
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
"lint": "eslint .",
|
|
14
14
|
"test": "vitest --watch=false",
|
|
15
15
|
"test:watch": "vitest",
|
|
16
|
-
"test:
|
|
16
|
+
"test:file1": "vitest test.md.spec.ts",
|
|
17
|
+
"test:file2": "vitest test.html.spec.ts",
|
|
18
|
+
"test:file3": "vitest test.cases.spec.ts",
|
|
19
|
+
"test:file4": "vitest from-rehype-highlight/test.rhcl2.spec.ts",
|
|
17
20
|
"prepack": "npm run build",
|
|
18
21
|
"prepublishOnly": "npm run test && npm run format && npm run test-coverage",
|
|
19
22
|
"test-coverage": "vitest run --coverage"
|
|
@@ -51,16 +54,16 @@
|
|
|
51
54
|
"url": "https://github.com/ipikuka/rehype-highlight-code-lines/issues"
|
|
52
55
|
},
|
|
53
56
|
"devDependencies": {
|
|
54
|
-
"@eslint/js": "^9.
|
|
57
|
+
"@eslint/js": "^9.20.0",
|
|
55
58
|
"@types/dedent": "^0.7.2",
|
|
56
59
|
"@types/node": "^22.13.1",
|
|
57
60
|
"@vitest/coverage-v8": "^3.0.5",
|
|
58
|
-
"@vitest/eslint-plugin": "^1.1.
|
|
61
|
+
"@vitest/eslint-plugin": "^1.1.27",
|
|
59
62
|
"dedent": "^1.5.3",
|
|
60
|
-
"eslint": "^9.
|
|
63
|
+
"eslint": "^9.20.0",
|
|
61
64
|
"eslint-config-prettier": "^10.0.1",
|
|
62
65
|
"eslint-plugin-prettier": "^5.2.3",
|
|
63
|
-
"prettier": "^3.
|
|
66
|
+
"prettier": "^3.5.0",
|
|
64
67
|
"rehype": "^13.0.2",
|
|
65
68
|
"rehype-highlight": "^7.0.2",
|
|
66
69
|
"rehype-parse": "^9.0.1",
|
|
@@ -74,14 +77,17 @@
|
|
|
74
77
|
"typescript-eslint": "^8.23.0",
|
|
75
78
|
"unist-util-remove-position": "^5.0.0",
|
|
76
79
|
"vfile": "^6.0.3",
|
|
77
|
-
"vitest": "^3.0.5"
|
|
80
|
+
"vitest": "^3.0.5",
|
|
81
|
+
"unified": "^11.0.5"
|
|
78
82
|
},
|
|
79
83
|
"dependencies": {
|
|
80
84
|
"@types/hast": "^3.0.4",
|
|
81
85
|
"parse-numeric-range": "^1.3.0",
|
|
82
|
-
"unified": "^11.0.5",
|
|
83
86
|
"unist-util-visit": "^5.0.0"
|
|
84
87
|
},
|
|
88
|
+
"peerDependencies": {
|
|
89
|
+
"unified": "^11"
|
|
90
|
+
},
|
|
85
91
|
"typeCoverage": {
|
|
86
92
|
"atLeast": 100,
|
|
87
93
|
"detail": true,
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from "unified";
|
|
2
|
-
import type { Root, Element,
|
|
2
|
+
import type { Root, Element, Text, ElementContent } from "hast";
|
|
3
3
|
import { visit, type VisitorResult } from "unist-util-visit";
|
|
4
4
|
import rangeParser from "parse-numeric-range";
|
|
5
5
|
|
|
@@ -7,6 +7,16 @@ type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
|
|
7
7
|
|
|
8
8
|
type PartiallyRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
|
|
9
9
|
|
|
10
|
+
declare module "hast" {
|
|
11
|
+
interface Data {
|
|
12
|
+
meta?: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type ElementWithTextNode = Element & {
|
|
17
|
+
children: [Text, ...ElementContent[]];
|
|
18
|
+
};
|
|
19
|
+
|
|
10
20
|
export type HighlightLinesOptions = {
|
|
11
21
|
showLineNumbers?: boolean;
|
|
12
22
|
/**
|
|
@@ -14,19 +24,23 @@ export type HighlightLinesOptions = {
|
|
|
14
24
|
* will be removed in the next versions
|
|
15
25
|
*/
|
|
16
26
|
lineContainerTagName?: "div" | "span";
|
|
27
|
+
trimBlankLines?: boolean;
|
|
17
28
|
};
|
|
18
29
|
|
|
19
30
|
const DEFAULT_SETTINGS: HighlightLinesOptions = {
|
|
20
31
|
showLineNumbers: false,
|
|
21
32
|
lineContainerTagName: "span",
|
|
33
|
+
trimBlankLines: false,
|
|
22
34
|
};
|
|
23
35
|
|
|
24
36
|
type PartiallyRequiredHighlightLinesOptions = Prettify<
|
|
25
37
|
PartiallyRequired<HighlightLinesOptions, "showLineNumbers" | "lineContainerTagName">
|
|
26
38
|
>;
|
|
27
39
|
|
|
28
|
-
type
|
|
29
|
-
|
|
40
|
+
type GutterOptions = {
|
|
41
|
+
directiveShowLineNumbers: boolean | number;
|
|
42
|
+
directiveHighlightLines: number[];
|
|
43
|
+
directiveTrimBlankLines: boolean;
|
|
30
44
|
};
|
|
31
45
|
|
|
32
46
|
// a simple util for our use case, like clsx package
|
|
@@ -34,6 +48,33 @@ export function clsx(arr: (string | false | null | undefined | 0)[]): string[] {
|
|
|
34
48
|
return arr.filter((item): item is string => !!item);
|
|
35
49
|
}
|
|
36
50
|
|
|
51
|
+
// check if it is string array
|
|
52
|
+
function isStringArray(value: unknown): value is string[] {
|
|
53
|
+
return (
|
|
54
|
+
// type-coverage:ignore-next-line
|
|
55
|
+
Array.isArray(value) && value.every((item) => typeof item === "string")
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// check if it is Element which first child is text
|
|
60
|
+
function isElementWithTextNode(node: ElementContent | undefined): node is ElementWithTextNode {
|
|
61
|
+
return (
|
|
62
|
+
node?.type === "element" && node.children[0]?.type === "text" && "value" in node.children[0]
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function hasClassName(node: ElementContent | undefined, className: string): boolean {
|
|
67
|
+
return (
|
|
68
|
+
node?.type === "element" &&
|
|
69
|
+
isStringArray(node.properties.className) &&
|
|
70
|
+
node.properties.className.some((cls) => cls.includes(className))
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// match all common types of line breaks
|
|
75
|
+
const REGEX_LINE_BREAKS = /\r?\n|\r/g;
|
|
76
|
+
const REGEX_LINE_BREAKS_IN_THE_BEGINNING = /^(\r?\n|\r)+/;
|
|
77
|
+
|
|
37
78
|
/**
|
|
38
79
|
*
|
|
39
80
|
* add line numbers to code blocks and allow highlighting of desired code lines
|
|
@@ -51,14 +92,13 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
51
92
|
* check code element children need flattening or not
|
|
52
93
|
*
|
|
53
94
|
*/
|
|
54
|
-
function
|
|
95
|
+
function hasFlatteningNeed(code: Element): boolean {
|
|
55
96
|
const elementContents = code.children;
|
|
56
97
|
|
|
57
98
|
// type ElementContent = Comment | Element | Text
|
|
58
99
|
for (const elemenContent of elementContents) {
|
|
59
|
-
if (elemenContent.type === "element")
|
|
60
|
-
if (elemenContent.children.
|
|
61
|
-
return true;
|
|
100
|
+
if (elemenContent.type === "element" && Boolean(elemenContent.children.length))
|
|
101
|
+
if (elemenContent.children.some((ec) => ec.type === "element")) return true;
|
|
62
102
|
}
|
|
63
103
|
|
|
64
104
|
return false;
|
|
@@ -66,7 +106,8 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
66
106
|
|
|
67
107
|
/**
|
|
68
108
|
*
|
|
69
|
-
* flatten
|
|
109
|
+
* flatten deeper nodes into first level <span> and text, especially for languages like jsx, tsx
|
|
110
|
+
* mutates the code, recursively
|
|
70
111
|
* inspired from https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/src/highlight.js
|
|
71
112
|
*
|
|
72
113
|
*/
|
|
@@ -106,25 +147,12 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
106
147
|
const createLine = (
|
|
107
148
|
children: ElementContent[],
|
|
108
149
|
lineNumber: number,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
linesToBeHighlighted: number[],
|
|
150
|
+
directiveShowLineNumbers: boolean | number,
|
|
151
|
+
directiveHighlightLines: number[],
|
|
112
152
|
): Element => {
|
|
113
153
|
const firstChild = children[0];
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
firstChild?.type === "element" &&
|
|
117
|
-
Array.isArray(firstChild.properties.className) &&
|
|
118
|
-
firstChild.properties.className.some(
|
|
119
|
-
(cls) => typeof cls === "string" && cls.includes("addition"),
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
const isDeletion =
|
|
123
|
-
firstChild?.type === "element" &&
|
|
124
|
-
Array.isArray(firstChild.properties.className) &&
|
|
125
|
-
firstChild.properties.className.some(
|
|
126
|
-
(cls) => typeof cls === "string" && cls.includes("deletion"),
|
|
127
|
-
);
|
|
154
|
+
const isAddition = hasClassName(firstChild, "addition");
|
|
155
|
+
const isDeletion = hasClassName(firstChild, "deletion");
|
|
128
156
|
|
|
129
157
|
return {
|
|
130
158
|
type: "element",
|
|
@@ -134,54 +162,136 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
134
162
|
className: clsx([
|
|
135
163
|
"code-line",
|
|
136
164
|
directiveShowLineNumbers && "numbered-code-line",
|
|
137
|
-
|
|
165
|
+
directiveHighlightLines.includes(lineNumber) && "highlighted-code-line",
|
|
138
166
|
isAddition && "inserted",
|
|
139
167
|
isDeletion && "deleted",
|
|
140
168
|
]),
|
|
141
|
-
dataLineNumber:
|
|
169
|
+
dataLineNumber:
|
|
170
|
+
typeof directiveShowLineNumbers === "number"
|
|
171
|
+
? directiveShowLineNumbers - 1 + lineNumber
|
|
172
|
+
: directiveShowLineNumbers
|
|
173
|
+
? lineNumber
|
|
174
|
+
: undefined,
|
|
142
175
|
},
|
|
143
176
|
};
|
|
144
177
|
};
|
|
145
178
|
|
|
146
|
-
|
|
147
|
-
|
|
179
|
+
/**
|
|
180
|
+
*
|
|
181
|
+
* handle elements which is multi line comment in code
|
|
182
|
+
* mutates the code
|
|
183
|
+
*
|
|
184
|
+
*/
|
|
185
|
+
function handleMultiLineComments(code: Element): undefined {
|
|
186
|
+
for (let index = 0; index < code.children.length; index++) {
|
|
187
|
+
const replacement: ElementContent[] = [];
|
|
188
|
+
|
|
189
|
+
const child = code.children[index];
|
|
190
|
+
|
|
191
|
+
if (!isElementWithTextNode(child)) continue;
|
|
192
|
+
if (!hasClassName(child, "comment")) continue;
|
|
193
|
+
|
|
194
|
+
const textNode = child.children[0];
|
|
195
|
+
if (!REGEX_LINE_BREAKS.test(textNode.value)) continue;
|
|
196
|
+
const comments = textNode.value.split(REGEX_LINE_BREAKS);
|
|
197
|
+
|
|
198
|
+
for (let i = 0; i < comments.length; i++) {
|
|
199
|
+
const newChild = structuredClone(child);
|
|
200
|
+
newChild.children[0].value = comments[i];
|
|
201
|
+
replacement.push(newChild);
|
|
202
|
+
|
|
203
|
+
if (i < comments.length - 1) {
|
|
204
|
+
replacement.push({ type: "text", value: "\n" }); // eol
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
code.children = [
|
|
209
|
+
...code.children.slice(0, index),
|
|
210
|
+
...replacement,
|
|
211
|
+
...code.children.slice(index + 1),
|
|
212
|
+
];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
148
215
|
|
|
149
216
|
/**
|
|
150
217
|
*
|
|
151
|
-
*
|
|
218
|
+
* handle eol characters in the beginning of the only first element
|
|
219
|
+
* (because gutter function does not check the first element in the HAST whether contain eol at the beginning)
|
|
220
|
+
* mutates the code
|
|
152
221
|
*
|
|
153
222
|
*/
|
|
154
|
-
function
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
223
|
+
function handleFirstElementContent(code: Element): undefined {
|
|
224
|
+
const elementNode = code.children[0];
|
|
225
|
+
if (!isElementWithTextNode(elementNode)) return;
|
|
226
|
+
|
|
227
|
+
const textNode = elementNode.children[0];
|
|
228
|
+
if (!REGEX_LINE_BREAKS_IN_THE_BEGINNING.test(textNode.value)) return;
|
|
229
|
+
|
|
230
|
+
const match = REGEX_LINE_BREAKS_IN_THE_BEGINNING.exec(textNode.value);
|
|
231
|
+
|
|
232
|
+
if (match) {
|
|
233
|
+
code.children.unshift({ type: "text", value: match[0] });
|
|
234
|
+
|
|
235
|
+
textNode.value = textNode.value.replace(REGEX_LINE_BREAKS_IN_THE_BEGINNING, "");
|
|
236
|
+
}
|
|
159
237
|
}
|
|
160
238
|
|
|
239
|
+
/**
|
|
240
|
+
*
|
|
241
|
+
* handle trimming blank line for the last text node
|
|
242
|
+
*
|
|
243
|
+
*/
|
|
244
|
+
function handleTrimmingBlankLines(code: Element, directiveTrimBlankLines: boolean) {
|
|
245
|
+
if (!directiveTrimBlankLines) return;
|
|
246
|
+
|
|
247
|
+
const lastChild = code.children[code.children.length - 1];
|
|
248
|
+
|
|
249
|
+
if (lastChild.type === "text") {
|
|
250
|
+
if (/(\r?\n|\r)(\1)$/.test(lastChild.value)) {
|
|
251
|
+
lastChild.value = lastChild.value.replace(/(\r?\n|\r)(\1)$/, "$1");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
*
|
|
258
|
+
* extract the lines from HAST of code element
|
|
259
|
+
* mutates the code
|
|
260
|
+
*
|
|
261
|
+
*/
|
|
161
262
|
function gutter(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
263
|
+
code: Element,
|
|
264
|
+
{
|
|
265
|
+
directiveShowLineNumbers,
|
|
266
|
+
directiveHighlightLines,
|
|
267
|
+
directiveTrimBlankLines,
|
|
268
|
+
}: GutterOptions,
|
|
166
269
|
) {
|
|
270
|
+
hasFlatteningNeed(code) && flattenCodeTree(code); // mutates the code
|
|
271
|
+
|
|
272
|
+
handleMultiLineComments(code); // mutates the code
|
|
273
|
+
|
|
274
|
+
handleFirstElementContent(code); // mutates the code
|
|
275
|
+
|
|
276
|
+
handleTrimmingBlankLines(code, directiveTrimBlankLines);
|
|
277
|
+
|
|
167
278
|
const replacement: ElementContent[] = [];
|
|
168
279
|
|
|
169
|
-
let index = -1;
|
|
170
280
|
let start = 0;
|
|
171
281
|
let startTextRemainder = "";
|
|
172
282
|
let lineNumber = 0;
|
|
173
283
|
|
|
174
|
-
|
|
175
|
-
const child =
|
|
284
|
+
for (let index = 0; index < code.children.length; index++) {
|
|
285
|
+
const child = code.children[index];
|
|
176
286
|
|
|
177
287
|
if (child.type !== "text") continue;
|
|
178
288
|
|
|
179
289
|
let textStart = 0;
|
|
180
|
-
let match = REGEX_LINE_BREAKS.exec(child.value);
|
|
181
290
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
291
|
+
const matches = Array.from(child.value.matchAll(REGEX_LINE_BREAKS));
|
|
292
|
+
matches.forEach((match, iteration) => {
|
|
293
|
+
// Nodes in this line. (current child (index) is exclusive)
|
|
294
|
+
const line = code.children.slice(start, index);
|
|
185
295
|
|
|
186
296
|
// Prepend text from a partial matched earlier text.
|
|
187
297
|
if (startTextRemainder) {
|
|
@@ -195,28 +305,21 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
195
305
|
line.push({ type: "text", value });
|
|
196
306
|
}
|
|
197
307
|
|
|
198
|
-
|
|
308
|
+
const isFirstIteration = index === 0 && iteration === 0;
|
|
309
|
+
|
|
310
|
+
if (isFirstIteration && directiveTrimBlankLines && line.length === 0) {
|
|
311
|
+
replacement.push({ type: "text", value: match[0] }); // eol
|
|
312
|
+
} else {
|
|
199
313
|
lineNumber += 1;
|
|
200
314
|
replacement.push(
|
|
201
|
-
createLine(
|
|
202
|
-
|
|
203
|
-
lineNumber,
|
|
204
|
-
startingNumber,
|
|
205
|
-
directiveShowLineNumbers,
|
|
206
|
-
linesToBeHighlighted,
|
|
207
|
-
),
|
|
315
|
+
createLine(line, lineNumber, directiveShowLineNumbers, directiveHighlightLines),
|
|
316
|
+
{ type: "text", value: match[0] }, // eol
|
|
208
317
|
);
|
|
209
318
|
}
|
|
210
319
|
|
|
211
|
-
// Add eol
|
|
212
|
-
replacement.push({ type: "text", value: match[0] });
|
|
213
|
-
|
|
214
320
|
start = index + 1;
|
|
215
321
|
textStart = match.index + match[0].length;
|
|
216
|
-
|
|
217
|
-
// iterate the match
|
|
218
|
-
match = REGEX_LINE_BREAKS.exec(child.value);
|
|
219
|
-
}
|
|
322
|
+
});
|
|
220
323
|
|
|
221
324
|
// If we matched, make sure to not drop the text after the last line ending.
|
|
222
325
|
if (start === index + 1) {
|
|
@@ -224,7 +327,7 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
224
327
|
}
|
|
225
328
|
}
|
|
226
329
|
|
|
227
|
-
const line =
|
|
330
|
+
const line = code.children.slice(start);
|
|
228
331
|
|
|
229
332
|
// Prepend text from a partial matched earlier text.
|
|
230
333
|
if (startTextRemainder) {
|
|
@@ -232,23 +335,16 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
232
335
|
startTextRemainder = "";
|
|
233
336
|
}
|
|
234
337
|
|
|
235
|
-
if (
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
replacement.push(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
lineNumber,
|
|
242
|
-
startingNumber,
|
|
243
|
-
directiveShowLineNumbers,
|
|
244
|
-
linesToBeHighlighted,
|
|
245
|
-
),
|
|
246
|
-
);
|
|
247
|
-
}
|
|
338
|
+
if (line.length > 0) {
|
|
339
|
+
directiveTrimBlankLines
|
|
340
|
+
? replacement.push(...line)
|
|
341
|
+
: replacement.push(
|
|
342
|
+
createLine(line, ++lineNumber, directiveShowLineNumbers, directiveHighlightLines),
|
|
343
|
+
);
|
|
248
344
|
}
|
|
249
345
|
|
|
250
346
|
// Replace children with new array.
|
|
251
|
-
|
|
347
|
+
code.children = replacement;
|
|
252
348
|
}
|
|
253
349
|
|
|
254
350
|
/**
|
|
@@ -283,8 +379,8 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
283
379
|
* Nothing.
|
|
284
380
|
*/
|
|
285
381
|
return (tree: Root): undefined => {
|
|
286
|
-
visit(tree, "element", function (
|
|
287
|
-
if (!parent || index === undefined ||
|
|
382
|
+
visit(tree, "element", function (code, index, parent): VisitorResult {
|
|
383
|
+
if (!parent || index === undefined || code.tagName !== "code") {
|
|
288
384
|
return;
|
|
289
385
|
}
|
|
290
386
|
|
|
@@ -292,58 +388,65 @@ const plugin: Plugin<[HighlightLinesOptions?], Root> = (options) => {
|
|
|
292
388
|
return;
|
|
293
389
|
}
|
|
294
390
|
|
|
295
|
-
const code = node;
|
|
296
|
-
|
|
297
391
|
const classNames = code.properties.className;
|
|
298
392
|
|
|
299
393
|
// only for type narrowing
|
|
300
394
|
/* v8 ignore next */
|
|
301
|
-
if (!
|
|
395
|
+
if (!isStringArray(classNames) && classNames !== undefined) return;
|
|
302
396
|
|
|
303
|
-
let meta =
|
|
397
|
+
let meta = code.data?.meta?.toLowerCase().trim() ?? "";
|
|
304
398
|
|
|
305
399
|
const language = getLanguage(classNames);
|
|
306
400
|
|
|
307
401
|
if (
|
|
308
402
|
language?.startsWith("{") ||
|
|
309
403
|
language?.startsWith("showlinenumbers") ||
|
|
310
|
-
language?.startsWith("nolinenumbers")
|
|
404
|
+
language?.startsWith("nolinenumbers") ||
|
|
405
|
+
language?.startsWith("trimblanklines")
|
|
311
406
|
) {
|
|
312
407
|
// add specifiers to meta
|
|
313
408
|
meta = (language + " " + meta).trim();
|
|
314
409
|
|
|
315
|
-
//
|
|
410
|
+
// correct the code's meta
|
|
411
|
+
code.data && (code.data.meta = meta);
|
|
412
|
+
|
|
413
|
+
// remove all classnames like hljs, lang-{1,3}, language-showLineNumbers, because of false positive
|
|
316
414
|
code.properties.className = undefined;
|
|
317
415
|
}
|
|
318
416
|
|
|
319
|
-
|
|
417
|
+
let directiveShowLineNumbers: boolean | number = meta.includes("nolinenumbers")
|
|
320
418
|
? false
|
|
321
419
|
: settings.showLineNumbers || meta.includes("showlinenumbers");
|
|
322
420
|
|
|
323
|
-
let startingNumber = 1;
|
|
324
|
-
|
|
325
421
|
// find the number where the line number starts, if exists
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if (start && !isNaN(Number(start))) startingNumber = Number(start);
|
|
330
|
-
}
|
|
422
|
+
const REGEX1 = /showlinenumbers=(?<start>\d+)/i;
|
|
423
|
+
const start = REGEX1.exec(meta)?.groups?.start;
|
|
424
|
+
if (start && !isNaN(Number(start))) directiveShowLineNumbers = Number(start);
|
|
331
425
|
|
|
332
426
|
// find number range string within curly braces and parse it
|
|
333
427
|
const REGEX2 = /{(?<lines>[\d\s,-]+)}/g;
|
|
334
428
|
const strLineNumbers = REGEX2.exec(meta)?.groups?.lines?.replace(/\s/g, "");
|
|
335
|
-
const
|
|
429
|
+
const directiveHighlightLines = strLineNumbers ? rangeParser(strLineNumbers) : [];
|
|
336
430
|
|
|
337
|
-
//
|
|
338
|
-
|
|
431
|
+
// find the directive for trimming blank lines
|
|
432
|
+
const REGEX3 = /trimblanklines/i;
|
|
433
|
+
const directiveTrimBlankLines = settings.trimBlankLines || REGEX3.test(meta);
|
|
339
434
|
|
|
340
|
-
//
|
|
341
|
-
if (
|
|
342
|
-
|
|
435
|
+
// if nothing to do for numbering, highlihting or trimming blank lines, just return;
|
|
436
|
+
if (
|
|
437
|
+
directiveShowLineNumbers === false &&
|
|
438
|
+
directiveHighlightLines.length === 0 &&
|
|
439
|
+
directiveTrimBlankLines === false
|
|
440
|
+
) {
|
|
441
|
+
return;
|
|
343
442
|
}
|
|
344
443
|
|
|
345
444
|
// add container for each line mutating the code element
|
|
346
|
-
gutter(code,
|
|
445
|
+
gutter(code, {
|
|
446
|
+
directiveShowLineNumbers,
|
|
447
|
+
directiveHighlightLines,
|
|
448
|
+
directiveTrimBlankLines,
|
|
449
|
+
});
|
|
347
450
|
});
|
|
348
451
|
};
|
|
349
452
|
};
|