tree-sitter-ts-highlight-cli 0.1.2

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/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # tree-sitter-ts-highlight-cli
2
+
3
+ Command-line wrapper for [`tree-sitter-ts-highlight`](https://www.npmjs.com/package/tree-sitter-ts-highlight).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g tree-sitter-ts-highlight-cli
9
+ ```
10
+
11
+ Or run with `npx`:
12
+
13
+ ```bash
14
+ npx tree-sitter-ts-highlight-cli --help
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```bash
20
+ hlts [options]
21
+ ```
22
+
23
+ ### HTML highlight
24
+
25
+ ```bash
26
+ hlts --input example.ts --language typescript --block --line-numbers > out.html
27
+ ```
28
+
29
+ ### ANSI highlight (terminal)
30
+
31
+ ```bash
32
+ hlts --input example.ts --ansi --line-numbers
33
+ ```
34
+
35
+ ### Diff highlight (HTML)
36
+
37
+ ```bash
38
+ hlts --diff --old before.ts --new after.ts --view side-by-side > diff.html
39
+ ```
40
+
41
+ ## Options
42
+
43
+ - `-i, --input <file>`: input file path (default: stdin)
44
+ - `-o, --output <file>`: output file path (default: stdout)
45
+ - `-l, --language <lang>`: language name or extension
46
+ - `--ansi`: output ANSI-colored text
47
+ - `--diff`: output highlighted HTML diff (requires `--old` and `--new`)
48
+ - `--block`: wrap HTML output in `<pre><code>`
49
+ - `--line-numbers`: include line numbers
50
+ - `--start-line <n>`: set starting line number
51
+ - `--semantic`: enable semantic token enhancement
52
+ - `--theme <name>`: built-in HTML theme name (from `tree-sitter-ts-highlight`)
53
+ - `--old <file>`: old/original file for diff mode
54
+ - `--new <file>`: new/updated file for diff mode
55
+ - `--view <mode>`: `side-by-side` or `inline` (diff mode)
56
+ - `--old-label <label>`: label for old side header
57
+ - `--new-label <label>`: label for new side header
58
+ - `--no-header`: hide diff header row
59
+ - `-h, --help`: show help
60
+ - `-v, --version`: show version
61
+
62
+ ## Programmatic API
63
+
64
+ ```ts
65
+ import { runCli, parseCliArgs } from "tree-sitter-ts-highlight-cli";
66
+ ```
67
+
68
+ The package also re-exports all public APIs from `tree-sitter-ts-highlight`.
69
+
70
+ ### TypeScript types
71
+
72
+ This package also re-exports types from both `tree-sitter-ts-highlight` and `tree-sitter-ts`, so TypeScript libraries can consume those shared types directly:
73
+
74
+ ```ts
75
+ import type { ThemeDefinition } from "tree-sitter-ts-highlight-cli";
76
+ ```
77
+
78
+ ## Test
79
+
80
+ ```bash
81
+ npm test
82
+ ```
83
+
84
+ Watch mode:
85
+
86
+ ```bash
87
+ npm run test:watch
88
+ ```
package/dist/cli.js ADDED
@@ -0,0 +1,277 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/run-cli.ts
4
+ import { extname } from "path";
5
+ import {
6
+ getTheme,
7
+ highlight,
8
+ highlightAnsi,
9
+ highlightBlock,
10
+ highlightDiff
11
+ } from "tree-sitter-ts-highlight";
12
+ var VERSION = "0.1.2";
13
+ function createHelpText() {
14
+ return [
15
+ "tree-sitter-ts-highlight-cli",
16
+ "",
17
+ "Usage:",
18
+ " hlts [options]",
19
+ "",
20
+ "Modes:",
21
+ " --ansi Output ANSI-highlighted text for terminals",
22
+ " --diff Output HTML highlighted diff (requires --old and --new)",
23
+ "",
24
+ "Input:",
25
+ " -i, --input <file> Input file path (default: stdin)",
26
+ " -o, --output <file> Output file path (default: stdout)",
27
+ " -l, --language <lang> Language or extension (default: detect from file, else typescript)",
28
+ "",
29
+ "HTML options:",
30
+ " --block Wrap output in <pre><code>",
31
+ " --line-numbers Include line numbers",
32
+ " --start-line <n> Starting line number",
33
+ " --semantic Enable semantic token enhancement",
34
+ " --theme <name> Built-in HTML theme name",
35
+ "",
36
+ "Diff options:",
37
+ " --old <file> Old/original file for diff mode",
38
+ " --new <file> New/updated file for diff mode",
39
+ " --view <mode> side-by-side | inline (default: side-by-side)",
40
+ " --old-label <label> Header label for old side",
41
+ " --new-label <label> Header label for new side",
42
+ " --no-header Hide diff headers",
43
+ "",
44
+ "General:",
45
+ " -h, --help Show help",
46
+ " -v, --version Show version"
47
+ ].join("\n");
48
+ }
49
+ function parseCliArgs(args) {
50
+ const options = {
51
+ mode: "html",
52
+ language: "typescript",
53
+ lineNumbers: false,
54
+ semanticHighlighting: false,
55
+ wrapInPre: false,
56
+ diffView: "side-by-side",
57
+ showHeader: true,
58
+ help: false,
59
+ version: false
60
+ };
61
+ for (let index = 0; index < args.length; index += 1) {
62
+ const arg = args[index];
63
+ if (arg === "-h" || arg === "--help") {
64
+ options.help = true;
65
+ continue;
66
+ }
67
+ if (arg === "-v" || arg === "--version") {
68
+ options.version = true;
69
+ continue;
70
+ }
71
+ if (arg === "--ansi") {
72
+ options.mode = "ansi";
73
+ continue;
74
+ }
75
+ if (arg === "--diff") {
76
+ options.mode = "diff";
77
+ continue;
78
+ }
79
+ if (arg === "--line-numbers") {
80
+ options.lineNumbers = true;
81
+ continue;
82
+ }
83
+ if (arg === "--semantic") {
84
+ options.semanticHighlighting = true;
85
+ continue;
86
+ }
87
+ if (arg === "--block") {
88
+ options.wrapInPre = true;
89
+ continue;
90
+ }
91
+ if (arg === "--no-header") {
92
+ options.showHeader = false;
93
+ continue;
94
+ }
95
+ if (arg === "-i" || arg === "--input") {
96
+ options.inputPath = nextValue(args, ++index, arg);
97
+ continue;
98
+ }
99
+ if (arg === "-o" || arg === "--output") {
100
+ options.outputPath = nextValue(args, ++index, arg);
101
+ continue;
102
+ }
103
+ if (arg === "-l" || arg === "--language") {
104
+ options.language = nextValue(args, ++index, arg);
105
+ continue;
106
+ }
107
+ if (arg === "--start-line") {
108
+ const value = nextValue(args, ++index, arg);
109
+ const startLine = Number.parseInt(value, 10);
110
+ if (!Number.isFinite(startLine) || startLine <= 0) {
111
+ throw new Error(`Invalid --start-line value: ${value}`);
112
+ }
113
+ options.startLine = startLine;
114
+ continue;
115
+ }
116
+ if (arg === "--theme") {
117
+ options.themeName = nextValue(args, ++index, arg);
118
+ continue;
119
+ }
120
+ if (arg === "--old") {
121
+ options.oldPath = nextValue(args, ++index, arg);
122
+ continue;
123
+ }
124
+ if (arg === "--new") {
125
+ options.newPath = nextValue(args, ++index, arg);
126
+ continue;
127
+ }
128
+ if (arg === "--view") {
129
+ const view = nextValue(args, ++index, arg);
130
+ if (view !== "side-by-side" && view !== "inline") {
131
+ throw new Error(`Invalid --view value: ${view}`);
132
+ }
133
+ options.diffView = view;
134
+ continue;
135
+ }
136
+ if (arg === "--old-label") {
137
+ options.oldLabel = nextValue(args, ++index, arg);
138
+ continue;
139
+ }
140
+ if (arg === "--new-label") {
141
+ options.newLabel = nextValue(args, ++index, arg);
142
+ continue;
143
+ }
144
+ throw new Error(`Unknown argument: ${arg}`);
145
+ }
146
+ return options;
147
+ }
148
+ async function runCli(args, io) {
149
+ try {
150
+ const options = parseCliArgs(args);
151
+ if (options.help) {
152
+ io.stdout.write(`${createHelpText()}
153
+ `);
154
+ return;
155
+ }
156
+ if (options.version) {
157
+ io.stdout.write(`${VERSION}
158
+ `);
159
+ return;
160
+ }
161
+ const renderResult = await render(options, io.stdin);
162
+ if (options.outputPath) {
163
+ const { writeFile } = await import("fs/promises");
164
+ await writeFile(options.outputPath, renderResult, "utf8");
165
+ } else {
166
+ io.stdout.write(renderResult);
167
+ if (!renderResult.endsWith("\n")) {
168
+ io.stdout.write("\n");
169
+ }
170
+ }
171
+ } catch (error) {
172
+ const message = error instanceof Error ? error.message : String(error);
173
+ io.stderr.write(`Error: ${message}
174
+ `);
175
+ io.stderr.write("Use --help to see usage.\n");
176
+ io.exit(1);
177
+ }
178
+ }
179
+ async function render(options, stdin) {
180
+ if (options.mode === "diff") {
181
+ if (!options.oldPath || !options.newPath) {
182
+ throw new Error("--diff requires both --old and --new");
183
+ }
184
+ const { readFile } = await import("fs/promises");
185
+ const [oldSource, newSource] = await Promise.all([
186
+ readFile(options.oldPath, "utf8"),
187
+ readFile(options.newPath, "utf8")
188
+ ]);
189
+ const language2 = resolveLanguage(options.language, options.newPath);
190
+ return highlightDiff(oldSource, newSource, language2, {
191
+ view: options.diffView,
192
+ semanticHighlighting: options.semanticHighlighting,
193
+ oldLabel: options.oldLabel,
194
+ newLabel: options.newLabel,
195
+ showHeader: options.showHeader,
196
+ classPrefix: "hlts-",
197
+ theme: resolveHtmlTheme(options.themeName)
198
+ });
199
+ }
200
+ const source = options.inputPath ? await readTextFile(options.inputPath) : await readStdin(stdin);
201
+ const language = resolveLanguage(options.language, options.inputPath);
202
+ if (options.mode === "ansi") {
203
+ return highlightAnsi(source, language, {
204
+ semanticHighlighting: options.semanticHighlighting,
205
+ lineNumbers: options.lineNumbers,
206
+ startLine: options.startLine
207
+ });
208
+ }
209
+ const htmlOptions = {
210
+ semanticHighlighting: options.semanticHighlighting,
211
+ lineNumbers: options.lineNumbers,
212
+ startLine: options.startLine,
213
+ theme: resolveHtmlTheme(options.themeName)
214
+ };
215
+ if (options.wrapInPre) {
216
+ return highlightBlock(source, language, {
217
+ ...htmlOptions,
218
+ language
219
+ });
220
+ }
221
+ return highlight(source, language, htmlOptions);
222
+ }
223
+ async function readTextFile(filePath) {
224
+ const { readFile } = await import("fs/promises");
225
+ return readFile(filePath, "utf8");
226
+ }
227
+ function readStdin(stdin) {
228
+ return new Promise((resolve, reject) => {
229
+ const chunks = [];
230
+ stdin.on("data", (chunk) => {
231
+ if (typeof chunk === "string") {
232
+ chunks.push(Buffer.from(chunk));
233
+ return;
234
+ }
235
+ chunks.push(chunk);
236
+ });
237
+ stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
238
+ stdin.on("error", reject);
239
+ stdin.resume();
240
+ });
241
+ }
242
+ function resolveLanguage(explicitLanguage, filePath) {
243
+ if (explicitLanguage && explicitLanguage !== "typescript") {
244
+ return explicitLanguage;
245
+ }
246
+ if (!filePath) {
247
+ return explicitLanguage || "typescript";
248
+ }
249
+ const extension = extname(filePath);
250
+ return extension || explicitLanguage || "typescript";
251
+ }
252
+ function resolveHtmlTheme(themeName) {
253
+ if (!themeName) {
254
+ return void 0;
255
+ }
256
+ const theme = getTheme(themeName);
257
+ if (!theme) {
258
+ throw new Error(`Unknown theme: ${themeName}`);
259
+ }
260
+ return theme;
261
+ }
262
+ function nextValue(args, index, flagName) {
263
+ const value = args[index];
264
+ if (!value || value.startsWith("-")) {
265
+ throw new Error(`Missing value for ${flagName}`);
266
+ }
267
+ return value;
268
+ }
269
+
270
+ // src/cli.ts
271
+ void runCli(process.argv.slice(2), {
272
+ stdin: process.stdin,
273
+ stdout: process.stdout,
274
+ stderr: process.stderr,
275
+ exit: (code) => process.exit(code)
276
+ });
277
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/run-cli.ts","../src/cli.ts"],"sourcesContent":["import { extname } from \"node:path\";\r\nimport {\r\n getTheme,\r\n highlight,\r\n highlightAnsi,\r\n highlightBlock,\r\n highlightDiff,\r\n} from \"tree-sitter-ts-highlight\";\r\n\r\nexport type CliMode = \"html\" | \"ansi\" | \"diff\";\r\n\r\nexport interface CliOptions {\r\n mode: CliMode;\r\n inputPath?: string;\r\n outputPath?: string;\r\n language: string;\r\n lineNumbers: boolean;\r\n startLine?: number;\r\n semanticHighlighting: boolean;\r\n wrapInPre: boolean;\r\n diffView: \"side-by-side\" | \"inline\";\r\n oldPath?: string;\r\n newPath?: string;\r\n oldLabel?: string;\r\n newLabel?: string;\r\n showHeader: boolean;\r\n themeName?: string;\r\n help: boolean;\r\n version: boolean;\r\n}\r\n\r\ninterface IoLike {\r\n stdin: NodeJS.ReadStream;\r\n stdout: NodeJS.WriteStream;\r\n stderr: NodeJS.WriteStream;\r\n exit: (code: number) => never | void;\r\n}\r\n\r\nconst VERSION = \"0.1.2\";\r\n\r\nexport function createHelpText(): string {\r\n return [\r\n \"tree-sitter-ts-highlight-cli\",\r\n \"\",\r\n \"Usage:\",\r\n \" hlts [options]\",\r\n \"\",\r\n \"Modes:\",\r\n \" --ansi Output ANSI-highlighted text for terminals\",\r\n \" --diff Output HTML highlighted diff (requires --old and --new)\",\r\n \"\",\r\n \"Input:\",\r\n \" -i, --input <file> Input file path (default: stdin)\",\r\n \" -o, --output <file> Output file path (default: stdout)\",\r\n \" -l, --language <lang> Language or extension (default: detect from file, else typescript)\",\r\n \"\",\r\n \"HTML options:\",\r\n \" --block Wrap output in <pre><code>\",\r\n \" --line-numbers Include line numbers\",\r\n \" --start-line <n> Starting line number\",\r\n \" --semantic Enable semantic token enhancement\",\r\n \" --theme <name> Built-in HTML theme name\",\r\n \"\",\r\n \"Diff options:\",\r\n \" --old <file> Old/original file for diff mode\",\r\n \" --new <file> New/updated file for diff mode\",\r\n \" --view <mode> side-by-side | inline (default: side-by-side)\",\r\n \" --old-label <label> Header label for old side\",\r\n \" --new-label <label> Header label for new side\",\r\n \" --no-header Hide diff headers\",\r\n \"\",\r\n \"General:\",\r\n \" -h, --help Show help\",\r\n \" -v, --version Show version\",\r\n ].join(\"\\n\");\r\n}\r\n\r\nexport function parseCliArgs(args: string[]): CliOptions {\r\n const options: CliOptions = {\r\n mode: \"html\",\r\n language: \"typescript\",\r\n lineNumbers: false,\r\n semanticHighlighting: false,\r\n wrapInPre: false,\r\n diffView: \"side-by-side\",\r\n showHeader: true,\r\n help: false,\r\n version: false,\r\n };\r\n\r\n for (let index = 0; index < args.length; index += 1) {\r\n const arg = args[index];\r\n\r\n if (arg === \"-h\" || arg === \"--help\") {\r\n options.help = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"-v\" || arg === \"--version\") {\r\n options.version = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--ansi\") {\r\n options.mode = \"ansi\";\r\n continue;\r\n }\r\n\r\n if (arg === \"--diff\") {\r\n options.mode = \"diff\";\r\n continue;\r\n }\r\n\r\n if (arg === \"--line-numbers\") {\r\n options.lineNumbers = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--semantic\") {\r\n options.semanticHighlighting = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--block\") {\r\n options.wrapInPre = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--no-header\") {\r\n options.showHeader = false;\r\n continue;\r\n }\r\n\r\n if (arg === \"-i\" || arg === \"--input\") {\r\n options.inputPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"-o\" || arg === \"--output\") {\r\n options.outputPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"-l\" || arg === \"--language\") {\r\n options.language = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--start-line\") {\r\n const value = nextValue(args, ++index, arg);\r\n const startLine = Number.parseInt(value, 10);\r\n if (!Number.isFinite(startLine) || startLine <= 0) {\r\n throw new Error(`Invalid --start-line value: ${value}`);\r\n }\r\n options.startLine = startLine;\r\n continue;\r\n }\r\n\r\n if (arg === \"--theme\") {\r\n options.themeName = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--old\") {\r\n options.oldPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--new\") {\r\n options.newPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--view\") {\r\n const view = nextValue(args, ++index, arg);\r\n if (view !== \"side-by-side\" && view !== \"inline\") {\r\n throw new Error(`Invalid --view value: ${view}`);\r\n }\r\n options.diffView = view;\r\n continue;\r\n }\r\n\r\n if (arg === \"--old-label\") {\r\n options.oldLabel = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--new-label\") {\r\n options.newLabel = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n throw new Error(`Unknown argument: ${arg}`);\r\n }\r\n\r\n return options;\r\n}\r\n\r\nexport async function runCli(args: string[], io: IoLike): Promise<void> {\r\n try {\r\n const options = parseCliArgs(args);\r\n\r\n if (options.help) {\r\n io.stdout.write(`${createHelpText()}\\n`);\r\n return;\r\n }\r\n\r\n if (options.version) {\r\n io.stdout.write(`${VERSION}\\n`);\r\n return;\r\n }\r\n\r\n const renderResult = await render(options, io.stdin);\r\n\r\n if (options.outputPath) {\r\n const { writeFile } = await import(\"node:fs/promises\");\r\n await writeFile(options.outputPath, renderResult, \"utf8\");\r\n } else {\r\n io.stdout.write(renderResult);\r\n if (!renderResult.endsWith(\"\\n\")) {\r\n io.stdout.write(\"\\n\");\r\n }\r\n }\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n io.stderr.write(`Error: ${message}\\n`);\r\n io.stderr.write(\"Use --help to see usage.\\n\");\r\n io.exit(1);\r\n }\r\n}\r\n\r\nasync function render(options: CliOptions, stdin: NodeJS.ReadStream): Promise<string> {\r\n if (options.mode === \"diff\") {\r\n if (!options.oldPath || !options.newPath) {\r\n throw new Error(\"--diff requires both --old and --new\");\r\n }\r\n\r\n const { readFile } = await import(\"node:fs/promises\");\r\n const [oldSource, newSource] = await Promise.all([\r\n readFile(options.oldPath, \"utf8\"),\r\n readFile(options.newPath, \"utf8\"),\r\n ]);\r\n\r\n const language = resolveLanguage(options.language, options.newPath);\r\n\r\n return highlightDiff(oldSource, newSource, language, {\r\n view: options.diffView,\r\n semanticHighlighting: options.semanticHighlighting,\r\n oldLabel: options.oldLabel,\r\n newLabel: options.newLabel,\r\n showHeader: options.showHeader,\r\n classPrefix: \"hlts-\",\r\n theme: resolveHtmlTheme(options.themeName),\r\n });\r\n }\r\n\r\n const source = options.inputPath\r\n ? await readTextFile(options.inputPath)\r\n : await readStdin(stdin);\r\n\r\n const language = resolveLanguage(options.language, options.inputPath);\r\n\r\n if (options.mode === \"ansi\") {\r\n return highlightAnsi(source, language, {\r\n semanticHighlighting: options.semanticHighlighting,\r\n lineNumbers: options.lineNumbers,\r\n startLine: options.startLine,\r\n });\r\n }\r\n\r\n const htmlOptions = {\r\n semanticHighlighting: options.semanticHighlighting,\r\n lineNumbers: options.lineNumbers,\r\n startLine: options.startLine,\r\n theme: resolveHtmlTheme(options.themeName),\r\n };\r\n\r\n if (options.wrapInPre) {\r\n return highlightBlock(source, language, {\r\n ...htmlOptions,\r\n language,\r\n });\r\n }\r\n\r\n return highlight(source, language, htmlOptions);\r\n}\r\n\r\nasync function readTextFile(filePath: string): Promise<string> {\r\n const { readFile } = await import(\"node:fs/promises\");\r\n return readFile(filePath, \"utf8\");\r\n}\r\n\r\nfunction readStdin(stdin: NodeJS.ReadStream): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const chunks: Buffer[] = [];\r\n stdin.on(\"data\", (chunk: Buffer | string) => {\r\n if (typeof chunk === \"string\") {\r\n chunks.push(Buffer.from(chunk));\r\n return;\r\n }\r\n chunks.push(chunk);\r\n });\r\n stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")));\r\n stdin.on(\"error\", reject);\r\n stdin.resume();\r\n });\r\n}\r\n\r\nfunction resolveLanguage(explicitLanguage: string, filePath?: string): string {\r\n if (explicitLanguage && explicitLanguage !== \"typescript\") {\r\n return explicitLanguage;\r\n }\r\n\r\n if (!filePath) {\r\n return explicitLanguage || \"typescript\";\r\n }\r\n\r\n const extension = extname(filePath);\r\n return extension || explicitLanguage || \"typescript\";\r\n}\r\n\r\nfunction resolveHtmlTheme(themeName?: string) {\r\n if (!themeName) {\r\n return undefined;\r\n }\r\n\r\n const theme = getTheme(themeName);\r\n if (!theme) {\r\n throw new Error(`Unknown theme: ${themeName}`);\r\n }\r\n return theme;\r\n}\r\n\r\nfunction nextValue(args: string[], index: number, flagName: string): string {\r\n const value = args[index];\r\n if (!value || value.startsWith(\"-\")) {\r\n throw new Error(`Missing value for ${flagName}`);\r\n }\r\n return value;\r\n}\r\n","import { runCli } from \"./run-cli\";\r\n\r\nvoid runCli(process.argv.slice(2), {\r\n stdin: process.stdin,\r\n stdout: process.stdout,\r\n stderr: process.stderr,\r\n exit: (code) => process.exit(code),\r\n});\r\n"],"mappings":"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","names":["language"]}
package/dist/index.cjs ADDED
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ createHelpText: () => createHelpText,
35
+ parseCliArgs: () => parseCliArgs,
36
+ runCli: () => runCli
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+
40
+ // src/run-cli.ts
41
+ var import_node_path = require("path");
42
+ var import_tree_sitter_ts_highlight = require("tree-sitter-ts-highlight");
43
+ var VERSION = "0.1.2";
44
+ function createHelpText() {
45
+ return [
46
+ "tree-sitter-ts-highlight-cli",
47
+ "",
48
+ "Usage:",
49
+ " hlts [options]",
50
+ "",
51
+ "Modes:",
52
+ " --ansi Output ANSI-highlighted text for terminals",
53
+ " --diff Output HTML highlighted diff (requires --old and --new)",
54
+ "",
55
+ "Input:",
56
+ " -i, --input <file> Input file path (default: stdin)",
57
+ " -o, --output <file> Output file path (default: stdout)",
58
+ " -l, --language <lang> Language or extension (default: detect from file, else typescript)",
59
+ "",
60
+ "HTML options:",
61
+ " --block Wrap output in <pre><code>",
62
+ " --line-numbers Include line numbers",
63
+ " --start-line <n> Starting line number",
64
+ " --semantic Enable semantic token enhancement",
65
+ " --theme <name> Built-in HTML theme name",
66
+ "",
67
+ "Diff options:",
68
+ " --old <file> Old/original file for diff mode",
69
+ " --new <file> New/updated file for diff mode",
70
+ " --view <mode> side-by-side | inline (default: side-by-side)",
71
+ " --old-label <label> Header label for old side",
72
+ " --new-label <label> Header label for new side",
73
+ " --no-header Hide diff headers",
74
+ "",
75
+ "General:",
76
+ " -h, --help Show help",
77
+ " -v, --version Show version"
78
+ ].join("\n");
79
+ }
80
+ function parseCliArgs(args) {
81
+ const options = {
82
+ mode: "html",
83
+ language: "typescript",
84
+ lineNumbers: false,
85
+ semanticHighlighting: false,
86
+ wrapInPre: false,
87
+ diffView: "side-by-side",
88
+ showHeader: true,
89
+ help: false,
90
+ version: false
91
+ };
92
+ for (let index = 0; index < args.length; index += 1) {
93
+ const arg = args[index];
94
+ if (arg === "-h" || arg === "--help") {
95
+ options.help = true;
96
+ continue;
97
+ }
98
+ if (arg === "-v" || arg === "--version") {
99
+ options.version = true;
100
+ continue;
101
+ }
102
+ if (arg === "--ansi") {
103
+ options.mode = "ansi";
104
+ continue;
105
+ }
106
+ if (arg === "--diff") {
107
+ options.mode = "diff";
108
+ continue;
109
+ }
110
+ if (arg === "--line-numbers") {
111
+ options.lineNumbers = true;
112
+ continue;
113
+ }
114
+ if (arg === "--semantic") {
115
+ options.semanticHighlighting = true;
116
+ continue;
117
+ }
118
+ if (arg === "--block") {
119
+ options.wrapInPre = true;
120
+ continue;
121
+ }
122
+ if (arg === "--no-header") {
123
+ options.showHeader = false;
124
+ continue;
125
+ }
126
+ if (arg === "-i" || arg === "--input") {
127
+ options.inputPath = nextValue(args, ++index, arg);
128
+ continue;
129
+ }
130
+ if (arg === "-o" || arg === "--output") {
131
+ options.outputPath = nextValue(args, ++index, arg);
132
+ continue;
133
+ }
134
+ if (arg === "-l" || arg === "--language") {
135
+ options.language = nextValue(args, ++index, arg);
136
+ continue;
137
+ }
138
+ if (arg === "--start-line") {
139
+ const value = nextValue(args, ++index, arg);
140
+ const startLine = Number.parseInt(value, 10);
141
+ if (!Number.isFinite(startLine) || startLine <= 0) {
142
+ throw new Error(`Invalid --start-line value: ${value}`);
143
+ }
144
+ options.startLine = startLine;
145
+ continue;
146
+ }
147
+ if (arg === "--theme") {
148
+ options.themeName = nextValue(args, ++index, arg);
149
+ continue;
150
+ }
151
+ if (arg === "--old") {
152
+ options.oldPath = nextValue(args, ++index, arg);
153
+ continue;
154
+ }
155
+ if (arg === "--new") {
156
+ options.newPath = nextValue(args, ++index, arg);
157
+ continue;
158
+ }
159
+ if (arg === "--view") {
160
+ const view = nextValue(args, ++index, arg);
161
+ if (view !== "side-by-side" && view !== "inline") {
162
+ throw new Error(`Invalid --view value: ${view}`);
163
+ }
164
+ options.diffView = view;
165
+ continue;
166
+ }
167
+ if (arg === "--old-label") {
168
+ options.oldLabel = nextValue(args, ++index, arg);
169
+ continue;
170
+ }
171
+ if (arg === "--new-label") {
172
+ options.newLabel = nextValue(args, ++index, arg);
173
+ continue;
174
+ }
175
+ throw new Error(`Unknown argument: ${arg}`);
176
+ }
177
+ return options;
178
+ }
179
+ async function runCli(args, io) {
180
+ try {
181
+ const options = parseCliArgs(args);
182
+ if (options.help) {
183
+ io.stdout.write(`${createHelpText()}
184
+ `);
185
+ return;
186
+ }
187
+ if (options.version) {
188
+ io.stdout.write(`${VERSION}
189
+ `);
190
+ return;
191
+ }
192
+ const renderResult = await render(options, io.stdin);
193
+ if (options.outputPath) {
194
+ const { writeFile } = await import("fs/promises");
195
+ await writeFile(options.outputPath, renderResult, "utf8");
196
+ } else {
197
+ io.stdout.write(renderResult);
198
+ if (!renderResult.endsWith("\n")) {
199
+ io.stdout.write("\n");
200
+ }
201
+ }
202
+ } catch (error) {
203
+ const message = error instanceof Error ? error.message : String(error);
204
+ io.stderr.write(`Error: ${message}
205
+ `);
206
+ io.stderr.write("Use --help to see usage.\n");
207
+ io.exit(1);
208
+ }
209
+ }
210
+ async function render(options, stdin) {
211
+ if (options.mode === "diff") {
212
+ if (!options.oldPath || !options.newPath) {
213
+ throw new Error("--diff requires both --old and --new");
214
+ }
215
+ const { readFile } = await import("fs/promises");
216
+ const [oldSource, newSource] = await Promise.all([
217
+ readFile(options.oldPath, "utf8"),
218
+ readFile(options.newPath, "utf8")
219
+ ]);
220
+ const language2 = resolveLanguage(options.language, options.newPath);
221
+ return (0, import_tree_sitter_ts_highlight.highlightDiff)(oldSource, newSource, language2, {
222
+ view: options.diffView,
223
+ semanticHighlighting: options.semanticHighlighting,
224
+ oldLabel: options.oldLabel,
225
+ newLabel: options.newLabel,
226
+ showHeader: options.showHeader,
227
+ classPrefix: "hlts-",
228
+ theme: resolveHtmlTheme(options.themeName)
229
+ });
230
+ }
231
+ const source = options.inputPath ? await readTextFile(options.inputPath) : await readStdin(stdin);
232
+ const language = resolveLanguage(options.language, options.inputPath);
233
+ if (options.mode === "ansi") {
234
+ return (0, import_tree_sitter_ts_highlight.highlightAnsi)(source, language, {
235
+ semanticHighlighting: options.semanticHighlighting,
236
+ lineNumbers: options.lineNumbers,
237
+ startLine: options.startLine
238
+ });
239
+ }
240
+ const htmlOptions = {
241
+ semanticHighlighting: options.semanticHighlighting,
242
+ lineNumbers: options.lineNumbers,
243
+ startLine: options.startLine,
244
+ theme: resolveHtmlTheme(options.themeName)
245
+ };
246
+ if (options.wrapInPre) {
247
+ return (0, import_tree_sitter_ts_highlight.highlightBlock)(source, language, {
248
+ ...htmlOptions,
249
+ language
250
+ });
251
+ }
252
+ return (0, import_tree_sitter_ts_highlight.highlight)(source, language, htmlOptions);
253
+ }
254
+ async function readTextFile(filePath) {
255
+ const { readFile } = await import("fs/promises");
256
+ return readFile(filePath, "utf8");
257
+ }
258
+ function readStdin(stdin) {
259
+ return new Promise((resolve, reject) => {
260
+ const chunks = [];
261
+ stdin.on("data", (chunk) => {
262
+ if (typeof chunk === "string") {
263
+ chunks.push(Buffer.from(chunk));
264
+ return;
265
+ }
266
+ chunks.push(chunk);
267
+ });
268
+ stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
269
+ stdin.on("error", reject);
270
+ stdin.resume();
271
+ });
272
+ }
273
+ function resolveLanguage(explicitLanguage, filePath) {
274
+ if (explicitLanguage && explicitLanguage !== "typescript") {
275
+ return explicitLanguage;
276
+ }
277
+ if (!filePath) {
278
+ return explicitLanguage || "typescript";
279
+ }
280
+ const extension = (0, import_node_path.extname)(filePath);
281
+ return extension || explicitLanguage || "typescript";
282
+ }
283
+ function resolveHtmlTheme(themeName) {
284
+ if (!themeName) {
285
+ return void 0;
286
+ }
287
+ const theme = (0, import_tree_sitter_ts_highlight.getTheme)(themeName);
288
+ if (!theme) {
289
+ throw new Error(`Unknown theme: ${themeName}`);
290
+ }
291
+ return theme;
292
+ }
293
+ function nextValue(args, index, flagName) {
294
+ const value = args[index];
295
+ if (!value || value.startsWith("-")) {
296
+ throw new Error(`Missing value for ${flagName}`);
297
+ }
298
+ return value;
299
+ }
300
+
301
+ // src/index.ts
302
+ __reExport(index_exports, require("tree-sitter-ts-highlight"), module.exports);
303
+ // Annotate the CommonJS export names for ESM import in node:
304
+ 0 && (module.exports = {
305
+ createHelpText,
306
+ parseCliArgs,
307
+ runCli,
308
+ ...require("tree-sitter-ts-highlight")
309
+ });
310
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/run-cli.ts"],"sourcesContent":["export {\r\n runCli,\r\n parseCliArgs,\r\n createHelpText,\r\n type CliOptions,\r\n type CliMode,\r\n} from \"./run-cli\";\r\n\r\nexport * from \"tree-sitter-ts-highlight\";\r\nexport type * from \"tree-sitter-ts-highlight\";\r\nexport type * from \"tree-sitter-ts\";\r\n","import { extname } from \"node:path\";\r\nimport {\r\n getTheme,\r\n highlight,\r\n highlightAnsi,\r\n highlightBlock,\r\n highlightDiff,\r\n} from \"tree-sitter-ts-highlight\";\r\n\r\nexport type CliMode = \"html\" | \"ansi\" | \"diff\";\r\n\r\nexport interface CliOptions {\r\n mode: CliMode;\r\n inputPath?: string;\r\n outputPath?: string;\r\n language: string;\r\n lineNumbers: boolean;\r\n startLine?: number;\r\n semanticHighlighting: boolean;\r\n wrapInPre: boolean;\r\n diffView: \"side-by-side\" | \"inline\";\r\n oldPath?: string;\r\n newPath?: string;\r\n oldLabel?: string;\r\n newLabel?: string;\r\n showHeader: boolean;\r\n themeName?: string;\r\n help: boolean;\r\n version: boolean;\r\n}\r\n\r\ninterface IoLike {\r\n stdin: NodeJS.ReadStream;\r\n stdout: NodeJS.WriteStream;\r\n stderr: NodeJS.WriteStream;\r\n exit: (code: number) => never | void;\r\n}\r\n\r\nconst VERSION = \"0.1.2\";\r\n\r\nexport function createHelpText(): string {\r\n return [\r\n \"tree-sitter-ts-highlight-cli\",\r\n \"\",\r\n \"Usage:\",\r\n \" hlts [options]\",\r\n \"\",\r\n \"Modes:\",\r\n \" --ansi Output ANSI-highlighted text for terminals\",\r\n \" --diff Output HTML highlighted diff (requires --old and --new)\",\r\n \"\",\r\n \"Input:\",\r\n \" -i, --input <file> Input file path (default: stdin)\",\r\n \" -o, --output <file> Output file path (default: stdout)\",\r\n \" -l, --language <lang> Language or extension (default: detect from file, else typescript)\",\r\n \"\",\r\n \"HTML options:\",\r\n \" --block Wrap output in <pre><code>\",\r\n \" --line-numbers Include line numbers\",\r\n \" --start-line <n> Starting line number\",\r\n \" --semantic Enable semantic token enhancement\",\r\n \" --theme <name> Built-in HTML theme name\",\r\n \"\",\r\n \"Diff options:\",\r\n \" --old <file> Old/original file for diff mode\",\r\n \" --new <file> New/updated file for diff mode\",\r\n \" --view <mode> side-by-side | inline (default: side-by-side)\",\r\n \" --old-label <label> Header label for old side\",\r\n \" --new-label <label> Header label for new side\",\r\n \" --no-header Hide diff headers\",\r\n \"\",\r\n \"General:\",\r\n \" -h, --help Show help\",\r\n \" -v, --version Show version\",\r\n ].join(\"\\n\");\r\n}\r\n\r\nexport function parseCliArgs(args: string[]): CliOptions {\r\n const options: CliOptions = {\r\n mode: \"html\",\r\n language: \"typescript\",\r\n lineNumbers: false,\r\n semanticHighlighting: false,\r\n wrapInPre: false,\r\n diffView: \"side-by-side\",\r\n showHeader: true,\r\n help: false,\r\n version: false,\r\n };\r\n\r\n for (let index = 0; index < args.length; index += 1) {\r\n const arg = args[index];\r\n\r\n if (arg === \"-h\" || arg === \"--help\") {\r\n options.help = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"-v\" || arg === \"--version\") {\r\n options.version = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--ansi\") {\r\n options.mode = \"ansi\";\r\n continue;\r\n }\r\n\r\n if (arg === \"--diff\") {\r\n options.mode = \"diff\";\r\n continue;\r\n }\r\n\r\n if (arg === \"--line-numbers\") {\r\n options.lineNumbers = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--semantic\") {\r\n options.semanticHighlighting = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--block\") {\r\n options.wrapInPre = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--no-header\") {\r\n options.showHeader = false;\r\n continue;\r\n }\r\n\r\n if (arg === \"-i\" || arg === \"--input\") {\r\n options.inputPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"-o\" || arg === \"--output\") {\r\n options.outputPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"-l\" || arg === \"--language\") {\r\n options.language = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--start-line\") {\r\n const value = nextValue(args, ++index, arg);\r\n const startLine = Number.parseInt(value, 10);\r\n if (!Number.isFinite(startLine) || startLine <= 0) {\r\n throw new Error(`Invalid --start-line value: ${value}`);\r\n }\r\n options.startLine = startLine;\r\n continue;\r\n }\r\n\r\n if (arg === \"--theme\") {\r\n options.themeName = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--old\") {\r\n options.oldPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--new\") {\r\n options.newPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--view\") {\r\n const view = nextValue(args, ++index, arg);\r\n if (view !== \"side-by-side\" && view !== \"inline\") {\r\n throw new Error(`Invalid --view value: ${view}`);\r\n }\r\n options.diffView = view;\r\n continue;\r\n }\r\n\r\n if (arg === \"--old-label\") {\r\n options.oldLabel = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--new-label\") {\r\n options.newLabel = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n throw new Error(`Unknown argument: ${arg}`);\r\n }\r\n\r\n return options;\r\n}\r\n\r\nexport async function runCli(args: string[], io: IoLike): Promise<void> {\r\n try {\r\n const options = parseCliArgs(args);\r\n\r\n if (options.help) {\r\n io.stdout.write(`${createHelpText()}\\n`);\r\n return;\r\n }\r\n\r\n if (options.version) {\r\n io.stdout.write(`${VERSION}\\n`);\r\n return;\r\n }\r\n\r\n const renderResult = await render(options, io.stdin);\r\n\r\n if (options.outputPath) {\r\n const { writeFile } = await import(\"node:fs/promises\");\r\n await writeFile(options.outputPath, renderResult, \"utf8\");\r\n } else {\r\n io.stdout.write(renderResult);\r\n if (!renderResult.endsWith(\"\\n\")) {\r\n io.stdout.write(\"\\n\");\r\n }\r\n }\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n io.stderr.write(`Error: ${message}\\n`);\r\n io.stderr.write(\"Use --help to see usage.\\n\");\r\n io.exit(1);\r\n }\r\n}\r\n\r\nasync function render(options: CliOptions, stdin: NodeJS.ReadStream): Promise<string> {\r\n if (options.mode === \"diff\") {\r\n if (!options.oldPath || !options.newPath) {\r\n throw new Error(\"--diff requires both --old and --new\");\r\n }\r\n\r\n const { readFile } = await import(\"node:fs/promises\");\r\n const [oldSource, newSource] = await Promise.all([\r\n readFile(options.oldPath, \"utf8\"),\r\n readFile(options.newPath, \"utf8\"),\r\n ]);\r\n\r\n const language = resolveLanguage(options.language, options.newPath);\r\n\r\n return highlightDiff(oldSource, newSource, language, {\r\n view: options.diffView,\r\n semanticHighlighting: options.semanticHighlighting,\r\n oldLabel: options.oldLabel,\r\n newLabel: options.newLabel,\r\n showHeader: options.showHeader,\r\n classPrefix: \"hlts-\",\r\n theme: resolveHtmlTheme(options.themeName),\r\n });\r\n }\r\n\r\n const source = options.inputPath\r\n ? await readTextFile(options.inputPath)\r\n : await readStdin(stdin);\r\n\r\n const language = resolveLanguage(options.language, options.inputPath);\r\n\r\n if (options.mode === \"ansi\") {\r\n return highlightAnsi(source, language, {\r\n semanticHighlighting: options.semanticHighlighting,\r\n lineNumbers: options.lineNumbers,\r\n startLine: options.startLine,\r\n });\r\n }\r\n\r\n const htmlOptions = {\r\n semanticHighlighting: options.semanticHighlighting,\r\n lineNumbers: options.lineNumbers,\r\n startLine: options.startLine,\r\n theme: resolveHtmlTheme(options.themeName),\r\n };\r\n\r\n if (options.wrapInPre) {\r\n return highlightBlock(source, language, {\r\n ...htmlOptions,\r\n language,\r\n });\r\n }\r\n\r\n return highlight(source, language, htmlOptions);\r\n}\r\n\r\nasync function readTextFile(filePath: string): Promise<string> {\r\n const { readFile } = await import(\"node:fs/promises\");\r\n return readFile(filePath, \"utf8\");\r\n}\r\n\r\nfunction readStdin(stdin: NodeJS.ReadStream): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const chunks: Buffer[] = [];\r\n stdin.on(\"data\", (chunk: Buffer | string) => {\r\n if (typeof chunk === \"string\") {\r\n chunks.push(Buffer.from(chunk));\r\n return;\r\n }\r\n chunks.push(chunk);\r\n });\r\n stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")));\r\n stdin.on(\"error\", reject);\r\n stdin.resume();\r\n });\r\n}\r\n\r\nfunction resolveLanguage(explicitLanguage: string, filePath?: string): string {\r\n if (explicitLanguage && explicitLanguage !== \"typescript\") {\r\n return explicitLanguage;\r\n }\r\n\r\n if (!filePath) {\r\n return explicitLanguage || \"typescript\";\r\n }\r\n\r\n const extension = extname(filePath);\r\n return extension || explicitLanguage || \"typescript\";\r\n}\r\n\r\nfunction resolveHtmlTheme(themeName?: string) {\r\n if (!themeName) {\r\n return undefined;\r\n }\r\n\r\n const theme = getTheme(themeName);\r\n if (!theme) {\r\n throw new Error(`Unknown theme: ${themeName}`);\r\n }\r\n return theme;\r\n}\r\n\r\nfunction nextValue(args: string[], index: number, flagName: string): string {\r\n const value = args[index];\r\n if (!value || value.startsWith(\"-\")) {\r\n throw new Error(`Missing value for ${flagName}`);\r\n }\r\n return value;\r\n}\r\n"],"mappings":"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","names":["language"]}
@@ -0,0 +1,34 @@
1
+ export * from 'tree-sitter-ts-highlight';
2
+ export * from 'tree-sitter-ts';
3
+
4
+ type CliMode = "html" | "ansi" | "diff";
5
+ interface CliOptions {
6
+ mode: CliMode;
7
+ inputPath?: string;
8
+ outputPath?: string;
9
+ language: string;
10
+ lineNumbers: boolean;
11
+ startLine?: number;
12
+ semanticHighlighting: boolean;
13
+ wrapInPre: boolean;
14
+ diffView: "side-by-side" | "inline";
15
+ oldPath?: string;
16
+ newPath?: string;
17
+ oldLabel?: string;
18
+ newLabel?: string;
19
+ showHeader: boolean;
20
+ themeName?: string;
21
+ help: boolean;
22
+ version: boolean;
23
+ }
24
+ interface IoLike {
25
+ stdin: NodeJS.ReadStream;
26
+ stdout: NodeJS.WriteStream;
27
+ stderr: NodeJS.WriteStream;
28
+ exit: (code: number) => never | void;
29
+ }
30
+ declare function createHelpText(): string;
31
+ declare function parseCliArgs(args: string[]): CliOptions;
32
+ declare function runCli(args: string[], io: IoLike): Promise<void>;
33
+
34
+ export { type CliMode, type CliOptions, createHelpText, parseCliArgs, runCli };
@@ -0,0 +1,34 @@
1
+ export * from 'tree-sitter-ts-highlight';
2
+ export * from 'tree-sitter-ts';
3
+
4
+ type CliMode = "html" | "ansi" | "diff";
5
+ interface CliOptions {
6
+ mode: CliMode;
7
+ inputPath?: string;
8
+ outputPath?: string;
9
+ language: string;
10
+ lineNumbers: boolean;
11
+ startLine?: number;
12
+ semanticHighlighting: boolean;
13
+ wrapInPre: boolean;
14
+ diffView: "side-by-side" | "inline";
15
+ oldPath?: string;
16
+ newPath?: string;
17
+ oldLabel?: string;
18
+ newLabel?: string;
19
+ showHeader: boolean;
20
+ themeName?: string;
21
+ help: boolean;
22
+ version: boolean;
23
+ }
24
+ interface IoLike {
25
+ stdin: NodeJS.ReadStream;
26
+ stdout: NodeJS.WriteStream;
27
+ stderr: NodeJS.WriteStream;
28
+ exit: (code: number) => never | void;
29
+ }
30
+ declare function createHelpText(): string;
31
+ declare function parseCliArgs(args: string[]): CliOptions;
32
+ declare function runCli(args: string[], io: IoLike): Promise<void>;
33
+
34
+ export { type CliMode, type CliOptions, createHelpText, parseCliArgs, runCli };
package/dist/index.js ADDED
@@ -0,0 +1,275 @@
1
+ // src/run-cli.ts
2
+ import { extname } from "path";
3
+ import {
4
+ getTheme,
5
+ highlight,
6
+ highlightAnsi,
7
+ highlightBlock,
8
+ highlightDiff
9
+ } from "tree-sitter-ts-highlight";
10
+ var VERSION = "0.1.2";
11
+ function createHelpText() {
12
+ return [
13
+ "tree-sitter-ts-highlight-cli",
14
+ "",
15
+ "Usage:",
16
+ " hlts [options]",
17
+ "",
18
+ "Modes:",
19
+ " --ansi Output ANSI-highlighted text for terminals",
20
+ " --diff Output HTML highlighted diff (requires --old and --new)",
21
+ "",
22
+ "Input:",
23
+ " -i, --input <file> Input file path (default: stdin)",
24
+ " -o, --output <file> Output file path (default: stdout)",
25
+ " -l, --language <lang> Language or extension (default: detect from file, else typescript)",
26
+ "",
27
+ "HTML options:",
28
+ " --block Wrap output in <pre><code>",
29
+ " --line-numbers Include line numbers",
30
+ " --start-line <n> Starting line number",
31
+ " --semantic Enable semantic token enhancement",
32
+ " --theme <name> Built-in HTML theme name",
33
+ "",
34
+ "Diff options:",
35
+ " --old <file> Old/original file for diff mode",
36
+ " --new <file> New/updated file for diff mode",
37
+ " --view <mode> side-by-side | inline (default: side-by-side)",
38
+ " --old-label <label> Header label for old side",
39
+ " --new-label <label> Header label for new side",
40
+ " --no-header Hide diff headers",
41
+ "",
42
+ "General:",
43
+ " -h, --help Show help",
44
+ " -v, --version Show version"
45
+ ].join("\n");
46
+ }
47
+ function parseCliArgs(args) {
48
+ const options = {
49
+ mode: "html",
50
+ language: "typescript",
51
+ lineNumbers: false,
52
+ semanticHighlighting: false,
53
+ wrapInPre: false,
54
+ diffView: "side-by-side",
55
+ showHeader: true,
56
+ help: false,
57
+ version: false
58
+ };
59
+ for (let index = 0; index < args.length; index += 1) {
60
+ const arg = args[index];
61
+ if (arg === "-h" || arg === "--help") {
62
+ options.help = true;
63
+ continue;
64
+ }
65
+ if (arg === "-v" || arg === "--version") {
66
+ options.version = true;
67
+ continue;
68
+ }
69
+ if (arg === "--ansi") {
70
+ options.mode = "ansi";
71
+ continue;
72
+ }
73
+ if (arg === "--diff") {
74
+ options.mode = "diff";
75
+ continue;
76
+ }
77
+ if (arg === "--line-numbers") {
78
+ options.lineNumbers = true;
79
+ continue;
80
+ }
81
+ if (arg === "--semantic") {
82
+ options.semanticHighlighting = true;
83
+ continue;
84
+ }
85
+ if (arg === "--block") {
86
+ options.wrapInPre = true;
87
+ continue;
88
+ }
89
+ if (arg === "--no-header") {
90
+ options.showHeader = false;
91
+ continue;
92
+ }
93
+ if (arg === "-i" || arg === "--input") {
94
+ options.inputPath = nextValue(args, ++index, arg);
95
+ continue;
96
+ }
97
+ if (arg === "-o" || arg === "--output") {
98
+ options.outputPath = nextValue(args, ++index, arg);
99
+ continue;
100
+ }
101
+ if (arg === "-l" || arg === "--language") {
102
+ options.language = nextValue(args, ++index, arg);
103
+ continue;
104
+ }
105
+ if (arg === "--start-line") {
106
+ const value = nextValue(args, ++index, arg);
107
+ const startLine = Number.parseInt(value, 10);
108
+ if (!Number.isFinite(startLine) || startLine <= 0) {
109
+ throw new Error(`Invalid --start-line value: ${value}`);
110
+ }
111
+ options.startLine = startLine;
112
+ continue;
113
+ }
114
+ if (arg === "--theme") {
115
+ options.themeName = nextValue(args, ++index, arg);
116
+ continue;
117
+ }
118
+ if (arg === "--old") {
119
+ options.oldPath = nextValue(args, ++index, arg);
120
+ continue;
121
+ }
122
+ if (arg === "--new") {
123
+ options.newPath = nextValue(args, ++index, arg);
124
+ continue;
125
+ }
126
+ if (arg === "--view") {
127
+ const view = nextValue(args, ++index, arg);
128
+ if (view !== "side-by-side" && view !== "inline") {
129
+ throw new Error(`Invalid --view value: ${view}`);
130
+ }
131
+ options.diffView = view;
132
+ continue;
133
+ }
134
+ if (arg === "--old-label") {
135
+ options.oldLabel = nextValue(args, ++index, arg);
136
+ continue;
137
+ }
138
+ if (arg === "--new-label") {
139
+ options.newLabel = nextValue(args, ++index, arg);
140
+ continue;
141
+ }
142
+ throw new Error(`Unknown argument: ${arg}`);
143
+ }
144
+ return options;
145
+ }
146
+ async function runCli(args, io) {
147
+ try {
148
+ const options = parseCliArgs(args);
149
+ if (options.help) {
150
+ io.stdout.write(`${createHelpText()}
151
+ `);
152
+ return;
153
+ }
154
+ if (options.version) {
155
+ io.stdout.write(`${VERSION}
156
+ `);
157
+ return;
158
+ }
159
+ const renderResult = await render(options, io.stdin);
160
+ if (options.outputPath) {
161
+ const { writeFile } = await import("fs/promises");
162
+ await writeFile(options.outputPath, renderResult, "utf8");
163
+ } else {
164
+ io.stdout.write(renderResult);
165
+ if (!renderResult.endsWith("\n")) {
166
+ io.stdout.write("\n");
167
+ }
168
+ }
169
+ } catch (error) {
170
+ const message = error instanceof Error ? error.message : String(error);
171
+ io.stderr.write(`Error: ${message}
172
+ `);
173
+ io.stderr.write("Use --help to see usage.\n");
174
+ io.exit(1);
175
+ }
176
+ }
177
+ async function render(options, stdin) {
178
+ if (options.mode === "diff") {
179
+ if (!options.oldPath || !options.newPath) {
180
+ throw new Error("--diff requires both --old and --new");
181
+ }
182
+ const { readFile } = await import("fs/promises");
183
+ const [oldSource, newSource] = await Promise.all([
184
+ readFile(options.oldPath, "utf8"),
185
+ readFile(options.newPath, "utf8")
186
+ ]);
187
+ const language2 = resolveLanguage(options.language, options.newPath);
188
+ return highlightDiff(oldSource, newSource, language2, {
189
+ view: options.diffView,
190
+ semanticHighlighting: options.semanticHighlighting,
191
+ oldLabel: options.oldLabel,
192
+ newLabel: options.newLabel,
193
+ showHeader: options.showHeader,
194
+ classPrefix: "hlts-",
195
+ theme: resolveHtmlTheme(options.themeName)
196
+ });
197
+ }
198
+ const source = options.inputPath ? await readTextFile(options.inputPath) : await readStdin(stdin);
199
+ const language = resolveLanguage(options.language, options.inputPath);
200
+ if (options.mode === "ansi") {
201
+ return highlightAnsi(source, language, {
202
+ semanticHighlighting: options.semanticHighlighting,
203
+ lineNumbers: options.lineNumbers,
204
+ startLine: options.startLine
205
+ });
206
+ }
207
+ const htmlOptions = {
208
+ semanticHighlighting: options.semanticHighlighting,
209
+ lineNumbers: options.lineNumbers,
210
+ startLine: options.startLine,
211
+ theme: resolveHtmlTheme(options.themeName)
212
+ };
213
+ if (options.wrapInPre) {
214
+ return highlightBlock(source, language, {
215
+ ...htmlOptions,
216
+ language
217
+ });
218
+ }
219
+ return highlight(source, language, htmlOptions);
220
+ }
221
+ async function readTextFile(filePath) {
222
+ const { readFile } = await import("fs/promises");
223
+ return readFile(filePath, "utf8");
224
+ }
225
+ function readStdin(stdin) {
226
+ return new Promise((resolve, reject) => {
227
+ const chunks = [];
228
+ stdin.on("data", (chunk) => {
229
+ if (typeof chunk === "string") {
230
+ chunks.push(Buffer.from(chunk));
231
+ return;
232
+ }
233
+ chunks.push(chunk);
234
+ });
235
+ stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
236
+ stdin.on("error", reject);
237
+ stdin.resume();
238
+ });
239
+ }
240
+ function resolveLanguage(explicitLanguage, filePath) {
241
+ if (explicitLanguage && explicitLanguage !== "typescript") {
242
+ return explicitLanguage;
243
+ }
244
+ if (!filePath) {
245
+ return explicitLanguage || "typescript";
246
+ }
247
+ const extension = extname(filePath);
248
+ return extension || explicitLanguage || "typescript";
249
+ }
250
+ function resolveHtmlTheme(themeName) {
251
+ if (!themeName) {
252
+ return void 0;
253
+ }
254
+ const theme = getTheme(themeName);
255
+ if (!theme) {
256
+ throw new Error(`Unknown theme: ${themeName}`);
257
+ }
258
+ return theme;
259
+ }
260
+ function nextValue(args, index, flagName) {
261
+ const value = args[index];
262
+ if (!value || value.startsWith("-")) {
263
+ throw new Error(`Missing value for ${flagName}`);
264
+ }
265
+ return value;
266
+ }
267
+
268
+ // src/index.ts
269
+ export * from "tree-sitter-ts-highlight";
270
+ export {
271
+ createHelpText,
272
+ parseCliArgs,
273
+ runCli
274
+ };
275
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/run-cli.ts","../src/index.ts"],"sourcesContent":["import { extname } from \"node:path\";\r\nimport {\r\n getTheme,\r\n highlight,\r\n highlightAnsi,\r\n highlightBlock,\r\n highlightDiff,\r\n} from \"tree-sitter-ts-highlight\";\r\n\r\nexport type CliMode = \"html\" | \"ansi\" | \"diff\";\r\n\r\nexport interface CliOptions {\r\n mode: CliMode;\r\n inputPath?: string;\r\n outputPath?: string;\r\n language: string;\r\n lineNumbers: boolean;\r\n startLine?: number;\r\n semanticHighlighting: boolean;\r\n wrapInPre: boolean;\r\n diffView: \"side-by-side\" | \"inline\";\r\n oldPath?: string;\r\n newPath?: string;\r\n oldLabel?: string;\r\n newLabel?: string;\r\n showHeader: boolean;\r\n themeName?: string;\r\n help: boolean;\r\n version: boolean;\r\n}\r\n\r\ninterface IoLike {\r\n stdin: NodeJS.ReadStream;\r\n stdout: NodeJS.WriteStream;\r\n stderr: NodeJS.WriteStream;\r\n exit: (code: number) => never | void;\r\n}\r\n\r\nconst VERSION = \"0.1.2\";\r\n\r\nexport function createHelpText(): string {\r\n return [\r\n \"tree-sitter-ts-highlight-cli\",\r\n \"\",\r\n \"Usage:\",\r\n \" hlts [options]\",\r\n \"\",\r\n \"Modes:\",\r\n \" --ansi Output ANSI-highlighted text for terminals\",\r\n \" --diff Output HTML highlighted diff (requires --old and --new)\",\r\n \"\",\r\n \"Input:\",\r\n \" -i, --input <file> Input file path (default: stdin)\",\r\n \" -o, --output <file> Output file path (default: stdout)\",\r\n \" -l, --language <lang> Language or extension (default: detect from file, else typescript)\",\r\n \"\",\r\n \"HTML options:\",\r\n \" --block Wrap output in <pre><code>\",\r\n \" --line-numbers Include line numbers\",\r\n \" --start-line <n> Starting line number\",\r\n \" --semantic Enable semantic token enhancement\",\r\n \" --theme <name> Built-in HTML theme name\",\r\n \"\",\r\n \"Diff options:\",\r\n \" --old <file> Old/original file for diff mode\",\r\n \" --new <file> New/updated file for diff mode\",\r\n \" --view <mode> side-by-side | inline (default: side-by-side)\",\r\n \" --old-label <label> Header label for old side\",\r\n \" --new-label <label> Header label for new side\",\r\n \" --no-header Hide diff headers\",\r\n \"\",\r\n \"General:\",\r\n \" -h, --help Show help\",\r\n \" -v, --version Show version\",\r\n ].join(\"\\n\");\r\n}\r\n\r\nexport function parseCliArgs(args: string[]): CliOptions {\r\n const options: CliOptions = {\r\n mode: \"html\",\r\n language: \"typescript\",\r\n lineNumbers: false,\r\n semanticHighlighting: false,\r\n wrapInPre: false,\r\n diffView: \"side-by-side\",\r\n showHeader: true,\r\n help: false,\r\n version: false,\r\n };\r\n\r\n for (let index = 0; index < args.length; index += 1) {\r\n const arg = args[index];\r\n\r\n if (arg === \"-h\" || arg === \"--help\") {\r\n options.help = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"-v\" || arg === \"--version\") {\r\n options.version = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--ansi\") {\r\n options.mode = \"ansi\";\r\n continue;\r\n }\r\n\r\n if (arg === \"--diff\") {\r\n options.mode = \"diff\";\r\n continue;\r\n }\r\n\r\n if (arg === \"--line-numbers\") {\r\n options.lineNumbers = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--semantic\") {\r\n options.semanticHighlighting = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--block\") {\r\n options.wrapInPre = true;\r\n continue;\r\n }\r\n\r\n if (arg === \"--no-header\") {\r\n options.showHeader = false;\r\n continue;\r\n }\r\n\r\n if (arg === \"-i\" || arg === \"--input\") {\r\n options.inputPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"-o\" || arg === \"--output\") {\r\n options.outputPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"-l\" || arg === \"--language\") {\r\n options.language = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--start-line\") {\r\n const value = nextValue(args, ++index, arg);\r\n const startLine = Number.parseInt(value, 10);\r\n if (!Number.isFinite(startLine) || startLine <= 0) {\r\n throw new Error(`Invalid --start-line value: ${value}`);\r\n }\r\n options.startLine = startLine;\r\n continue;\r\n }\r\n\r\n if (arg === \"--theme\") {\r\n options.themeName = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--old\") {\r\n options.oldPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--new\") {\r\n options.newPath = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--view\") {\r\n const view = nextValue(args, ++index, arg);\r\n if (view !== \"side-by-side\" && view !== \"inline\") {\r\n throw new Error(`Invalid --view value: ${view}`);\r\n }\r\n options.diffView = view;\r\n continue;\r\n }\r\n\r\n if (arg === \"--old-label\") {\r\n options.oldLabel = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n if (arg === \"--new-label\") {\r\n options.newLabel = nextValue(args, ++index, arg);\r\n continue;\r\n }\r\n\r\n throw new Error(`Unknown argument: ${arg}`);\r\n }\r\n\r\n return options;\r\n}\r\n\r\nexport async function runCli(args: string[], io: IoLike): Promise<void> {\r\n try {\r\n const options = parseCliArgs(args);\r\n\r\n if (options.help) {\r\n io.stdout.write(`${createHelpText()}\\n`);\r\n return;\r\n }\r\n\r\n if (options.version) {\r\n io.stdout.write(`${VERSION}\\n`);\r\n return;\r\n }\r\n\r\n const renderResult = await render(options, io.stdin);\r\n\r\n if (options.outputPath) {\r\n const { writeFile } = await import(\"node:fs/promises\");\r\n await writeFile(options.outputPath, renderResult, \"utf8\");\r\n } else {\r\n io.stdout.write(renderResult);\r\n if (!renderResult.endsWith(\"\\n\")) {\r\n io.stdout.write(\"\\n\");\r\n }\r\n }\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n io.stderr.write(`Error: ${message}\\n`);\r\n io.stderr.write(\"Use --help to see usage.\\n\");\r\n io.exit(1);\r\n }\r\n}\r\n\r\nasync function render(options: CliOptions, stdin: NodeJS.ReadStream): Promise<string> {\r\n if (options.mode === \"diff\") {\r\n if (!options.oldPath || !options.newPath) {\r\n throw new Error(\"--diff requires both --old and --new\");\r\n }\r\n\r\n const { readFile } = await import(\"node:fs/promises\");\r\n const [oldSource, newSource] = await Promise.all([\r\n readFile(options.oldPath, \"utf8\"),\r\n readFile(options.newPath, \"utf8\"),\r\n ]);\r\n\r\n const language = resolveLanguage(options.language, options.newPath);\r\n\r\n return highlightDiff(oldSource, newSource, language, {\r\n view: options.diffView,\r\n semanticHighlighting: options.semanticHighlighting,\r\n oldLabel: options.oldLabel,\r\n newLabel: options.newLabel,\r\n showHeader: options.showHeader,\r\n classPrefix: \"hlts-\",\r\n theme: resolveHtmlTheme(options.themeName),\r\n });\r\n }\r\n\r\n const source = options.inputPath\r\n ? await readTextFile(options.inputPath)\r\n : await readStdin(stdin);\r\n\r\n const language = resolveLanguage(options.language, options.inputPath);\r\n\r\n if (options.mode === \"ansi\") {\r\n return highlightAnsi(source, language, {\r\n semanticHighlighting: options.semanticHighlighting,\r\n lineNumbers: options.lineNumbers,\r\n startLine: options.startLine,\r\n });\r\n }\r\n\r\n const htmlOptions = {\r\n semanticHighlighting: options.semanticHighlighting,\r\n lineNumbers: options.lineNumbers,\r\n startLine: options.startLine,\r\n theme: resolveHtmlTheme(options.themeName),\r\n };\r\n\r\n if (options.wrapInPre) {\r\n return highlightBlock(source, language, {\r\n ...htmlOptions,\r\n language,\r\n });\r\n }\r\n\r\n return highlight(source, language, htmlOptions);\r\n}\r\n\r\nasync function readTextFile(filePath: string): Promise<string> {\r\n const { readFile } = await import(\"node:fs/promises\");\r\n return readFile(filePath, \"utf8\");\r\n}\r\n\r\nfunction readStdin(stdin: NodeJS.ReadStream): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const chunks: Buffer[] = [];\r\n stdin.on(\"data\", (chunk: Buffer | string) => {\r\n if (typeof chunk === \"string\") {\r\n chunks.push(Buffer.from(chunk));\r\n return;\r\n }\r\n chunks.push(chunk);\r\n });\r\n stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")));\r\n stdin.on(\"error\", reject);\r\n stdin.resume();\r\n });\r\n}\r\n\r\nfunction resolveLanguage(explicitLanguage: string, filePath?: string): string {\r\n if (explicitLanguage && explicitLanguage !== \"typescript\") {\r\n return explicitLanguage;\r\n }\r\n\r\n if (!filePath) {\r\n return explicitLanguage || \"typescript\";\r\n }\r\n\r\n const extension = extname(filePath);\r\n return extension || explicitLanguage || \"typescript\";\r\n}\r\n\r\nfunction resolveHtmlTheme(themeName?: string) {\r\n if (!themeName) {\r\n return undefined;\r\n }\r\n\r\n const theme = getTheme(themeName);\r\n if (!theme) {\r\n throw new Error(`Unknown theme: ${themeName}`);\r\n }\r\n return theme;\r\n}\r\n\r\nfunction nextValue(args: string[], index: number, flagName: string): string {\r\n const value = args[index];\r\n if (!value || value.startsWith(\"-\")) {\r\n throw new Error(`Missing value for ${flagName}`);\r\n }\r\n return value;\r\n}\r\n","export {\r\n runCli,\r\n parseCliArgs,\r\n createHelpText,\r\n type CliOptions,\r\n type CliMode,\r\n} from \"./run-cli\";\r\n\r\nexport * from \"tree-sitter-ts-highlight\";\r\nexport type * from \"tree-sitter-ts-highlight\";\r\nexport type * from \"tree-sitter-ts\";\r\n"],"mappings":"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","names":["language"]}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "tree-sitter-ts-highlight-cli",
3
+ "version": "0.1.2",
4
+ "description": "Command-line wrapper for tree-sitter-ts-highlight.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "bin": {
10
+ "hlts": "./dist/cli.js",
11
+ "tree-sitter-ts-highlight": "./dist/cli.js"
12
+ },
13
+ "exports": {
14
+ ".": {
15
+ "import": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.js"
18
+ },
19
+ "require": {
20
+ "types": "./dist/index.d.cts",
21
+ "default": "./dist/index.cjs"
22
+ }
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md"
28
+ ],
29
+ "scripts": {
30
+ "build": "tsup",
31
+ "typecheck": "tsc --noEmit",
32
+ "test": "jest",
33
+ "test:watch": "jest --watch"
34
+ },
35
+ "dependencies": {
36
+ "tree-sitter-ts": "^0.1.2",
37
+ "tree-sitter-ts-highlight": "^0.1.2"
38
+ },
39
+ "devDependencies": {
40
+ "@swc/core": "^1.15.11",
41
+ "@swc/jest": "^0.2.39",
42
+ "@types/jest": "^30.0.0",
43
+ "@types/node": "^25.3.0",
44
+ "jest": "^30.2.0",
45
+ "tsup": "^8.0.0",
46
+ "tsx": "^4.20.5",
47
+ "typescript": "^5.4.0"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public",
51
+ "provenance": false
52
+ },
53
+ "keywords": [
54
+ "cli",
55
+ "tree-sitter",
56
+ "syntax-highlighting",
57
+ "typescript",
58
+ "ansi",
59
+ "html"
60
+ ],
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "https://github.com/hieutran512/tree-sitter-ts-highlight-cli"
64
+ },
65
+ "license": "MIT",
66
+ "engines": {
67
+ "node": ">=18.0.0"
68
+ }
69
+ }