@shikijs/twoslash 1.0.0 → 1.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/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
  */
@@ -62,10 +62,6 @@ interface TwoslashRenderer {
62
62
  nodesHighlight?: (this: ShikiTransformerContext, highlight: NodeHighlight, nodes: ElementContent[]) => ElementContent[];
63
63
  }
64
64
 
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
65
  interface RendererRichOptions {
70
66
  /**
71
67
  * Render JSDoc comments in hover popup.
@@ -80,7 +76,7 @@ interface RendererRichOptions {
80
76
  * If `false`, no icons will be rendered.
81
77
  * @default defaultCompletionIcons
82
78
  */
83
- completionIcons?: Partial<Record<CompletionItem['kind'], ElementContent>> | false;
79
+ completionIcons?: Partial<Record<string, ElementContent>> | false;
84
80
  /**
85
81
  * Custom icons for custom tags lines.
86
82
  * A map from tag name to a HAST node.
@@ -245,6 +241,10 @@ declare function defaultHoverInfoProcessor(type: string): string;
245
241
  */
246
242
  declare function rendererClassic(): TwoslashRenderer;
247
243
 
244
+ type CompletionItem = NonNullable<NodeCompletion['completions']>[number];
245
+ declare const defaultCompletionIcons: Record<string, Element | undefined>;
246
+ declare const defaultCustomTagIcons: Record<string, Element | undefined>;
247
+
248
248
  declare class ShikiTwoslashError extends Error {
249
249
  constructor(message: string);
250
250
  }
@@ -255,6 +255,6 @@ declare class ShikiTwoslashError extends Error {
255
255
  */
256
256
 
257
257
  declare function defaultTwoslashOptions(): TwoslashExecuteOptions;
258
- declare function createTransformerFactory(defaultTwoslasher: TwoslashShikiFunction, defaultRenderer?: TwoslashRenderer): (options?: TransformerTwoslashOptions) => ShikiTransformer;
258
+ declare function createTransformerFactory(defaultTwoslasher: TwoslashShikiFunction | TwoslashGenericFunction, defaultRenderer?: TwoslashRenderer): (options?: TransformerTwoslashOptions) => ShikiTransformer;
259
259
 
260
260
  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
  */
@@ -62,10 +62,6 @@ interface TwoslashRenderer {
62
62
  nodesHighlight?: (this: ShikiTransformerContext, highlight: NodeHighlight, nodes: ElementContent[]) => ElementContent[];
63
63
  }
64
64
 
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
65
  interface RendererRichOptions {
70
66
  /**
71
67
  * Render JSDoc comments in hover popup.
@@ -80,7 +76,7 @@ interface RendererRichOptions {
80
76
  * If `false`, no icons will be rendered.
81
77
  * @default defaultCompletionIcons
82
78
  */
83
- completionIcons?: Partial<Record<CompletionItem['kind'], ElementContent>> | false;
79
+ completionIcons?: Partial<Record<string, ElementContent>> | false;
84
80
  /**
85
81
  * Custom icons for custom tags lines.
86
82
  * A map from tag name to a HAST node.
@@ -245,6 +241,10 @@ declare function defaultHoverInfoProcessor(type: string): string;
245
241
  */
246
242
  declare function rendererClassic(): TwoslashRenderer;
247
243
 
244
+ type CompletionItem = NonNullable<NodeCompletion['completions']>[number];
245
+ declare const defaultCompletionIcons: Record<string, Element | undefined>;
246
+ declare const defaultCustomTagIcons: Record<string, Element | undefined>;
247
+
248
248
  declare class ShikiTwoslashError extends Error {
249
249
  constructor(message: string);
250
250
  }
@@ -255,6 +255,6 @@ declare class ShikiTwoslashError extends Error {
255
255
  */
256
256
 
257
257
  declare function defaultTwoslashOptions(): TwoslashExecuteOptions;
258
- declare function createTransformerFactory(defaultTwoslasher: TwoslashShikiFunction, defaultRenderer?: TwoslashRenderer): (options?: TransformerTwoslashOptions) => ShikiTransformer;
258
+ declare function createTransformerFactory(defaultTwoslasher: TwoslashShikiFunction | TwoslashGenericFunction, defaultRenderer?: TwoslashRenderer): (options?: TransformerTwoslashOptions) => ShikiTransformer;
259
259
 
260
260
  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
- type: "element",
562
- tagName: "li",
563
- properties: {},
564
- children: [
565
- ...completionIcons ? [{
566
- type: "element",
567
- tagName: "span",
568
- properties: { class: `twoslash-completions-icon completions-${i.kind.replace(/\s/g, "-")}` },
569
- children: [
570
- completionIcons[i.kind] || completionIcons.property
571
- ].filter(Boolean)
572
- }] : [],
573
- {
574
- type: "element",
575
- tagName: "span",
576
- properties: {
577
- class: i.kindModifiers?.split(",").includes("deprecated") ? "deprecated" : void 0
578
- },
579
- children: [
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
- type: "element",
593
- tagName: "span",
594
- properties: { class: "twoslash-completions-unmatched" },
595
- children: [
596
- {
597
- type: "text",
598
- value: i.name.startsWith(query.completionsPrefix) ? i.name.slice(query.completionsPrefix.length || 0) : i.name
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 0:
785
+ case "warning":
782
786
  return "twoslash-error-level-warning";
783
- case 1:
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 "twoslash-error-level-info";
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",
@@ -989,6 +993,7 @@ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
989
993
  const trigger = explicitTrigger instanceof RegExp ? explicitTrigger : /\btwoslash\b/;
990
994
  if (!renderer)
991
995
  throw new ShikiTwoslashError("Missing renderer");
996
+ const map = /* @__PURE__ */ new WeakMap();
992
997
  const filter = options.filter || ((lang, _, options2) => langs.includes(lang) && (!explicitTrigger || trigger.test(options2.meta?.__raw || "")));
993
998
  return {
994
999
  preprocess(code) {
@@ -997,27 +1002,31 @@ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
997
1002
  lang = langAlias[this.options.lang];
998
1003
  if (filter(lang, code, this.options)) {
999
1004
  const twoslash = twoslasher(code, lang, twoslashOptions);
1005
+ map.set(this.meta, twoslash);
1000
1006
  this.meta.twoslash = twoslash;
1001
1007
  this.options.lang = twoslash.meta?.extension || lang;
1002
1008
  return twoslash.code;
1003
1009
  }
1004
1010
  },
1005
1011
  tokens(tokens) {
1006
- if (!this.meta.twoslash)
1012
+ const twoslash = map.get(this.meta);
1013
+ if (!twoslash)
1007
1014
  return;
1008
1015
  return splitTokens(
1009
1016
  tokens,
1010
- this.meta.twoslash.nodes.flatMap(
1017
+ twoslash.nodes.flatMap(
1011
1018
  (i) => ["hover", "error", "query", "highlight", "completion"].includes(i.type) ? [i.start, i.start + i.length] : []
1012
1019
  )
1013
1020
  );
1014
1021
  },
1015
1022
  pre(pre) {
1016
- if (this.meta.twoslash)
1017
- this.addClassToHast(pre, "twoslash lsp");
1023
+ const twoslash = map.get(this.meta);
1024
+ if (!twoslash)
1025
+ return;
1026
+ this.addClassToHast(pre, "twoslash lsp");
1018
1027
  },
1019
1028
  code(codeEl) {
1020
- const twoslash = this.meta.twoslash;
1029
+ const twoslash = map.get(this.meta);
1021
1030
  if (!twoslash)
1022
1031
  return;
1023
1032
  const insertAfterLine = (line, nodes) => {
@@ -1068,6 +1077,8 @@ function createTransformerFactory(defaultTwoslasher, defaultRenderer) {
1068
1077
  continue;
1069
1078
  }
1070
1079
  const tokens = locateTextTokens(node.line, node.character, node.length);
1080
+ if (!tokens.length)
1081
+ throw new ShikiTwoslashError(`Cannot find tokens for node: ${JSON.stringify(node)}`);
1071
1082
  const wrapTokens = (fn) => {
1072
1083
  const line = this.lines[node.line];
1073
1084
  let charIndex = 0;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shikijs/twoslash",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "1.1.0",
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.2",
53
- "@shikijs/core": "1.0.0"
52
+ "twoslash": "^0.2.0",
53
+ "@shikijs/core": "1.1.0"
54
54
  },
55
55
  "devDependencies": {
56
- "@iconify-json/carbon": "^1.1.28",
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",