@shikijs/twoslash 1.0.0 → 1.1.1
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 +19 -8
- package/dist/core.d.ts +19 -8
- package/dist/core.mjs +87 -64
- package/package.json +4 -4
package/dist/core.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TwoslashReturn, TwoslashExecuteOptions, TwoslashOptions, NodeError, NodeTag, NodeQuery, NodeCompletion, NodeHover, NodeHighlight } from 'twoslash';
|
|
1
|
+
import { TwoslashReturn, TwoslashExecuteOptions, TwoslashGenericFunction, TwoslashOptions, NodeError, NodeTag, NodeQuery, NodeCompletion, NodeHover, NodeHighlight } from 'twoslash';
|
|
2
2
|
import { CodeToHastOptions, ShikiTransformerContext, ShikiTransformerContextCommon, ShikiTransformer } from '@shikijs/core';
|
|
3
3
|
import { ElementContent, Element, Text } from 'hast';
|
|
4
4
|
|
|
@@ -34,7 +34,7 @@ interface TransformerTwoslashOptions {
|
|
|
34
34
|
/**
|
|
35
35
|
* Custom instance of twoslasher function
|
|
36
36
|
*/
|
|
37
|
-
twoslasher?: TwoslashShikiFunction;
|
|
37
|
+
twoslasher?: TwoslashShikiFunction | TwoslashGenericFunction;
|
|
38
38
|
/**
|
|
39
39
|
* Options to pass to twoslash
|
|
40
40
|
*/
|
|
@@ -48,6 +48,17 @@ interface TransformerTwoslashOptions {
|
|
|
48
48
|
* @default true
|
|
49
49
|
*/
|
|
50
50
|
throws?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Custom error handler for twoslash errors
|
|
53
|
+
* When specified, `throws` will be ignored
|
|
54
|
+
* Optionally return a string to replace the code
|
|
55
|
+
*/
|
|
56
|
+
onTwoslashError?: (error: unknown, code: string, lang: string, options: CodeToHastOptions) => string | void;
|
|
57
|
+
/**
|
|
58
|
+
* Custom error handler for Shiki errors
|
|
59
|
+
* When specified, `throws` will be ignored
|
|
60
|
+
*/
|
|
61
|
+
onShikiError?: (error: unknown) => void;
|
|
51
62
|
}
|
|
52
63
|
interface TwoslashRenderer {
|
|
53
64
|
lineError?: (this: ShikiTransformerContext, error: NodeError) => ElementContent[];
|
|
@@ -62,10 +73,6 @@ interface TwoslashRenderer {
|
|
|
62
73
|
nodesHighlight?: (this: ShikiTransformerContext, highlight: NodeHighlight, nodes: ElementContent[]) => ElementContent[];
|
|
63
74
|
}
|
|
64
75
|
|
|
65
|
-
type CompletionItem = NonNullable<NodeCompletion['completions']>[number];
|
|
66
|
-
declare const defaultCompletionIcons: Record<CompletionItem['kind'], Element | undefined>;
|
|
67
|
-
declare const defaultCustomTagIcons: Record<string, Element | undefined>;
|
|
68
|
-
|
|
69
76
|
interface RendererRichOptions {
|
|
70
77
|
/**
|
|
71
78
|
* Render JSDoc comments in hover popup.
|
|
@@ -80,7 +87,7 @@ interface RendererRichOptions {
|
|
|
80
87
|
* If `false`, no icons will be rendered.
|
|
81
88
|
* @default defaultCompletionIcons
|
|
82
89
|
*/
|
|
83
|
-
completionIcons?: Partial<Record<
|
|
90
|
+
completionIcons?: Partial<Record<string, ElementContent>> | false;
|
|
84
91
|
/**
|
|
85
92
|
* Custom icons for custom tags lines.
|
|
86
93
|
* A map from tag name to a HAST node.
|
|
@@ -245,6 +252,10 @@ declare function defaultHoverInfoProcessor(type: string): string;
|
|
|
245
252
|
*/
|
|
246
253
|
declare function rendererClassic(): TwoslashRenderer;
|
|
247
254
|
|
|
255
|
+
type CompletionItem = NonNullable<NodeCompletion['completions']>[number];
|
|
256
|
+
declare const defaultCompletionIcons: Record<string, Element | undefined>;
|
|
257
|
+
declare const defaultCustomTagIcons: Record<string, Element | undefined>;
|
|
258
|
+
|
|
248
259
|
declare class ShikiTwoslashError extends Error {
|
|
249
260
|
constructor(message: string);
|
|
250
261
|
}
|
|
@@ -255,6 +266,6 @@ declare class ShikiTwoslashError extends Error {
|
|
|
255
266
|
*/
|
|
256
267
|
|
|
257
268
|
declare function defaultTwoslashOptions(): TwoslashExecuteOptions;
|
|
258
|
-
declare function createTransformerFactory(defaultTwoslasher: TwoslashShikiFunction, defaultRenderer?: TwoslashRenderer): (options?: TransformerTwoslashOptions) => ShikiTransformer;
|
|
269
|
+
declare function createTransformerFactory(defaultTwoslasher: TwoslashShikiFunction | TwoslashGenericFunction, defaultRenderer?: TwoslashRenderer): (options?: TransformerTwoslashOptions) => ShikiTransformer;
|
|
259
270
|
|
|
260
271
|
export { type CompletionItem, type HastExtension, type RendererRichOptions, ShikiTwoslashError, type TransformerTwoslashOptions, type TwoslashRenderer, type TwoslashShikiFunction, type TwoslashShikiReturn, createTransformerFactory, defaultCompletionIcons, defaultCustomTagIcons, defaultHoverInfoProcessor, defaultTwoslashOptions, rendererClassic, rendererRich };
|
package/dist/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TwoslashReturn, TwoslashExecuteOptions, TwoslashOptions, NodeError, NodeTag, NodeQuery, NodeCompletion, NodeHover, NodeHighlight } from 'twoslash';
|
|
1
|
+
import { TwoslashReturn, TwoslashExecuteOptions, TwoslashGenericFunction, TwoslashOptions, NodeError, NodeTag, NodeQuery, NodeCompletion, NodeHover, NodeHighlight } from 'twoslash';
|
|
2
2
|
import { CodeToHastOptions, ShikiTransformerContext, ShikiTransformerContextCommon, ShikiTransformer } from '@shikijs/core';
|
|
3
3
|
import { ElementContent, Element, Text } from 'hast';
|
|
4
4
|
|
|
@@ -34,7 +34,7 @@ interface TransformerTwoslashOptions {
|
|
|
34
34
|
/**
|
|
35
35
|
* Custom instance of twoslasher function
|
|
36
36
|
*/
|
|
37
|
-
twoslasher?: TwoslashShikiFunction;
|
|
37
|
+
twoslasher?: TwoslashShikiFunction | TwoslashGenericFunction;
|
|
38
38
|
/**
|
|
39
39
|
* Options to pass to twoslash
|
|
40
40
|
*/
|
|
@@ -48,6 +48,17 @@ interface TransformerTwoslashOptions {
|
|
|
48
48
|
* @default true
|
|
49
49
|
*/
|
|
50
50
|
throws?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Custom error handler for twoslash errors
|
|
53
|
+
* When specified, `throws` will be ignored
|
|
54
|
+
* Optionally return a string to replace the code
|
|
55
|
+
*/
|
|
56
|
+
onTwoslashError?: (error: unknown, code: string, lang: string, options: CodeToHastOptions) => string | void;
|
|
57
|
+
/**
|
|
58
|
+
* Custom error handler for Shiki errors
|
|
59
|
+
* When specified, `throws` will be ignored
|
|
60
|
+
*/
|
|
61
|
+
onShikiError?: (error: unknown) => void;
|
|
51
62
|
}
|
|
52
63
|
interface TwoslashRenderer {
|
|
53
64
|
lineError?: (this: ShikiTransformerContext, error: NodeError) => ElementContent[];
|
|
@@ -62,10 +73,6 @@ interface TwoslashRenderer {
|
|
|
62
73
|
nodesHighlight?: (this: ShikiTransformerContext, highlight: NodeHighlight, nodes: ElementContent[]) => ElementContent[];
|
|
63
74
|
}
|
|
64
75
|
|
|
65
|
-
type CompletionItem = NonNullable<NodeCompletion['completions']>[number];
|
|
66
|
-
declare const defaultCompletionIcons: Record<CompletionItem['kind'], Element | undefined>;
|
|
67
|
-
declare const defaultCustomTagIcons: Record<string, Element | undefined>;
|
|
68
|
-
|
|
69
76
|
interface RendererRichOptions {
|
|
70
77
|
/**
|
|
71
78
|
* Render JSDoc comments in hover popup.
|
|
@@ -80,7 +87,7 @@ interface RendererRichOptions {
|
|
|
80
87
|
* If `false`, no icons will be rendered.
|
|
81
88
|
* @default defaultCompletionIcons
|
|
82
89
|
*/
|
|
83
|
-
completionIcons?: Partial<Record<
|
|
90
|
+
completionIcons?: Partial<Record<string, ElementContent>> | false;
|
|
84
91
|
/**
|
|
85
92
|
* Custom icons for custom tags lines.
|
|
86
93
|
* A map from tag name to a HAST node.
|
|
@@ -245,6 +252,10 @@ declare function defaultHoverInfoProcessor(type: string): string;
|
|
|
245
252
|
*/
|
|
246
253
|
declare function rendererClassic(): TwoslashRenderer;
|
|
247
254
|
|
|
255
|
+
type CompletionItem = NonNullable<NodeCompletion['completions']>[number];
|
|
256
|
+
declare const defaultCompletionIcons: Record<string, Element | undefined>;
|
|
257
|
+
declare const defaultCustomTagIcons: Record<string, Element | undefined>;
|
|
258
|
+
|
|
248
259
|
declare class ShikiTwoslashError extends Error {
|
|
249
260
|
constructor(message: string);
|
|
250
261
|
}
|
|
@@ -255,6 +266,6 @@ declare class ShikiTwoslashError extends Error {
|
|
|
255
266
|
*/
|
|
256
267
|
|
|
257
268
|
declare function defaultTwoslashOptions(): TwoslashExecuteOptions;
|
|
258
|
-
declare function createTransformerFactory(defaultTwoslasher: TwoslashShikiFunction, defaultRenderer?: TwoslashRenderer): (options?: TransformerTwoslashOptions) => ShikiTransformer;
|
|
269
|
+
declare function createTransformerFactory(defaultTwoslasher: TwoslashShikiFunction | TwoslashGenericFunction, defaultRenderer?: TwoslashRenderer): (options?: TransformerTwoslashOptions) => ShikiTransformer;
|
|
259
270
|
|
|
260
271
|
export { type CompletionItem, type HastExtension, type RendererRichOptions, ShikiTwoslashError, type TransformerTwoslashOptions, type TwoslashRenderer, type TwoslashShikiFunction, type TwoslashShikiReturn, createTransformerFactory, defaultCompletionIcons, defaultCustomTagIcons, defaultHoverInfoProcessor, defaultTwoslashOptions, rendererClassic, rendererRich };
|
package/dist/core.mjs
CHANGED
|
@@ -557,52 +557,56 @@ function rendererRich(options = {}) {
|
|
|
557
557
|
nodeCompletion(query, node) {
|
|
558
558
|
if (node.type !== "text")
|
|
559
559
|
throw new ShikiTwoslashError(`Renderer hook nodeCompletion only works on text nodes, got ${node.type}`);
|
|
560
|
-
const items = query.completions.map((i) =>
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
type: "element",
|
|
582
|
-
tagName: "span",
|
|
583
|
-
properties: { class: "twoslash-completions-matched" },
|
|
584
|
-
children: [
|
|
585
|
-
{
|
|
586
|
-
type: "text",
|
|
587
|
-
value: i.name.startsWith(query.completionsPrefix) ? query.completionsPrefix : ""
|
|
588
|
-
}
|
|
589
|
-
]
|
|
560
|
+
const items = query.completions.map((i) => {
|
|
561
|
+
const kind = i.kind || "default";
|
|
562
|
+
const isDeprecated = "kindModifiers" in i && typeof i.kindModifiers === "string" && i.kindModifiers?.split(",").includes("deprecated");
|
|
563
|
+
return {
|
|
564
|
+
type: "element",
|
|
565
|
+
tagName: "li",
|
|
566
|
+
properties: {},
|
|
567
|
+
children: [
|
|
568
|
+
...completionIcons ? [{
|
|
569
|
+
type: "element",
|
|
570
|
+
tagName: "span",
|
|
571
|
+
properties: { class: `twoslash-completions-icon completions-${kind.replace(/\s/g, "-")}` },
|
|
572
|
+
children: [
|
|
573
|
+
completionIcons[kind] || completionIcons.property
|
|
574
|
+
].filter(Boolean)
|
|
575
|
+
}] : [],
|
|
576
|
+
{
|
|
577
|
+
type: "element",
|
|
578
|
+
tagName: "span",
|
|
579
|
+
properties: {
|
|
580
|
+
class: isDeprecated ? "deprecated" : void 0
|
|
590
581
|
},
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
582
|
+
children: [
|
|
583
|
+
{
|
|
584
|
+
type: "element",
|
|
585
|
+
tagName: "span",
|
|
586
|
+
properties: { class: "twoslash-completions-matched" },
|
|
587
|
+
children: [
|
|
588
|
+
{
|
|
589
|
+
type: "text",
|
|
590
|
+
value: i.name.startsWith(query.completionsPrefix) ? query.completionsPrefix : ""
|
|
591
|
+
}
|
|
592
|
+
]
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
type: "element",
|
|
596
|
+
tagName: "span",
|
|
597
|
+
properties: { class: "twoslash-completions-unmatched" },
|
|
598
|
+
children: [
|
|
599
|
+
{
|
|
600
|
+
type: "text",
|
|
601
|
+
value: i.name.startsWith(query.completionsPrefix) ? i.name.slice(query.completionsPrefix.length || 0) : i.name
|
|
602
|
+
}
|
|
603
|
+
]
|
|
604
|
+
}
|
|
605
|
+
]
|
|
606
|
+
}
|
|
607
|
+
]
|
|
608
|
+
};
|
|
609
|
+
});
|
|
606
610
|
const cursor = extend(
|
|
607
611
|
hast?.completionCursor,
|
|
608
612
|
{
|
|
@@ -778,14 +782,14 @@ function defaultHoverInfoProcessor(type) {
|
|
|
778
782
|
}
|
|
779
783
|
function getErrorLevelClass(error) {
|
|
780
784
|
switch (error.level) {
|
|
781
|
-
case
|
|
785
|
+
case "warning":
|
|
782
786
|
return "twoslash-error-level-warning";
|
|
783
|
-
case
|
|
784
|
-
return "";
|
|
785
|
-
case 2:
|
|
787
|
+
case "suggestion":
|
|
786
788
|
return "twoslash-error-level-suggestion";
|
|
789
|
+
case "message":
|
|
790
|
+
return "twoslash-error-level-message";
|
|
787
791
|
default:
|
|
788
|
-
return "
|
|
792
|
+
return "";
|
|
789
793
|
}
|
|
790
794
|
}
|
|
791
795
|
|
|
@@ -879,7 +883,7 @@ function rendererClassic() {
|
|
|
879
883
|
type: "element",
|
|
880
884
|
tagName: "li",
|
|
881
885
|
properties: {
|
|
882
|
-
class: i.kindModifiers?.split(",").includes("deprecated") ? "deprecated" : void 0
|
|
886
|
+
class: "kindModifiers" in i && typeof i.kindModifiers === "string" && i.kindModifiers?.split(",").includes("deprecated") ? "deprecated" : void 0
|
|
883
887
|
},
|
|
884
888
|
children: [{
|
|
885
889
|
type: "element",
|
|
@@ -986,9 +990,16 @@ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
|
|
|
986
990
|
renderer = defaultRenderer,
|
|
987
991
|
throws = true
|
|
988
992
|
} = options;
|
|
993
|
+
const onTwoslashError = options.onTwoslashError || (throws ? (error) => {
|
|
994
|
+
throw error;
|
|
995
|
+
} : () => false);
|
|
996
|
+
const onShikiError = options.onShikiError || (throws ? (error) => {
|
|
997
|
+
throw error;
|
|
998
|
+
} : () => false);
|
|
989
999
|
const trigger = explicitTrigger instanceof RegExp ? explicitTrigger : /\btwoslash\b/;
|
|
990
1000
|
if (!renderer)
|
|
991
1001
|
throw new ShikiTwoslashError("Missing renderer");
|
|
1002
|
+
const map = /* @__PURE__ */ new WeakMap();
|
|
992
1003
|
const filter = options.filter || ((lang, _, options2) => langs.includes(lang) && (!explicitTrigger || trigger.test(options2.meta?.__raw || "")));
|
|
993
1004
|
return {
|
|
994
1005
|
preprocess(code) {
|
|
@@ -996,28 +1007,38 @@ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
|
|
|
996
1007
|
if (lang in langAlias)
|
|
997
1008
|
lang = langAlias[this.options.lang];
|
|
998
1009
|
if (filter(lang, code, this.options)) {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1010
|
+
try {
|
|
1011
|
+
const twoslash = twoslasher(code, lang, twoslashOptions);
|
|
1012
|
+
map.set(this.meta, twoslash);
|
|
1013
|
+
this.meta.twoslash = twoslash;
|
|
1014
|
+
this.options.lang = twoslash.meta?.extension || lang;
|
|
1015
|
+
return twoslash.code;
|
|
1016
|
+
} catch (error) {
|
|
1017
|
+
const result = onTwoslashError(error, code, lang, this.options);
|
|
1018
|
+
if (typeof result === "string")
|
|
1019
|
+
return code;
|
|
1020
|
+
}
|
|
1003
1021
|
}
|
|
1004
1022
|
},
|
|
1005
1023
|
tokens(tokens) {
|
|
1006
|
-
|
|
1024
|
+
const twoslash = map.get(this.meta);
|
|
1025
|
+
if (!twoslash)
|
|
1007
1026
|
return;
|
|
1008
1027
|
return splitTokens(
|
|
1009
1028
|
tokens,
|
|
1010
|
-
|
|
1029
|
+
twoslash.nodes.flatMap(
|
|
1011
1030
|
(i) => ["hover", "error", "query", "highlight", "completion"].includes(i.type) ? [i.start, i.start + i.length] : []
|
|
1012
1031
|
)
|
|
1013
1032
|
);
|
|
1014
1033
|
},
|
|
1015
1034
|
pre(pre) {
|
|
1016
|
-
|
|
1017
|
-
|
|
1035
|
+
const twoslash = map.get(this.meta);
|
|
1036
|
+
if (!twoslash)
|
|
1037
|
+
return;
|
|
1038
|
+
this.addClassToHast(pre, "twoslash lsp");
|
|
1018
1039
|
},
|
|
1019
1040
|
code(codeEl) {
|
|
1020
|
-
const twoslash = this.meta
|
|
1041
|
+
const twoslash = map.get(this.meta);
|
|
1021
1042
|
if (!twoslash)
|
|
1022
1043
|
return;
|
|
1023
1044
|
const insertAfterLine = (line, nodes) => {
|
|
@@ -1030,8 +1051,7 @@ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
|
|
|
1030
1051
|
const lineEl = this.lines[line];
|
|
1031
1052
|
index = codeEl.children.indexOf(lineEl);
|
|
1032
1053
|
if (index === -1) {
|
|
1033
|
-
|
|
1034
|
-
throw new ShikiTwoslashError(`Cannot find line ${line} in code element`);
|
|
1054
|
+
onShikiError(new ShikiTwoslashError(`Cannot find line ${line} in code element`));
|
|
1035
1055
|
return;
|
|
1036
1056
|
}
|
|
1037
1057
|
}
|
|
@@ -1068,6 +1088,10 @@ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
|
|
|
1068
1088
|
continue;
|
|
1069
1089
|
}
|
|
1070
1090
|
const tokens = locateTextTokens(node.line, node.character, node.length);
|
|
1091
|
+
if (!tokens.length && !(node.type === "error" && renderer.nodesError)) {
|
|
1092
|
+
onShikiError(new ShikiTwoslashError(`Cannot find tokens for node: ${JSON.stringify(node)}`));
|
|
1093
|
+
continue;
|
|
1094
|
+
}
|
|
1071
1095
|
const wrapTokens = (fn) => {
|
|
1072
1096
|
const line = this.lines[node.line];
|
|
1073
1097
|
let charIndex = 0;
|
|
@@ -1153,8 +1177,7 @@ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
|
|
|
1153
1177
|
break;
|
|
1154
1178
|
}
|
|
1155
1179
|
default: {
|
|
1156
|
-
|
|
1157
|
-
throw new ShikiTwoslashError(`Unknown node type: ${node.type}`);
|
|
1180
|
+
onShikiError(new ShikiTwoslashError(`Unknown node type: ${node?.type}`));
|
|
1158
1181
|
}
|
|
1159
1182
|
}
|
|
1160
1183
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shikijs/twoslash",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"description": "Shiki transformer for twoslash",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"dist"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"twoslash": "^0.1
|
|
53
|
-
"@shikijs/core": "1.
|
|
52
|
+
"twoslash": "^0.2.1",
|
|
53
|
+
"@shikijs/core": "1.1.1"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@iconify-json/carbon": "^1.1.
|
|
56
|
+
"@iconify-json/carbon": "^1.1.29",
|
|
57
57
|
"@iconify-json/codicon": "^1.1.41",
|
|
58
58
|
"@shikijs/twoslash": "^3.1.2",
|
|
59
59
|
"hast-util-from-html": "^2.0.1",
|