@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.
- package/dist/{renderer-rich-DEkszi0Z.mjs → core-VR43FShM.mjs} +225 -16
- package/dist/core.mjs +2 -214
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +8 -8
- package/package.json +8 -8
|
@@ -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(
|
|
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: ${
|
|
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(
|
|
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
|
|
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(
|
|
813
|
-
if (
|
|
814
|
-
else if (
|
|
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
|
-
|
|
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
|
|
2
|
-
|
|
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
|
|
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
|
-
|
|
11
|
-
cache: options
|
|
8
|
+
const twoslashOptions = {
|
|
9
|
+
cache: options.cache,
|
|
12
10
|
compilerOptions: { moduleResolution: 100 }
|
|
13
|
-
}
|
|
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
|
|
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.
|
|
42
|
-
"@shikijs/
|
|
43
|
-
"@shikijs/
|
|
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.
|
|
47
|
-
"@iconify-json/codicon": "^1.2.
|
|
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": "^
|
|
50
|
-
"@shikijs/twoslash": "4.0
|
|
49
|
+
"typescript": "^6.0.3",
|
|
50
|
+
"@shikijs/twoslash": "4.1.0"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"build": "tsdown",
|