@shikijs/twoslash 4.0.2 → 4.1.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.
@@ -1,3 +1,4 @@
1
+ import { splitTokens } from "@shikijs/core";
1
2
  //#region src/error.ts
2
3
  var ShikiTwoslashError = class extends Error {
3
4
  constructor(message) {
@@ -5,10 +6,11 @@ var ShikiTwoslashError = class extends Error {
5
6
  this.name = "ShikiTwoslashError";
6
7
  }
7
8
  };
8
-
9
9
  //#endregion
10
10
  //#region src/includes.ts
11
+ const RE_INCLUDE_MARKER = /\/\/ @include: (.*)$/gm;
11
12
  var TwoslashIncludesManager = class {
13
+ map;
12
14
  constructor(map = /* @__PURE__ */ new Map()) {
13
15
  this.map = map;
14
16
  }
@@ -24,13 +26,12 @@ var TwoslashIncludesManager = class {
24
26
  this.map.set(name, lines.join("\n"));
25
27
  }
26
28
  applyInclude(code) {
27
- const reMarker = /\/\/ @include: (.*)$/gm;
28
29
  const toReplace = [];
29
- for (const match of code.matchAll(reMarker)) {
30
+ for (const match of code.matchAll(RE_INCLUDE_MARKER)) {
30
31
  const key = match[1];
31
32
  const replaceWith = this.map.get(key);
32
33
  if (!replaceWith) {
33
- const msg = `Could not find an include with the key: '${key}'.\nThere is: ${Array.from(this.map.keys())}.`;
34
+ const msg = `Could not find an include with the key: '${key}'.\nThere is: ${[...this.map.keys()]}.`;
34
35
  throw new Error(msg);
35
36
  } else toReplace.push([
36
37
  match.index,
@@ -58,7 +59,6 @@ function parseIncludeMeta(meta) {
58
59
  if (!meta) return null;
59
60
  return meta.match(INCLUDE_META_REGEX)?.[1] ?? null;
60
61
  }
61
-
62
62
  //#endregion
63
63
  //#region src/icons-completions.json
64
64
  var icons_completions_default = {
@@ -261,7 +261,6 @@ var icons_completions_default = {
261
261
  }]
262
262
  }
263
263
  };
264
-
265
264
  //#endregion
266
265
  //#region src/icons-tags.json
267
266
  var icons_tags_default = {
@@ -346,12 +345,10 @@ var icons_tags_default = {
346
345
  }]
347
346
  }
348
347
  };
349
-
350
348
  //#endregion
351
349
  //#region src/icons.ts
352
350
  const defaultCompletionIcons = icons_completions_default;
353
351
  const defaultCustomTagIcons = icons_tags_default;
354
-
355
352
  //#endregion
356
353
  //#region src/renderer-classic.ts
357
354
  /**
@@ -493,7 +490,6 @@ function rendererClassic() {
493
490
  }
494
491
  };
495
492
  }
496
-
497
493
  //#endregion
498
494
  //#region src/renderer-rich.ts
499
495
  function extend(extension, node) {
@@ -509,6 +505,7 @@ function extend(extension, node) {
509
505
  children: extension.children?.(node.children) ?? node.children
510
506
  };
511
507
  }
508
+ const RE_WHITESPACE_CHAR = /\s/g;
512
509
  function renderMarkdownPassThrough(markdown) {
513
510
  return [{
514
511
  type: "text",
@@ -643,7 +640,7 @@ function rendererRich(options = {}) {
643
640
  children: [...completionIcons ? [{
644
641
  type: "element",
645
642
  tagName: "span",
646
- properties: { class: `twoslash-completions-icon completions-${kind.replace(/\s/g, "-")}` },
643
+ properties: { class: `twoslash-completions-icon completions-${kind.replace(RE_WHITESPACE_CHAR, "-")}` },
647
644
  children: [completionIcons[kind] || completionIcons.property].filter(Boolean)
648
645
  }] : [], {
649
646
  type: "element",
@@ -803,15 +800,18 @@ function rendererRich(options = {}) {
803
800
  }
804
801
  };
805
802
  }
806
- const regexType = /^[A-Z]\w*(<[^>]*>)?:/;
803
+ const RE_LEADING_MODIFIER = /^\(([\w-]+)\)\s+/gm;
804
+ const RE_IMPORT_STATEMENT = /\nimport .*$/;
805
+ const RE_INTERFACE_NAMESPACE = /^(interface|namespace) \w+$/gm;
806
+ const regexType = /^[A-Z]\w*(?:<[^>]*>)?:/;
807
807
  const regexFunction = /^\w*\(/;
808
808
  /**
809
809
  * The default hover info processor, which will do some basic cleanup
810
810
  */
811
811
  function defaultHoverInfoProcessor(type) {
812
- let content = type.replace(/^\(([\w-]+)\)\s+/gm, "").replace(/\nimport .*$/, "").replace(/^(interface|namespace) \w+$/gm, "").trim();
813
- if (content.match(regexType)) content = `type ${content}`;
814
- else if (content.match(regexFunction)) content = `function ${content}`;
812
+ let content = type.replace(RE_LEADING_MODIFIER, "").replace(RE_IMPORT_STATEMENT, "").replace(RE_INTERFACE_NAMESPACE, "").trim();
813
+ if (regexType.test(content)) content = `type ${content}`;
814
+ else if (regexFunction.test(content)) content = `function ${content}`;
815
815
  return content;
816
816
  }
817
817
  function getErrorLevelClass(error) {
@@ -822,6 +822,215 @@ function getErrorLevelClass(error) {
822
822
  default: return "";
823
823
  }
824
824
  }
825
-
826
825
  //#endregion
827
- export { defaultCustomTagIcons as a, ShikiTwoslashError as c, defaultCompletionIcons as i, rendererRich as n, TwoslashIncludesManager as o, rendererClassic as r, parseIncludeMeta as s, defaultHoverInfoProcessor as t };
826
+ //#region src/core.ts
827
+ const RE_TWOSLASH = /\btwoslash\b/;
828
+ function defaultTwoslashOptions() {
829
+ return {
830
+ customTags: [
831
+ "annotate",
832
+ "log",
833
+ "warn",
834
+ "error"
835
+ ],
836
+ compilerOptions: { moduleResolution: 100 }
837
+ };
838
+ }
839
+ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
840
+ return function transformerTwoslash(options = {}) {
841
+ const { langs = ["ts", "tsx"], twoslashOptions = defaultTwoslashOptions(), langAlias = {
842
+ typescript: "ts",
843
+ json5: "json",
844
+ yml: "yaml"
845
+ }, twoslasher = defaultTwoslasher, explicitTrigger = false, disableTriggers = ["notwoslash", "no-twoslash"], renderer = defaultRenderer, throws = true, includesMap = /* @__PURE__ */ new Map(), typesCache } = options;
846
+ const onTwoslashError = options.onTwoslashError || (throws ? (error) => {
847
+ throw error;
848
+ } : () => false);
849
+ const onShikiError = options.onShikiError || (throws ? (error) => {
850
+ throw error;
851
+ } : () => false);
852
+ const trigger = explicitTrigger instanceof RegExp ? explicitTrigger : RE_TWOSLASH;
853
+ if (!renderer) throw new ShikiTwoslashError("Missing renderer");
854
+ const map = /* @__PURE__ */ new WeakMap();
855
+ const { filter = (lang, _, options) => {
856
+ return langs.includes(lang) && (!explicitTrigger || trigger.test(options.meta?.__raw || "")) && !disableTriggers.some((i) => typeof i === "string" ? options.meta?.__raw?.includes(i) : i.test(options.meta?.__raw || ""));
857
+ } } = options;
858
+ const includes = new TwoslashIncludesManager(includesMap);
859
+ let _twoslasher = twoslasher;
860
+ if (typesCache) {
861
+ _twoslasher = ((code, lang, options, meta) => {
862
+ const preprocessed = typesCache?.preprocess?.(code, lang, options, meta);
863
+ if (preprocessed !== void 0) code = preprocessed;
864
+ let twoslash = typesCache?.read(code, lang, options, meta);
865
+ if (!twoslash) {
866
+ twoslash = twoslasher(code, lang, options);
867
+ typesCache?.write(code, twoslash, lang, options, meta);
868
+ }
869
+ return twoslash;
870
+ });
871
+ typesCache.init?.();
872
+ }
873
+ return {
874
+ preprocess(code) {
875
+ let lang = this.options.lang;
876
+ if (lang in langAlias) lang = langAlias[this.options.lang];
877
+ if (filter(lang, code, this.options, this)) try {
878
+ const codeWithIncludes = includes.applyInclude(code);
879
+ const include = parseIncludeMeta(this.options.meta?.__raw);
880
+ if (include) includes.add(include, codeWithIncludes);
881
+ const twoslash = _twoslasher(codeWithIncludes, lang, twoslashOptions, this.meta);
882
+ map.set(this.meta, twoslash);
883
+ this.meta.twoslash = twoslash;
884
+ this.options.lang = twoslash.meta?.extension || lang;
885
+ return twoslash.code;
886
+ } catch (error) {
887
+ const result = onTwoslashError(error, code, lang, this.options);
888
+ if (typeof result === "string") return result;
889
+ }
890
+ },
891
+ tokens(tokens) {
892
+ const twoslash = map.get(this.meta);
893
+ if (!twoslash) return;
894
+ return splitTokens(tokens, twoslash.nodes.flatMap((i) => [
895
+ "hover",
896
+ "error",
897
+ "query",
898
+ "highlight",
899
+ "completion"
900
+ ].includes(i.type) ? [i.start, i.start + i.length] : []));
901
+ },
902
+ pre(pre) {
903
+ if (!map.get(this.meta)) return;
904
+ this.addClassToHast(pre, "twoslash lsp");
905
+ },
906
+ code(codeEl) {
907
+ const twoslash = map.get(this.meta);
908
+ if (!twoslash) return;
909
+ const insertAfterLine = (line, nodes) => {
910
+ if (!nodes.length) return;
911
+ let index;
912
+ if (line >= this.lines.length) index = codeEl.children.length;
913
+ else {
914
+ const lineEl = this.lines[line];
915
+ index = codeEl.children.indexOf(lineEl);
916
+ if (index === -1) {
917
+ onShikiError(new ShikiTwoslashError(`Cannot find line ${line} in code element`), this.source, this.options.lang);
918
+ return;
919
+ }
920
+ }
921
+ const nodeAfter = codeEl.children[index + 1];
922
+ if (nodeAfter && nodeAfter.type === "text" && nodeAfter.value === "\n") codeEl.children.splice(index + 1, 1);
923
+ codeEl.children.splice(index + 1, 0, ...nodes);
924
+ };
925
+ const tokensMap = [];
926
+ this.lines.forEach((lineEl, line) => {
927
+ let index = 0;
928
+ for (const token of lineEl.children.flatMap((i) => i.type === "element" ? i.children || [] : [])) if ("value" in token && typeof token.value === "string") {
929
+ tokensMap.push([
930
+ line,
931
+ index,
932
+ index + token.value.length,
933
+ token
934
+ ]);
935
+ index += token.value.length;
936
+ }
937
+ });
938
+ const locateTextTokens = (line, character, length) => {
939
+ const start = character;
940
+ const end = character + length;
941
+ if (length === 0) return tokensMap.filter(([l, s, e]) => l === line && s < start && start <= e).map((i) => i[3]);
942
+ return tokensMap.filter(([l, s, e]) => l === line && start <= s && s < end && start < e && e <= end).map((i) => i[3]);
943
+ };
944
+ const tokensSkipHover = /* @__PURE__ */ new Set();
945
+ const actionsHovers = [];
946
+ const actionsHighlights = [];
947
+ for (const node of twoslash.nodes) {
948
+ if (node.type === "tag") {
949
+ if (renderer.lineCustomTag) insertAfterLine(node.line, renderer.lineCustomTag.call(this, node));
950
+ continue;
951
+ }
952
+ const tokens = locateTextTokens(node.line, node.character, node.length);
953
+ if (!tokens.length && !(node.type === "error" && renderer.nodesError)) {
954
+ onShikiError(new ShikiTwoslashError(`Cannot find tokens for node: ${JSON.stringify(node)}`), this.source, this.options.lang);
955
+ continue;
956
+ }
957
+ const wrapTokens = (fn) => {
958
+ const line = this.lines[node.line];
959
+ let charIndex = 0;
960
+ let itemStart = line.children.length;
961
+ let itemEnd = 0;
962
+ line.children.forEach((token, index) => {
963
+ if (charIndex >= node.character && index < itemStart) itemStart = index;
964
+ if (charIndex <= node.character + node.length && index > itemEnd) itemEnd = index;
965
+ charIndex += getTokenString(token).length;
966
+ });
967
+ if (charIndex <= node.character + node.length) itemEnd = line.children.length;
968
+ const targets = line.children.slice(itemStart, itemEnd);
969
+ const length = targets.length;
970
+ line.children.splice(itemStart, length, ...fn(targets));
971
+ };
972
+ switch (node.type) {
973
+ case "error":
974
+ if (renderer.nodeError) tokens.forEach((token) => {
975
+ tokensSkipHover.add(token);
976
+ const clone = { ...token };
977
+ Object.assign(token, renderer.nodeError.call(this, node, clone));
978
+ });
979
+ if (renderer.nodesError) {
980
+ tokens.forEach((token) => {
981
+ tokensSkipHover.add(token);
982
+ });
983
+ actionsHighlights.push(() => {
984
+ wrapTokens((targets) => renderer.nodesError?.call(this, node, targets) || targets);
985
+ });
986
+ }
987
+ if (renderer.lineError) insertAfterLine(node.line, renderer.lineError.call(this, node));
988
+ break;
989
+ case "query": {
990
+ const token = tokens[0];
991
+ if (token && renderer.nodeQuery) {
992
+ tokensSkipHover.add(token);
993
+ const clone = { ...token };
994
+ Object.assign(token, renderer.nodeQuery.call(this, node, clone));
995
+ }
996
+ if (renderer.lineQuery) insertAfterLine(node.line, renderer.lineQuery.call(this, node, token));
997
+ break;
998
+ }
999
+ case "completion":
1000
+ if (renderer.nodeCompletion) tokens.forEach((token) => {
1001
+ tokensSkipHover.add(token);
1002
+ const clone = { ...token };
1003
+ Object.assign(token, renderer.nodeCompletion.call(this, node, clone));
1004
+ });
1005
+ if (renderer.lineCompletion) insertAfterLine(node.line, renderer.lineCompletion.call(this, node));
1006
+ break;
1007
+ case "highlight":
1008
+ if (renderer.nodesHighlight) actionsHighlights.push(() => {
1009
+ wrapTokens((targets) => renderer.nodesHighlight?.call(this, node, targets) || targets);
1010
+ });
1011
+ break;
1012
+ case "hover":
1013
+ if (renderer.nodeStaticInfo) actionsHovers.push(() => {
1014
+ tokens.forEach((token) => {
1015
+ if (tokensSkipHover.has(token)) return;
1016
+ tokensSkipHover.add(token);
1017
+ const clone = { ...token };
1018
+ Object.assign(token, renderer.nodeStaticInfo.call(this, node, clone));
1019
+ });
1020
+ });
1021
+ break;
1022
+ default: onShikiError(new ShikiTwoslashError(`Unknown node type: ${node?.type}`), this.source, this.options.lang);
1023
+ }
1024
+ }
1025
+ actionsHovers.forEach((i) => i());
1026
+ actionsHighlights.forEach((i) => i());
1027
+ }
1028
+ };
1029
+ };
1030
+ }
1031
+ function getTokenString(token) {
1032
+ if ("value" in token) return token.value;
1033
+ return token.children?.map(getTokenString).join("") || "";
1034
+ }
1035
+ //#endregion
1036
+ export { rendererClassic as a, ShikiTwoslashError as c, rendererRich as i, defaultTwoslashOptions as n, defaultCompletionIcons as o, defaultHoverInfoProcessor as r, defaultCustomTagIcons as s, createTransformerFactory as t };
package/dist/core.mjs CHANGED
@@ -1,214 +1,2 @@
1
- import { a as defaultCustomTagIcons, c as ShikiTwoslashError, i as defaultCompletionIcons, n as rendererRich, o as TwoslashIncludesManager, r as rendererClassic, s as parseIncludeMeta, t as defaultHoverInfoProcessor } from "./renderer-rich-DEkszi0Z.mjs";
2
- import { splitTokens } from "@shikijs/core";
3
-
4
- //#region src/core.ts
5
- function defaultTwoslashOptions() {
6
- return {
7
- customTags: [
8
- "annotate",
9
- "log",
10
- "warn",
11
- "error"
12
- ],
13
- compilerOptions: { moduleResolution: 100 }
14
- };
15
- }
16
- function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
17
- return function transformerTwoslash(options = {}) {
18
- const { langs = ["ts", "tsx"], twoslashOptions = defaultTwoslashOptions(), langAlias = {
19
- typescript: "ts",
20
- json5: "json",
21
- yml: "yaml"
22
- }, twoslasher = defaultTwoslasher, explicitTrigger = false, disableTriggers = ["notwoslash", "no-twoslash"], renderer = defaultRenderer, throws = true, includesMap = /* @__PURE__ */ new Map(), typesCache } = options;
23
- const onTwoslashError = options.onTwoslashError || (throws ? (error) => {
24
- throw error;
25
- } : () => false);
26
- const onShikiError = options.onShikiError || (throws ? (error) => {
27
- throw error;
28
- } : () => false);
29
- const trigger = explicitTrigger instanceof RegExp ? explicitTrigger : /\btwoslash\b/;
30
- if (!renderer) throw new ShikiTwoslashError("Missing renderer");
31
- const map = /* @__PURE__ */ new WeakMap();
32
- const { filter = (lang, _, options) => {
33
- return langs.includes(lang) && (!explicitTrigger || trigger.test(options.meta?.__raw || "")) && !disableTriggers.some((i) => typeof i === "string" ? options.meta?.__raw?.includes(i) : i.test(options.meta?.__raw || ""));
34
- } } = options;
35
- const includes = new TwoslashIncludesManager(includesMap);
36
- let _twoslasher = twoslasher;
37
- if (typesCache) {
38
- _twoslasher = ((code, lang, options, meta) => {
39
- const preprocessed = typesCache?.preprocess?.(code, lang, options, meta);
40
- if (preprocessed !== void 0) code = preprocessed;
41
- let twoslash = typesCache?.read(code, lang, options, meta);
42
- if (!twoslash) {
43
- twoslash = twoslasher(code, lang, options);
44
- typesCache?.write(code, twoslash, lang, options, meta);
45
- }
46
- return twoslash;
47
- });
48
- typesCache.init?.();
49
- }
50
- return {
51
- preprocess(code) {
52
- let lang = this.options.lang;
53
- if (lang in langAlias) lang = langAlias[this.options.lang];
54
- if (filter(lang, code, this.options, this)) try {
55
- const codeWithIncludes = includes.applyInclude(code);
56
- const include = parseIncludeMeta(this.options.meta?.__raw);
57
- if (include) includes.add(include, codeWithIncludes);
58
- const twoslash = _twoslasher(codeWithIncludes, lang, twoslashOptions, this.meta);
59
- map.set(this.meta, twoslash);
60
- this.meta.twoslash = twoslash;
61
- this.options.lang = twoslash.meta?.extension || lang;
62
- return twoslash.code;
63
- } catch (error) {
64
- const result = onTwoslashError(error, code, lang, this.options);
65
- if (typeof result === "string") return result;
66
- }
67
- },
68
- tokens(tokens) {
69
- const twoslash = map.get(this.meta);
70
- if (!twoslash) return;
71
- return splitTokens(tokens, twoslash.nodes.flatMap((i) => [
72
- "hover",
73
- "error",
74
- "query",
75
- "highlight",
76
- "completion"
77
- ].includes(i.type) ? [i.start, i.start + i.length] : []));
78
- },
79
- pre(pre) {
80
- if (!map.get(this.meta)) return;
81
- this.addClassToHast(pre, "twoslash lsp");
82
- },
83
- code(codeEl) {
84
- const twoslash = map.get(this.meta);
85
- if (!twoslash) return;
86
- const insertAfterLine = (line, nodes) => {
87
- if (!nodes.length) return;
88
- let index;
89
- if (line >= this.lines.length) index = codeEl.children.length;
90
- else {
91
- const lineEl = this.lines[line];
92
- index = codeEl.children.indexOf(lineEl);
93
- if (index === -1) {
94
- onShikiError(new ShikiTwoslashError(`Cannot find line ${line} in code element`), this.source, this.options.lang);
95
- return;
96
- }
97
- }
98
- const nodeAfter = codeEl.children[index + 1];
99
- if (nodeAfter && nodeAfter.type === "text" && nodeAfter.value === "\n") codeEl.children.splice(index + 1, 1);
100
- codeEl.children.splice(index + 1, 0, ...nodes);
101
- };
102
- const tokensMap = [];
103
- this.lines.forEach((lineEl, line) => {
104
- let index = 0;
105
- for (const token of lineEl.children.flatMap((i) => i.type === "element" ? i.children || [] : [])) if ("value" in token && typeof token.value === "string") {
106
- tokensMap.push([
107
- line,
108
- index,
109
- index + token.value.length,
110
- token
111
- ]);
112
- index += token.value.length;
113
- }
114
- });
115
- const locateTextTokens = (line, character, length) => {
116
- const start = character;
117
- const end = character + length;
118
- if (length === 0) return tokensMap.filter(([l, s, e]) => l === line && s < start && start <= e).map((i) => i[3]);
119
- return tokensMap.filter(([l, s, e]) => l === line && start <= s && s < end && start < e && e <= end).map((i) => i[3]);
120
- };
121
- const tokensSkipHover = /* @__PURE__ */ new Set();
122
- const actionsHovers = [];
123
- const actionsHighlights = [];
124
- for (const node of twoslash.nodes) {
125
- if (node.type === "tag") {
126
- if (renderer.lineCustomTag) insertAfterLine(node.line, renderer.lineCustomTag.call(this, node));
127
- continue;
128
- }
129
- const tokens = locateTextTokens(node.line, node.character, node.length);
130
- if (!tokens.length && !(node.type === "error" && renderer.nodesError)) {
131
- onShikiError(new ShikiTwoslashError(`Cannot find tokens for node: ${JSON.stringify(node)}`), this.source, this.options.lang);
132
- continue;
133
- }
134
- const wrapTokens = (fn) => {
135
- const line = this.lines[node.line];
136
- let charIndex = 0;
137
- let itemStart = line.children.length;
138
- let itemEnd = 0;
139
- line.children.forEach((token, index) => {
140
- if (charIndex >= node.character && index < itemStart) itemStart = index;
141
- if (charIndex <= node.character + node.length && index > itemEnd) itemEnd = index;
142
- charIndex += getTokenString(token).length;
143
- });
144
- if (charIndex <= node.character + node.length) itemEnd = line.children.length;
145
- const targets = line.children.slice(itemStart, itemEnd);
146
- const length = targets.length;
147
- line.children.splice(itemStart, length, ...fn(targets));
148
- };
149
- switch (node.type) {
150
- case "error":
151
- if (renderer.nodeError) tokens.forEach((token) => {
152
- tokensSkipHover.add(token);
153
- const clone = { ...token };
154
- Object.assign(token, renderer.nodeError.call(this, node, clone));
155
- });
156
- if (renderer.nodesError) {
157
- tokens.forEach((token) => {
158
- tokensSkipHover.add(token);
159
- });
160
- actionsHighlights.push(() => {
161
- wrapTokens((targets) => renderer.nodesError?.call(this, node, targets) || targets);
162
- });
163
- }
164
- if (renderer.lineError) insertAfterLine(node.line, renderer.lineError.call(this, node));
165
- break;
166
- case "query": {
167
- const token = tokens[0];
168
- if (token && renderer.nodeQuery) {
169
- tokensSkipHover.add(token);
170
- const clone = { ...token };
171
- Object.assign(token, renderer.nodeQuery.call(this, node, clone));
172
- }
173
- if (renderer.lineQuery) insertAfterLine(node.line, renderer.lineQuery.call(this, node, token));
174
- break;
175
- }
176
- case "completion":
177
- if (renderer.nodeCompletion) tokens.forEach((token) => {
178
- tokensSkipHover.add(token);
179
- const clone = { ...token };
180
- Object.assign(token, renderer.nodeCompletion.call(this, node, clone));
181
- });
182
- if (renderer.lineCompletion) insertAfterLine(node.line, renderer.lineCompletion.call(this, node));
183
- break;
184
- case "highlight":
185
- if (renderer.nodesHighlight) actionsHighlights.push(() => {
186
- wrapTokens((targets) => renderer.nodesHighlight?.call(this, node, targets) || targets);
187
- });
188
- break;
189
- case "hover":
190
- if (renderer.nodeStaticInfo) actionsHovers.push(() => {
191
- tokens.forEach((token) => {
192
- if (tokensSkipHover.has(token)) return;
193
- tokensSkipHover.add(token);
194
- const clone = { ...token };
195
- Object.assign(token, renderer.nodeStaticInfo.call(this, node, clone));
196
- });
197
- });
198
- break;
199
- default: onShikiError(new ShikiTwoslashError(`Unknown node type: ${node?.type}`), this.source, this.options.lang);
200
- }
201
- }
202
- actionsHovers.forEach((i) => i());
203
- actionsHighlights.forEach((i) => i());
204
- }
205
- };
206
- };
207
- }
208
- function getTokenString(token) {
209
- if ("value" in token) return token.value;
210
- return token.children?.map(getTokenString).join("") || "";
211
- }
212
-
213
- //#endregion
214
- export { ShikiTwoslashError, createTransformerFactory, defaultCompletionIcons, defaultCustomTagIcons, defaultHoverInfoProcessor, defaultTwoslashOptions, rendererClassic, rendererRich };
1
+ import { a as rendererClassic, c as ShikiTwoslashError, i as rendererRich, n as defaultTwoslashOptions, o as defaultCompletionIcons, r as defaultHoverInfoProcessor, s as defaultCustomTagIcons, t as createTransformerFactory } from "./core-VR43FShM.mjs";
2
+ export { ShikiTwoslashError, createTransformerFactory, defaultCompletionIcons, defaultCustomTagIcons, defaultHoverInfoProcessor, defaultTwoslashOptions, rendererClassic, rendererRich };
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ import { CreateTwoslashOptions } from "twoslash";
3
3
  import { ShikiTransformer } from "@shikijs/types";
4
4
 
5
5
  //#region src/index.d.ts
6
- interface TransformerTwoslashIndexOptions extends TransformerTwoslashOptions, Pick<CreateTwoslashOptions, 'cache'> {
6
+ interface TransformerTwoslashIndexOptions extends TransformerTwoslashOptions, Pick<CreateTwoslashOptions, 'cache' | 'tsModule'> {
7
7
  /**
8
8
  * Options for the default rich renderer.
9
9
  *
package/dist/index.mjs CHANGED
@@ -1,17 +1,17 @@
1
- import { a as defaultCustomTagIcons, c as ShikiTwoslashError, i as defaultCompletionIcons, n as rendererRich, r as rendererClassic, t as defaultHoverInfoProcessor } from "./renderer-rich-DEkszi0Z.mjs";
2
- import { createTransformerFactory, defaultTwoslashOptions } from "./core.mjs";
1
+ import { a as rendererClassic, c as ShikiTwoslashError, i as rendererRich, n as defaultTwoslashOptions, o as defaultCompletionIcons, r as defaultHoverInfoProcessor, s as defaultCustomTagIcons, t as createTransformerFactory } from "./core-VR43FShM.mjs";
3
2
  import { createTwoslasher } from "twoslash";
4
-
5
3
  //#region src/index.ts
6
4
  /**
7
5
  * Factory function to create a Shiki transformer for twoslash integrations.
8
6
  */
9
7
  function transformerTwoslash(options = {}) {
10
- return createTransformerFactory(createTwoslasher({
11
- cache: options?.cache,
8
+ const twoslashOptions = {
9
+ cache: options.cache,
12
10
  compilerOptions: { moduleResolution: 100 }
13
- }), rendererRich(options.rendererRich))(options);
11
+ };
12
+ const tsModule = options.tsModule || options.twoslashOptions?.tsModule;
13
+ if (tsModule) twoslashOptions.tsModule = tsModule;
14
+ return createTransformerFactory(createTwoslasher(twoslashOptions), rendererRich(options.rendererRich))(options);
14
15
  }
15
-
16
16
  //#endregion
17
- export { ShikiTwoslashError, createTransformerFactory, defaultCompletionIcons, defaultCustomTagIcons, defaultHoverInfoProcessor, defaultTwoslashOptions, rendererClassic, rendererRich, transformerTwoslash };
17
+ export { ShikiTwoslashError, createTransformerFactory, defaultCompletionIcons, defaultCustomTagIcons, defaultHoverInfoProcessor, defaultTwoslashOptions, rendererClassic, rendererRich, transformerTwoslash };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/twoslash",
3
3
  "type": "module",
4
- "version": "4.0.2",
4
+ "version": "4.1.0",
5
5
  "description": "Shiki transformer for twoslash",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -38,16 +38,16 @@
38
38
  "typescript": ">=5.5.0"
39
39
  },
40
40
  "dependencies": {
41
- "twoslash": "^0.3.6",
42
- "@shikijs/types": "4.0.2",
43
- "@shikijs/core": "4.0.2"
41
+ "twoslash": "^0.3.8",
42
+ "@shikijs/core": "4.1.0",
43
+ "@shikijs/types": "4.1.0"
44
44
  },
45
45
  "devDependencies": {
46
- "@iconify-json/carbon": "^1.2.19",
47
- "@iconify-json/codicon": "^1.2.48",
46
+ "@iconify-json/carbon": "^1.2.21",
47
+ "@iconify-json/codicon": "^1.2.55",
48
48
  "hast-util-from-html": "^2.0.3",
49
- "typescript": "^5.9.3",
50
- "@shikijs/twoslash": "4.0.2"
49
+ "typescript": "^6.0.3",
50
+ "@shikijs/twoslash": "4.1.0"
51
51
  },
52
52
  "scripts": {
53
53
  "build": "tsdown",