fumadocs-core 14.7.5 → 14.7.7

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.
@@ -48,7 +48,7 @@ type RehypeCodeOptions = RehypeShikiOptions & {
48
48
  /**
49
49
  * Handle codeblocks
50
50
  */
51
- declare function rehypeCode(this: Processor, options?: Partial<RehypeCodeOptions>): Transformer<Root, Root>;
51
+ declare function rehypeCode(this: Processor, _options?: Partial<RehypeCodeOptions>): Transformer<Root, Root>;
52
52
  declare function transformerTab(): ShikiTransformer;
53
53
 
54
54
  interface RemarkImageOptions {
@@ -19,261 +19,11 @@ import {
19
19
 
20
20
  // src/mdx-plugins/rehype-code.ts
21
21
  import rehypeShikiFromHighlighter from "@shikijs/rehype/core";
22
-
23
- // ../../node_modules/.pnpm/shiki-transformers@1.0.1_shiki@1.27.2/node_modules/shiki-transformers/dist/index.js
24
- var matchers = [
25
- [/^(<!--)(.+)(-->)$/, false],
26
- [/^(\/\*)(.+)(\*\/)$/, false],
27
- [/^(\/\/|["']|;{1,2}|%{1,2}|--|#)(.+)$/, true],
28
- /**
29
- * for multi-line comments like this
30
- */
31
- [/^(\*)(.+)$/, true]
32
- ];
33
- function parseComments(lines, jsx) {
34
- const out = [];
35
- for (const line of lines) {
36
- const elements = line.children;
37
- const start = jsx ? elements.length - 2 : elements.length - 1;
38
- for (let i = Math.max(start, 0); i < elements.length; i++) {
39
- const token = elements[i];
40
- if (token.type !== "element")
41
- continue;
42
- const isLast = i === elements.length - 1;
43
- const match = matchToken(token, isLast);
44
- if (!match) continue;
45
- if (jsx && !isLast && i !== 0) {
46
- const left = elements[i - 1];
47
- const right = elements[i + 1];
48
- out.push({
49
- info: match,
50
- line,
51
- token,
52
- isJsxStyle: isValue(left, "{") && isValue(right, "}")
53
- });
54
- } else {
55
- out.push({
56
- info: match,
57
- line,
58
- token,
59
- isJsxStyle: false
60
- });
61
- }
62
- }
63
- }
64
- return out;
65
- }
66
- function isValue(element, value) {
67
- if (element.type !== "element") return false;
68
- const text = element.children[0];
69
- if (text.type !== "text")
70
- return false;
71
- return text.value.trim() === value;
72
- }
73
- function matchToken(token, isLast) {
74
- const text = token.children[0];
75
- if (text.type !== "text")
76
- return;
77
- for (const [matcher, endOfLine] of matchers) {
78
- if (endOfLine && !isLast) continue;
79
- let trimmed = text.value.trimStart();
80
- const spaceFront = text.value.length - trimmed.length;
81
- trimmed = trimmed.trimEnd();
82
- const spaceEnd = text.value.length - trimmed.length - spaceFront;
83
- const result = matcher.exec(trimmed);
84
- if (!result) continue;
85
- return [
86
- " ".repeat(spaceFront) + result[1],
87
- result[2],
88
- result[3] ? result[3] + " ".repeat(spaceEnd) : void 0
89
- ];
90
- }
91
- }
92
- function createCommentNotationTransformer(name, regex, onMatch) {
93
- return {
94
- name,
95
- code(code) {
96
- const lines = code.children.filter((i) => i.type === "element");
97
- const linesToRemove = [];
98
- code.data ??= {};
99
- const data = code.data;
100
- data._shiki_notation ??= parseComments(lines, ["jsx", "tsx"].includes(this.options.lang));
101
- const parsed = data._shiki_notation;
102
- for (const comment of parsed) {
103
- if (comment.info[1].length === 0) continue;
104
- const isLineCommentOnly = comment.line.children.length === (comment.isJsxStyle ? 3 : 1);
105
- let lineIdx = lines.indexOf(comment.line);
106
- if (isLineCommentOnly) lineIdx++;
107
- comment.info[1] = comment.info[1].replace(regex, (...match) => {
108
- if (onMatch.call(this, match, comment.line, comment.token, lines, lineIdx)) {
109
- return "";
110
- }
111
- return match[0];
112
- });
113
- const isEmpty = comment.info[1].trim().length === 0;
114
- if (isEmpty) comment.info[1] = "";
115
- if (isEmpty && isLineCommentOnly) {
116
- linesToRemove.push(comment.line);
117
- } else if (isEmpty && comment.isJsxStyle) {
118
- comment.line.children.splice(comment.line.children.indexOf(comment.token) - 1, 3);
119
- } else if (isEmpty) {
120
- comment.line.children.splice(comment.line.children.indexOf(comment.token), 1);
121
- } else {
122
- const head = comment.token.children[0];
123
- if (head.type === "text") {
124
- head.value = comment.info.join("");
125
- }
126
- }
127
- }
128
- for (const line of linesToRemove)
129
- code.children.splice(code.children.indexOf(line), 1);
130
- }
131
- };
132
- }
133
- function escapeRegExp(str) {
134
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
135
- }
136
- function transformerNotationMap(options = {}, name = "@shikijs/transformers:notation-map") {
137
- const {
138
- classMap = {},
139
- classActivePre = void 0
140
- } = options;
141
- return createCommentNotationTransformer(
142
- name,
143
- new RegExp(`\\s*\\[!code (${Object.keys(classMap).map(escapeRegExp).join("|")})(:\\d+)?\\]`),
144
- function([_, match, range = ":1"], _line, _comment, lines, index) {
145
- const lineNum = Number.parseInt(range.slice(1), 10);
146
- for (let i = index; i < Math.min(index + lineNum, lines.length); i++) {
147
- this.addClassToHast(lines[i], classMap[match]);
148
- }
149
- if (classActivePre)
150
- this.addClassToHast(this.pre, classActivePre);
151
- return true;
152
- }
153
- );
154
- }
155
- function transformerNotationDiff(options = {}) {
156
- const {
157
- classLineAdd = "diff add",
158
- classLineRemove = "diff remove",
159
- classActivePre = "has-diff"
160
- } = options;
161
- return transformerNotationMap(
162
- {
163
- classMap: {
164
- "++": classLineAdd,
165
- "--": classLineRemove
166
- },
167
- classActivePre
168
- },
169
- "@shikijs/transformers:notation-diff"
170
- );
171
- }
172
- function transformerNotationHighlight(options = {}) {
173
- const {
174
- classActiveLine = "highlighted",
175
- classActivePre = "has-highlighted"
176
- } = options;
177
- return transformerNotationMap(
178
- {
179
- classMap: {
180
- highlight: classActiveLine,
181
- hl: classActiveLine
182
- },
183
- classActivePre
184
- },
185
- "@shikijs/transformers:notation-highlight"
186
- );
187
- }
188
- function highlightWordInLine(line, ignoredElement, word, className) {
189
- const content = getTextContent(line);
190
- let index = content.indexOf(word);
191
- while (index !== -1) {
192
- highlightRange.call(this, line.children, ignoredElement, index, word.length, className);
193
- index = content.indexOf(word, index + 1);
194
- }
195
- }
196
- function getTextContent(element) {
197
- if (element.type === "text")
198
- return element.value;
199
- if (element.type === "element" && element.tagName === "span")
200
- return element.children.map(getTextContent).join("");
201
- return "";
202
- }
203
- function highlightRange(elements, ignoredElement, index, len, className) {
204
- let currentIdx = 0;
205
- for (let i = 0; i < elements.length; i++) {
206
- const element = elements[i];
207
- if (element.type !== "element" || element.tagName !== "span" || element === ignoredElement)
208
- continue;
209
- const textNode = element.children[0];
210
- if (textNode.type !== "text")
211
- continue;
212
- if (hasOverlap([currentIdx, currentIdx + textNode.value.length - 1], [index, index + len])) {
213
- const start = Math.max(0, index - currentIdx);
214
- const length = len - Math.max(0, currentIdx - index);
215
- if (length === 0)
216
- continue;
217
- const separated = separateToken(element, textNode, start, length);
218
- this.addClassToHast(separated[1], className);
219
- const output = separated.filter(Boolean);
220
- elements.splice(i, 1, ...output);
221
- i += output.length - 1;
222
- }
223
- currentIdx += textNode.value.length;
224
- }
225
- }
226
- function hasOverlap(range1, range2) {
227
- return range1[0] <= range2[1] && range1[1] >= range2[0];
228
- }
229
- function separateToken(span, textNode, index, len) {
230
- const text = textNode.value;
231
- const createNode = (value) => inheritElement(span, {
232
- children: [
233
- {
234
- type: "text",
235
- value
236
- }
237
- ]
238
- });
239
- return [
240
- index > 0 ? createNode(text.slice(0, index)) : void 0,
241
- createNode(text.slice(index, index + len)),
242
- index + len < text.length ? createNode(text.slice(index + len)) : void 0
243
- ];
244
- }
245
- function inheritElement(original, overrides) {
246
- return {
247
- ...original,
248
- properties: {
249
- ...original.properties
250
- },
251
- ...overrides
252
- };
253
- }
254
- function transformerNotationWordHighlight(options = {}) {
255
- const {
256
- classActiveWord = "highlighted-word",
257
- classActivePre = void 0
258
- } = options;
259
- return createCommentNotationTransformer(
260
- "@shikijs/transformers:notation-highlight-word",
261
- /\s*\[!code word:((?:\\.|[^:\]])+)(:\d+)?\]/,
262
- function([_, word, range], _line, comment, lines, index) {
263
- const lineNum = range ? Number.parseInt(range.slice(1), 10) : lines.length;
264
- word = word.replace(/\\(.)/g, "$1");
265
- for (let i = index; i < Math.min(index + lineNum, lines.length); i++) {
266
- highlightWordInLine.call(this, lines[i], comment, word, classActiveWord);
267
- }
268
- if (classActivePre)
269
- this.addClassToHast(this.pre, classActivePre);
270
- return true;
271
- }
272
- );
273
- }
274
- var symbol = Symbol("highlighted-lines");
275
-
276
- // src/mdx-plugins/rehype-code.ts
22
+ import {
23
+ transformerNotationDiff,
24
+ transformerNotationHighlight,
25
+ transformerNotationWordHighlight
26
+ } from "@shikijs/transformers";
277
27
  import {
278
28
  getSingletonHighlighter,
279
29
  bundledLanguages
@@ -450,9 +200,15 @@ var rehypeCodeDefaultOptions = {
450
200
  experimentalJSEngine: false,
451
201
  transformers: [
452
202
  createStyleTransformer(),
453
- transformerNotationHighlight(),
454
- transformerNotationWordHighlight(),
455
- transformerNotationDiff()
203
+ transformerNotationHighlight({
204
+ matchAlgorithm: "v3"
205
+ }),
206
+ transformerNotationWordHighlight({
207
+ matchAlgorithm: "v3"
208
+ }),
209
+ transformerNotationDiff({
210
+ matchAlgorithm: "v3"
211
+ })
456
212
  ],
457
213
  parseMetaString(meta) {
458
214
  const map = {};
@@ -467,53 +223,44 @@ var rehypeCodeDefaultOptions = {
467
223
  return map;
468
224
  }
469
225
  };
470
- function rehypeCode(options = {}) {
471
- const codeOptions = {
226
+ function rehypeCode(_options = {}) {
227
+ const options = {
472
228
  ...rehypeCodeDefaultOptions,
473
- ...options
229
+ ..._options
474
230
  };
475
- codeOptions.transformers ||= [];
476
- codeOptions.transformers = [
477
- {
478
- name: "rehype-code:pre-process",
479
- preprocess(code, { meta }) {
480
- if (meta && "__parsed_raw" in meta) {
481
- meta.__raw = meta.__parsed_raw;
482
- delete meta.__parsed_raw;
483
- }
484
- if (meta && codeOptions.filterMetaString) {
485
- meta.__raw = codeOptions.filterMetaString(meta.__raw ?? "");
486
- }
487
- return code.replace(/\n$/, "");
231
+ const transformers = [...options.transformers ?? []];
232
+ transformers.unshift({
233
+ name: "rehype-code:pre-process",
234
+ preprocess(code, { meta }) {
235
+ if (meta && "__parsed_raw" in meta) {
236
+ meta.__raw = meta.__parsed_raw;
237
+ delete meta.__parsed_raw;
488
238
  }
489
- },
490
- ...codeOptions.transformers
491
- ];
492
- if (codeOptions.icon !== false) {
493
- codeOptions.transformers = [
494
- ...codeOptions.transformers,
495
- transformerIcon(codeOptions.icon)
496
- ];
497
- }
498
- if (codeOptions.tab !== false) {
499
- codeOptions.transformers = [...codeOptions.transformers, transformerTab()];
239
+ if (meta && options.filterMetaString) {
240
+ meta.__raw = options.filterMetaString(meta.__raw ?? "");
241
+ }
242
+ return code.replace(/\n$/, "");
243
+ }
244
+ });
245
+ if (options.icon !== false) {
246
+ transformers.push(transformerIcon(options.icon));
500
247
  }
501
- let themeItems = [];
502
- if ("themes" in codeOptions) {
503
- themeItems = Object.values(codeOptions.themes);
504
- } else if ("theme" in codeOptions) {
505
- themeItems = [codeOptions.theme];
248
+ if (options.tab !== false) {
249
+ transformers.push(transformerTab());
506
250
  }
507
251
  const highlighter = getSingletonHighlighter({
508
- engine: codeOptions.experimentalJSEngine ? createJavaScriptRegexEngine() : createOnigurumaEngine(() => import("shiki/wasm")),
509
- themes: themeItems.filter(Boolean),
510
- langs: codeOptions.langs ?? Object.keys(bundledLanguages)
252
+ engine: options.experimentalJSEngine ? createJavaScriptRegexEngine() : createOnigurumaEngine(() => import("shiki/wasm")),
253
+ themes: "themes" in options ? Object.values(options.themes).filter(Boolean) : [options.theme],
254
+ langs: options.langs ?? (options.lazy ? void 0 : Object.keys(bundledLanguages))
511
255
  });
512
256
  const transformer = highlighter.then(
513
- (instance) => rehypeShikiFromHighlighter(instance, codeOptions)
257
+ (instance) => rehypeShikiFromHighlighter(instance, {
258
+ ...options,
259
+ transformers
260
+ })
514
261
  );
515
262
  return async (tree, file) => {
516
- (await transformer)(tree, file, () => {
263
+ await (await transformer)(tree, file, () => {
517
264
  });
518
265
  };
519
266
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-core",
3
- "version": "14.7.5",
3
+ "version": "14.7.7",
4
4
  "description": "The library for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -79,7 +79,8 @@
79
79
  "dependencies": {
80
80
  "@formatjs/intl-localematcher": "^0.5.10",
81
81
  "@orama/orama": "^2.1.1",
82
- "@shikijs/rehype": "^1.27.2",
82
+ "@shikijs/rehype": "^2.0.3",
83
+ "@shikijs/transformers": "^2.0.3",
83
84
  "github-slugger": "^2.0.0",
84
85
  "hast-util-to-estree": "^3.1.1",
85
86
  "hast-util-to-jsx-runtime": "^2.3.2",
@@ -89,7 +90,7 @@
89
90
  "remark": "^15.0.0",
90
91
  "remark-gfm": "^4.0.0",
91
92
  "scroll-into-view-if-needed": "^3.1.0",
92
- "shiki": "^1.27.2",
93
+ "shiki": "^2.0.3",
93
94
  "unist-util-visit": "^5.0.0"
94
95
  },
95
96
  "devDependencies": {
@@ -110,7 +111,6 @@
110
111
  "next": "^15.1.5",
111
112
  "remark-mdx": "^3.1.0",
112
113
  "remark-rehype": "^11.1.1",
113
- "shiki-transformers": "^1.0.1",
114
114
  "typescript": "^5.7.3",
115
115
  "unified": "^11.0.5",
116
116
  "vfile": "^6.0.3",