From b7637bcc0bdd47c4ee120860cb3212d741744b6a Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Sun, 14 Jan 2024 15:25:26 +0100 Subject: [PATCH] fix(twoslash)!: rename renderer hook `nodeCompletions` to `nodeCompletion` --- packages/shikiji-twoslash/src/core.ts | 128 +++++++++--------- .../shikiji-twoslash/src/renderer-classic.ts | 2 +- .../shikiji-twoslash/src/renderer-rich.ts | 4 +- packages/shikiji-twoslash/src/types.ts | 10 +- .../test/out/classic/completions.html | 2 +- .../classic/cuts_out_unnecessary_code.html | 6 +- 6 files changed, 80 insertions(+), 72 deletions(-) diff --git a/packages/shikiji-twoslash/src/core.ts b/packages/shikiji-twoslash/src/core.ts index 522d8fbda..a44f62621 100644 --- a/packages/shikiji-twoslash/src/core.ts +++ b/packages/shikiji-twoslash/src/core.ts @@ -120,73 +120,79 @@ export function createTransformerFactory( throw new Error(`[shikiji-twoslash] Cannot find token at L${line}:${character}`) } - const skipTokens = new Set() + const tokensSkipHover = new Set() + const postActions: (() => void)[] = [] - for (const error of twoslash.errors) { - const token = locateTextToken(error.line, error.character) - if (!token) + for (const node of twoslash.nodes) { + if (node.type === 'tag') { + if (renderer.lineCustomTag) + insertAfterLine(node.line, renderer.lineCustomTag.call(this, node)) continue - - skipTokens.add(token) - - if (renderer.nodeError) { - const clone = { ...token } - Object.assign(token, renderer.nodeError.call(this, error, clone)) } - if (renderer.lineError) - insertAfterLine(error.line, renderer.lineError.call(this, error)) - } - - for (const query of twoslash.queries) { - const token = locateTextToken(query.line, query.character) - if (!token) - continue - - skipTokens.add(token) - - if (renderer.nodeQuery) { - const clone = { ...token } - Object.assign(token, renderer.nodeQuery.call(this, query, clone)) - } - - if (renderer.lineQuery) - insertAfterLine(query.line, renderer.lineQuery.call(this, query, token)) - } - - for (const completion of twoslash.completions) { - const token = locateTextToken(completion.line, completion.character) - if (!token) - continue - - skipTokens.add(token) - - if (renderer.nodeCompletions) { - const clone = { ...token } - Object.assign(token, renderer.nodeCompletions.call(this, completion, clone)) + const token = locateTextToken(node.line, node.character) + + switch (node.type) { + case 'error': { + if (token && renderer.nodeError) { + tokensSkipHover.add(token) + const clone = { ...token } + Object.assign(token, renderer.nodeError.call(this, node, clone)) + } + if (renderer.lineError) + insertAfterLine(node.line, renderer.lineError.call(this, node)) + break + } + case 'query': { + if (token && renderer.nodeQuery) { + tokensSkipHover.add(token) + const clone = { ...token } + Object.assign(token, renderer.nodeQuery.call(this, node, clone)) + } + if (renderer.lineQuery) + insertAfterLine(node.line, renderer.lineQuery.call(this, node, token)) + break + } + case 'completion': { + if (token && renderer.nodeCompletion) { + tokensSkipHover.add(token) + const clone = { ...token } + Object.assign(token, renderer.nodeCompletion.call(this, node, clone)) + } + if (renderer.lineCompletion) + insertAfterLine(node.line, renderer.lineCompletion.call(this, node)) + break + } + case 'highlight': { + if (token && renderer.nodeHightlight) { + tokensSkipHover.add(token) + const clone = { ...token } + Object.assign(token, renderer.nodeHightlight.call(this, node, clone)) + } + if (renderer.lineHighlight) + insertAfterLine(node.line, renderer.lineHighlight.call(this, node)) + break + } + case 'hover': { + // Hover will be handled after all other nodes are processed + if (token && renderer.nodeStaticInfo) { + postActions.push(() => { + if (tokensSkipHover.has(token)) + return + const clone = { ...token } + Object.assign(token, renderer.nodeStaticInfo.call(this, node, clone)) + }) + } + break + } + default: { + if (throws) + // @ts-expect-error Unknown node type + throw new Error(`[shikiji-twoslash] Unknown node type: ${node.type}`) + } } - - if (renderer.lineCompletions) - insertAfterLine(completion.line, renderer.lineCompletions.call(this, completion)) - } - - for (const info of twoslash.hovers) { - const token = locateTextToken(info.line, info.character) - if (!token || token.type !== 'text') - continue - - // If it's already rendered as popup or error, skip it - if (skipTokens.has(token)) - continue - - const clone = { ...token } - Object.assign(token, renderer.nodeStaticInfo.call(this, info, clone)) - } - - if (renderer.lineCustomTag) { - for (const tag of twoslash.tags) - insertAfterLine(tag.line, renderer.lineCustomTag.call(this, tag)) } + postActions.forEach(i => i()) }, } } diff --git a/packages/shikiji-twoslash/src/renderer-classic.ts b/packages/shikiji-twoslash/src/renderer-classic.ts index 17fcbd8c2..2a3b47e64 100644 --- a/packages/shikiji-twoslash/src/renderer-classic.ts +++ b/packages/shikiji-twoslash/src/renderer-classic.ts @@ -76,7 +76,7 @@ export function rendererClassic(): TwoSlashRenderer { ] }, - lineCompletions(query) { + lineCompletion(query) { return [ { type: 'element', diff --git a/packages/shikiji-twoslash/src/renderer-rich.ts b/packages/shikiji-twoslash/src/renderer-rich.ts index 311020e8d..60ce4a960 100644 --- a/packages/shikiji-twoslash/src/renderer-rich.ts +++ b/packages/shikiji-twoslash/src/renderer-rich.ts @@ -175,9 +175,9 @@ export function rendererRich(options: RendererRichOptions = {}): TwoSlashRendere } }, - nodeCompletions(query, node) { + nodeCompletion(query, node) { if (node.type !== 'text') - throw new Error(`[shikiji-twoslash] nodeCompletions only works on text nodes, got ${node.type}`) + throw new Error(`[shikiji-twoslash] nodeCompletion only works on text nodes, got ${node.type}`) const leftPart = query.completionsPrefix || '' const rightPart = node.value.slice(leftPart.length || 0) diff --git a/packages/shikiji-twoslash/src/types.ts b/packages/shikiji-twoslash/src/types.ts index 1ad131215..f3b2fec66 100644 --- a/packages/shikiji-twoslash/src/types.ts +++ b/packages/shikiji-twoslash/src/types.ts @@ -1,4 +1,4 @@ -import type { NodeCompletion, NodeError, NodeHover, NodeQuery, NodeTag, TwoSlashOptions, TwoSlashReturn, twoslasher } from 'twoslash' +import type { NodeCompletion, NodeError, NodeHighlight, NodeHover, NodeQuery, NodeTag, TwoSlashOptions, TwoSlashReturn, twoslasher } from 'twoslash' import type { CodeToHastOptions, ShikijiTransformerContext } from 'shikiji-core' import type { Element, ElementContent, Text } from 'hast' @@ -51,10 +51,12 @@ export interface TwoSlashRenderer { lineError?(this: ShikijiTransformerContext, error: NodeError): ElementContent[] lineCustomTag?(this: ShikijiTransformerContext, tag: NodeTag): ElementContent[] lineQuery?(this: ShikijiTransformerContext, query: NodeQuery, targetNode?: Element | Text): ElementContent[] - lineCompletions?(this: ShikijiTransformerContext, query: NodeCompletion): ElementContent[] + lineCompletion?(this: ShikijiTransformerContext, query: NodeCompletion): ElementContent[] + lineHighlight?(this: ShikijiTransformerContext, query: NodeHighlight): ElementContent[] - nodeError?(this: ShikijiTransformerContext, error: NodeError, node: Element | Text): Partial nodeStaticInfo(this: ShikijiTransformerContext, info: NodeHover, node: Element | Text): Partial + nodeError?(this: ShikijiTransformerContext, error: NodeError, node: Element | Text): Partial nodeQuery?(this: ShikijiTransformerContext, query: NodeQuery, node: Element | Text): Partial - nodeCompletions?(this: ShikijiTransformerContext, query: NodeCompletion, node: Element | Text): Partial + nodeCompletion?(this: ShikijiTransformerContext, query: NodeCompletion, node: Element | Text): Partial + nodeHightlight?(this: ShikijiTransformerContext, query: NodeHighlight, node: Element | Text): Partial } diff --git a/packages/shikiji-twoslash/test/out/classic/completions.html b/packages/shikiji-twoslash/test/out/classic/completions.html index 743c282f5..c85b84736 100644 --- a/packages/shikiji-twoslash/test/out/classic/completions.html +++ b/packages/shikiji-twoslash/test/out/classic/completions.html @@ -4,4 +4,4 @@ html, body { margin: 0; } .shiki { padding: 2em; } -
const a = Number.isNaN(123)
\ No newline at end of file +
const a = Number.isNaN(123)
\ No newline at end of file diff --git a/packages/shikiji-twoslash/test/out/classic/cuts_out_unnecessary_code.html b/packages/shikiji-twoslash/test/out/classic/cuts_out_unnecessary_code.html index 419fc8833..acd3f536e 100644 --- a/packages/shikiji-twoslash/test/out/classic/cuts_out_unnecessary_code.html +++ b/packages/shikiji-twoslash/test/out/classic/cuts_out_unnecessary_code.html @@ -8,6 +8,6 @@ throw "unimplemented" } -let a = createLabel("typescript")
let a: NameLabel
-let b = createLabel(2.8)
function createLabel<2.8>(idOrName: 2.8): IdLabel
-let c = createLabel(Math.random() ? "hello" : 42)
\ No newline at end of file +let a = createLabel("typescript")
let a: NameLabel
+let b = createLabel(2.8)
function createLabel<2.8>(idOrName: 2.8): IdLabel
+let c = createLabel(Math.random() ? "hello" : 42)
\ No newline at end of file