@shikijs/rehype 1.19.0 → 1.20.0

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/dist/core.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { HighlighterGeneric } from '@shikijs/types';
2
2
  import { Root } from 'hast';
3
3
  import { Transformer } from 'unified';
4
- import { R as RehypeShikiCoreOptions } from './shared/rehype.198b1df4.mjs';
5
- export { M as MapLike, a as RehypeShikiExtraOptions } from './shared/rehype.198b1df4.mjs';
4
+ import { R as RehypeShikiCoreOptions } from './shared/rehype.7b862995.mjs';
5
+ export { M as MapLike, a as RehypeShikiExtraOptions } from './shared/rehype.7b862995.mjs';
6
6
  import 'shiki';
7
7
 
8
8
  declare function rehypeShikiFromHighlighter(highlighter: HighlighterGeneric<any, any>, options: RehypeShikiCoreOptions): Transformer<Root, Root>;
package/dist/core.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { HighlighterGeneric } from '@shikijs/types';
2
2
  import { Root } from 'hast';
3
3
  import { Transformer } from 'unified';
4
- import { R as RehypeShikiCoreOptions } from './shared/rehype.198b1df4.js';
5
- export { M as MapLike, a as RehypeShikiExtraOptions } from './shared/rehype.198b1df4.js';
4
+ import { R as RehypeShikiCoreOptions } from './shared/rehype.7b862995.js';
5
+ export { M as MapLike, a as RehypeShikiExtraOptions } from './shared/rehype.7b862995.js';
6
6
  import 'shiki';
7
7
 
8
8
  declare function rehypeShikiFromHighlighter(highlighter: HighlighterGeneric<any, any>, options: RehypeShikiCoreOptions): Transformer<Root, Root>;
package/dist/core.mjs CHANGED
@@ -1,30 +1,39 @@
1
- import { toString } from 'hast-util-to-string';
2
1
  import { visit } from 'unist-util-visit';
2
+ import { toString } from 'hast-util-to-string';
3
3
 
4
- const InlineCodeProcessors = {
5
- "tailing-curly-colon": ({ node, getLanguage, highlight }) => {
4
+ const InlineCodeHandlers = {
5
+ "tailing-curly-colon": (_tree, node) => {
6
6
  const raw = toString(node);
7
7
  const match = raw.match(/(.+)\{:([\w-]+)\}$/);
8
8
  if (!match)
9
9
  return;
10
- const lang = getLanguage(match[2]);
11
- if (!lang)
12
- return;
13
- const code = match[1] ?? raw;
14
- const fragment = highlight(lang, code);
15
- if (!fragment)
16
- return;
17
- const head = fragment.children[0];
18
- if (head.type === "element" && head.tagName === "pre") {
19
- head.tagName = "span";
20
- }
21
- return fragment;
10
+ return {
11
+ type: "inline",
12
+ code: match[1] ?? raw,
13
+ lang: match.at(2)
14
+ };
22
15
  }
23
16
  };
17
+ const languagePrefix$1 = "language-";
18
+ const PreHandler = (_tree, node) => {
19
+ const head = node.children[0];
20
+ if (!head || head.type !== "element" || head.tagName !== "code" || !head.properties) {
21
+ return;
22
+ }
23
+ const classes = head.properties.className;
24
+ const languageClass = Array.isArray(classes) ? classes.find(
25
+ (d) => typeof d === "string" && d.startsWith(languagePrefix$1)
26
+ ) : void 0;
27
+ return {
28
+ type: "pre",
29
+ lang: typeof languageClass === "string" ? languageClass.slice(languagePrefix$1.length) : void 0,
30
+ code: toString(head),
31
+ meta: head.data?.meta ?? head.properties.metastring?.toString() ?? ""
32
+ };
33
+ };
24
34
 
25
35
  const languagePrefix = "language-";
26
36
  function rehypeShikiFromHighlighter(highlighter, options) {
27
- const langs = highlighter.getLoadedLanguages();
28
37
  const {
29
38
  addLanguageClass = false,
30
39
  parseMetaString,
@@ -34,13 +43,9 @@ function rehypeShikiFromHighlighter(highlighter, options) {
34
43
  onError,
35
44
  stripEndNewline = true,
36
45
  inline = false,
46
+ lazy = false,
37
47
  ...rest
38
48
  } = options;
39
- function getLanguage(lang = defaultLanguage) {
40
- if (lang && fallbackLanguage && !langs.includes(lang))
41
- return fallbackLanguage;
42
- return lang;
43
- }
44
49
  function highlight(lang, code, metaString = "", meta = {}) {
45
50
  const cacheKey = `${lang}:${metaString}:${code}`;
46
51
  const cachedValue = cache?.get(cacheKey);
@@ -81,43 +86,63 @@ function rehypeShikiFromHighlighter(highlighter, options) {
81
86
  throw error;
82
87
  }
83
88
  }
84
- function processPre(tree, node) {
85
- const head = node.children[0];
86
- if (!head || head.type !== "element" || head.tagName !== "code" || !head.properties) {
87
- return;
89
+ return (tree) => {
90
+ const languageQueue = [];
91
+ const queue = [];
92
+ function getLanguage(lang) {
93
+ if (!lang)
94
+ return defaultLanguage;
95
+ if (highlighter.getLoadedLanguages().includes(lang))
96
+ return lang;
97
+ if (lazy) {
98
+ languageQueue.push(lang);
99
+ return lang;
100
+ }
101
+ if (fallbackLanguage)
102
+ return fallbackLanguage;
88
103
  }
89
- const classes = head.properties.className;
90
- const languageClass = Array.isArray(classes) ? classes.find(
91
- (d) => typeof d === "string" && d.startsWith(languagePrefix)
92
- ) : void 0;
93
- const lang = getLanguage(
94
- typeof languageClass === "string" ? languageClass.slice(languagePrefix.length) : void 0
95
- );
96
- if (!lang)
97
- return;
98
- const code = toString(head);
99
- const metaString = head.data?.meta ?? head.properties.metastring?.toString() ?? "";
100
- const meta = parseMetaString?.(metaString, node, tree) || {};
101
- return highlight(lang, code, metaString, meta);
102
- }
103
- return function(tree) {
104
104
  visit(tree, "element", (node, index, parent) => {
105
+ let handler;
105
106
  if (!parent || index == null)
106
107
  return;
107
108
  if (node.tagName === "pre") {
108
- const result = processPre(tree, node);
109
- if (result) {
110
- parent.children.splice(index, 1, ...result.children);
111
- }
112
- return "skip";
109
+ handler = PreHandler;
113
110
  }
114
111
  if (node.tagName === "code" && inline) {
115
- const result = InlineCodeProcessors[inline]?.({ node, getLanguage, highlight });
116
- if (result) {
117
- parent.children.splice(index, 1, ...result.children);
118
- }
112
+ handler = InlineCodeHandlers[inline];
119
113
  }
114
+ if (!handler)
115
+ return;
116
+ const res = handler(tree, node);
117
+ if (!res)
118
+ return;
119
+ const lang = getLanguage(res.lang);
120
+ if (!lang)
121
+ return;
122
+ const processNode = () => {
123
+ const meta = res.meta ? parseMetaString?.(res.meta, node, tree) : void 0;
124
+ const fragment = highlight(lang, res.code, res.meta, meta ?? {});
125
+ if (!fragment)
126
+ return;
127
+ if (res.type === "inline") {
128
+ const head = fragment.children[0];
129
+ if (head.type === "element" && head.tagName === "pre") {
130
+ head.tagName = "span";
131
+ }
132
+ }
133
+ parent.children.splice(index, 1, ...fragment.children);
134
+ };
135
+ if (lazy)
136
+ queue.push(processNode);
137
+ else
138
+ processNode();
139
+ return "skip";
120
140
  });
141
+ if (lazy) {
142
+ return highlighter.loadLanguage(...languageQueue).then(() => {
143
+ queue.forEach((fn) => fn());
144
+ });
145
+ }
121
146
  };
122
147
  }
123
148
 
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import { LanguageInput } from '@shikijs/types';
2
2
  import { Root } from 'hast';
3
3
  import { BuiltinLanguage } from 'shiki';
4
4
  import { Plugin } from 'unified';
5
- import { R as RehypeShikiCoreOptions } from './shared/rehype.198b1df4.mjs';
5
+ import { R as RehypeShikiCoreOptions } from './shared/rehype.7b862995.mjs';
6
6
 
7
7
  type RehypeShikiOptions = RehypeShikiCoreOptions & {
8
8
  /**
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { LanguageInput } from '@shikijs/types';
2
2
  import { Root } from 'hast';
3
3
  import { BuiltinLanguage } from 'shiki';
4
4
  import { Plugin } from 'unified';
5
- import { R as RehypeShikiCoreOptions } from './shared/rehype.198b1df4.js';
5
+ import { R as RehypeShikiCoreOptions } from './shared/rehype.7b862995.js';
6
6
 
7
7
  type RehypeShikiOptions = RehypeShikiCoreOptions & {
8
8
  /**
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { bundledLanguages, getSingletonHighlighter } from 'shiki';
2
2
  import rehypeShikiFromHighlighter from './core.mjs';
3
- import 'hast-util-to-string';
4
3
  import 'unist-util-visit';
4
+ import 'hast-util-to-string';
5
5
 
6
6
  const rehypeShiki = function(options = {}) {
7
7
  const themeNames = ("themes" in options ? Object.values(options.themes) : [options.theme]).filter(Boolean);
@@ -18,8 +18,17 @@ interface RehypeShikiExtraOptions {
18
18
  defaultLanguage?: string;
19
19
  /**
20
20
  * The fallback language to use when specified language is not loaded
21
+ *
22
+ * Ignored if `lazy` is enabled
21
23
  */
22
24
  fallbackLanguage?: string;
25
+ /**
26
+ * Load languages and themes on-demand.
27
+ * When enable, this would make requires the unified pipeline to be async.
28
+ *
29
+ * @default false
30
+ */
31
+ lazy?: boolean;
23
32
  /**
24
33
  * `mdast-util-to-hast` adds a newline to the end of code blocks
25
34
  *
@@ -18,8 +18,17 @@ interface RehypeShikiExtraOptions {
18
18
  defaultLanguage?: string;
19
19
  /**
20
20
  * The fallback language to use when specified language is not loaded
21
+ *
22
+ * Ignored if `lazy` is enabled
21
23
  */
22
24
  fallbackLanguage?: string;
25
+ /**
26
+ * Load languages and themes on-demand.
27
+ * When enable, this would make requires the unified pipeline to be async.
28
+ *
29
+ * @default false
30
+ */
31
+ lazy?: boolean;
23
32
  /**
24
33
  * `mdast-util-to-hast` adds a newline to the end of code blocks
25
34
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/rehype",
3
3
  "type": "module",
4
- "version": "1.19.0",
4
+ "version": "1.20.0",
5
5
  "description": "rehype integration for shiki",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -49,15 +49,15 @@
49
49
  "hast-util-to-string": "^3.0.0",
50
50
  "unified": "^11.0.5",
51
51
  "unist-util-visit": "^5.0.0",
52
- "@shikijs/types": "1.19.0",
53
- "shiki": "1.19.0"
52
+ "@shikijs/types": "1.20.0",
53
+ "shiki": "1.20.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "rehype-raw": "^7.0.0",
57
57
  "rehype-stringify": "^10.0.0",
58
58
  "remark-parse": "^11.0.0",
59
59
  "remark-rehype": "^11.1.1",
60
- "@shikijs/transformers": "1.19.0"
60
+ "@shikijs/transformers": "1.20.0"
61
61
  },
62
62
  "scripts": {
63
63
  "build": "unbuild",