diff --git a/package.json b/package.json index 077ffd64..4bf65a26 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,8 @@ "build:docs": "TARGET=docs vite build", "build:lib": "TARGET=lib vite build", "compile": "pnpm run compile:code-snippets && pnpm run compile:docs", - "compile:code-snippets": "node ./scripts/code-snippets/run.js", - "compile:docs": "node ./scripts/docs/run.js", + "compile:code-snippets": "node --loader ts-node/esm ./scripts/code-snippets/run.ts", + "compile:docs": "node --loader ts-node/esm ./scripts/docs/run.ts", "lint": "eslint .", "prerelease": "rm -rf dist && rm -rf docs && pnpm run build", "prettier": "prettier --write \"**/*.{css,html,js,json,jsx,ts,tsx}\"", @@ -87,6 +87,7 @@ "tailwind-merge": "^3.3.1", "tailwindcss": "^4.1.11", "ts-blank-space": "^0.6.2", + "ts-node": "^10.9.2", "typescript": "~5.8.3", "typescript-eslint": "^8.35.1", "typescript-json-schema": "^0.65.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f434e13a..be37b464 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -133,6 +133,9 @@ importers: ts-blank-space: specifier: ^0.6.2 version: 0.6.2 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@swc/core@1.12.9(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.8.3) typescript: specifier: ~5.8.3 version: 5.8.3 @@ -7060,6 +7063,26 @@ snapshots: optionalDependencies: "@swc/core": 1.12.9(@swc/helpers@0.5.17) + ts-node@10.9.2(@swc/core@1.12.9(@swc/helpers@0.5.17))(@types/node@24.2.0)(typescript@5.8.3): + dependencies: + "@cspotcode/source-map-support": 0.8.1 + "@tsconfig/node10": 1.0.11 + "@tsconfig/node12": 1.0.11 + "@tsconfig/node14": 1.0.3 + "@tsconfig/node16": 1.0.4 + "@types/node": 24.2.0 + acorn: 8.15.0 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.8.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optionalDependencies: + "@swc/core": 1.12.9(@swc/helpers@0.5.17) + tslib@2.8.1: {} type-check@0.4.0: diff --git a/scripts/code-snippets/run.js b/scripts/code-snippets/run.ts similarity index 94% rename from scripts/code-snippets/run.js rename to scripts/code-snippets/run.ts index bd0d117c..ce052337 100644 --- a/scripts/code-snippets/run.js +++ b/scripts/code-snippets/run.ts @@ -1,8 +1,8 @@ import { mkdir, readFile, writeFile } from "node:fs/promises"; import { basename, join } from "node:path"; import { cwd } from "node:process"; -import { getFilesWithExtensions, rmFilesWithExtensions } from "../utils.js"; -import { syntaxHighlight } from "./syntax-highlight.js"; +import { getFilesWithExtensions, rmFilesWithExtensions } from "../utils.ts"; +import { syntaxHighlight } from "./syntax-highlight.ts"; async function run() { const inputDir = join(cwd(), "src", "routes"); @@ -19,13 +19,12 @@ async function run() { ]); const exampleFiles = tsFiles.filter((file) => file.includes(".example.")); - for (let file of exampleFiles) { + for (const file of exampleFiles) { console.debug("Extracting", file); const buffer = await readFile(file); let rawText = buffer.toString(); - let json; { // Remove special comments and directives before syntax highlighting diff --git a/scripts/code-snippets/syntax-highlight.js b/scripts/code-snippets/syntax-highlight.ts similarity index 73% rename from scripts/code-snippets/syntax-highlight.js rename to scripts/code-snippets/syntax-highlight.ts index da2cf4fb..686d13dd 100644 --- a/scripts/code-snippets/syntax-highlight.js +++ b/scripts/code-snippets/syntax-highlight.ts @@ -4,20 +4,35 @@ import { typescriptLanguage } from "@codemirror/lang-javascript"; import { htmlLanguage } from "@codemirror/lang-html"; -import { ensureSyntaxTree } from "@codemirror/language"; +import { ensureSyntaxTree, LRLanguage } from "@codemirror/language"; import { EditorState } from "@codemirror/state"; import { classHighlighter, highlightTree } from "@lezer/highlight"; +type TokenType = string; +type Token = { + columnIndex: number; + type: TokenType | null; + value: string; +}; + +type Language = "HTML" | "JS" | "JSX" | "TS" | "TSX"; + +type State = { + parsedTokens: Token[]; + rawString: string; +}; + export const DEFAULT_MAX_CHARACTERS = 500000; export const DEFAULT_MAX_TIME = 5000; -export async function syntaxHighlight(code, language) { - let extension; +export async function syntaxHighlight(code: string, language: Language) { + let extension: LRLanguage; switch (language) { case "HTML": { extension = htmlLanguage.configure({ dialect: "selfClosing" }); break; } + case "JS": case "JSX": { extension = jsxLanguage; break; @@ -40,9 +55,9 @@ export async function syntaxHighlight(code, language) { return tokens.map(parsedTokensToHtml).join("\n"); } -async function parser(code, languageExtension = jsxLanguage) { - const parsedTokens = []; - const currentLineState = { +async function parser(code: string, languageExtension: LRLanguage) { + const parsedTokens: Token[][] = []; + const currentLineState: State = { parsedTokens: [], rawString: "" }; @@ -79,25 +94,29 @@ async function parser(code, languageExtension = jsxLanguage) { let characterIndex = 0; let parsedCharacterIndex = 0; - highlightTree(tree, classHighlighter, (from, to, className) => { - if (from > characterIndex) { - // No style applied to the token between position and from. - // This typically indicates white space or newline characters. + highlightTree( + tree, + classHighlighter, + (from: number, to: number, className: string) => { + if (from > characterIndex) { + // No style applied to the token between position and from. + // This typically indicates white space or newline characters. + processSection( + currentLineState, + parsedTokens, + code.slice(characterIndex, from), + "" + ); + } processSection( currentLineState, parsedTokens, - code.slice(characterIndex, from), - "" + code.slice(from, to), + className ); + characterIndex = to; } - processSection( - currentLineState, - parsedTokens, - code.slice(from, to), - className - ); - characterIndex = to; - }); + ); const maxPosition = code.length - 1; @@ -148,15 +167,18 @@ async function parser(code, languageExtension = jsxLanguage) { return parsedTokens; } -function processSection(currentLineState, parsedTokens, section, className) { - var _a; +function processSection( + currentLineState: State, + parsedTokens: Token[][], + section: string, + className: string +) { + // Remove "tok-" prefix; const tokenType = - (_a = - className === null || className === void 0 - ? void 0 - : className.substring(4)) !== null && _a !== void 0 - ? _a - : null; // Remove "tok-" prefix; + className === null || className === void 0 + ? null + : className.substring(4) || null; + let index = 0; let nextIndex = section.indexOf("\n"); while (true) { @@ -164,7 +186,7 @@ function processSection(currentLineState, parsedTokens, section, className) { nextIndex >= 0 ? section.substring(index, nextIndex) : section.substring(index); - const token = { + const token: Token = { columnIndex: currentLineState.rawString.length, type: tokenType, value: substring @@ -184,10 +206,10 @@ function processSection(currentLineState, parsedTokens, section, className) { } } -function parsedTokensToHtml(tokens) { +function parsedTokensToHtml(tokens: Token[]) { let indent = 0; - tokens = tokens.map((token, index) => { + const htmlStrings = tokens.map((token, index) => { const className = token.type ? `tok-${token.type}` : ""; // Trim leading space and use CSS to indent instead; @@ -207,10 +229,12 @@ function parsedTokensToHtml(tokens) { return `${escapedValue}`; }); - return `