tree-sitter-ts-highlight-react 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,85 @@
1
+ # tree-sitter-ts-highlight-react
2
+
3
+ React components and hooks for [`tree-sitter-ts-highlight`](https://www.npmjs.com/package/tree-sitter-ts-highlight), with React-element rendering (no `dangerouslySetInnerHTML` required).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install tree-sitter-ts-highlight-react tree-sitter-ts-highlight tree-sitter-ts
9
+ ```
10
+
11
+ ## Peer dependencies
12
+
13
+ This package expects these to be installed in your app:
14
+
15
+ - `react` (`^18` or `^19`)
16
+ - `tree-sitter-ts`
17
+ - `tree-sitter-ts-highlight`
18
+
19
+ ## Theme CSS
20
+
21
+ Import a theme from `tree-sitter-ts-highlight` once in your app entry:
22
+
23
+ ```ts
24
+ import "tree-sitter-ts-highlight/themes/github-dark.css";
25
+ ```
26
+
27
+ ## Basic usage
28
+
29
+ ```tsx
30
+ import { Highlight, HighlightDiff } from "tree-sitter-ts-highlight-react";
31
+
32
+ export function Example() {
33
+ return (
34
+ <>
35
+ <Highlight
36
+ code={`const n: number = 42;`}
37
+ language="typescript"
38
+ options={{ lineNumbers: true }}
39
+ />
40
+
41
+ <HighlightDiff
42
+ oldCode={`const n = 1;`}
43
+ newCode={`const n = 2;`}
44
+ language="typescript"
45
+ options={{ view: "side-by-side" }}
46
+ />
47
+ </>
48
+ );
49
+ }
50
+ ```
51
+
52
+ ## API
53
+
54
+ ### Components
55
+
56
+ - `Highlight`
57
+ - Props: `code`, `language`, `options?`, `preProps?`, `codeProps?`
58
+ - Renders highlighted output as `<pre><code>` React nodes
59
+ - `HighlightDiff`
60
+ - Props: `oldCode`, `newCode`, `language`, `options?`, `containerProps?`
61
+ - Renders highlighted diffs (inline or side-by-side)
62
+
63
+ ### Hooks
64
+
65
+ - `useHighlightedHtml({ code, language, options? })`
66
+ - Returns highlighted HTML without wrapping `<pre>`
67
+ - `useHighlightedDiffHtml({ oldCode, newCode, language, options? })`
68
+ - Returns highlighted diff HTML
69
+
70
+ ### Re-exports
71
+
72
+ - Runtime exports from `tree-sitter-ts-highlight` are re-exported by this package.
73
+ - Type exports from both `tree-sitter-ts-highlight` and `tree-sitter-ts` are re-exported.
74
+
75
+ ```ts
76
+ import type { HighlightOptions } from "tree-sitter-ts-highlight-react";
77
+ import type * as TsTypes from "tree-sitter-ts-highlight-react";
78
+ ```
79
+
80
+ ## Development
81
+
82
+ ```bash
83
+ npm run build
84
+ npm test
85
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,342 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ Highlight: () => Highlight,
25
+ HighlightDiff: () => HighlightDiff,
26
+ useHighlightedDiffHtml: () => useHighlightedDiffHtml,
27
+ useHighlightedHtml: () => useHighlightedHtml
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/components/Highlight.tsx
32
+ var import_tree_sitter_ts_highlight2 = require("tree-sitter-ts-highlight");
33
+ var import_tree_sitter_ts = require("tree-sitter-ts");
34
+ var import_react = require("react");
35
+
36
+ // src/react-renderer.tsx
37
+ var import_tree_sitter_ts_highlight = require("tree-sitter-ts-highlight");
38
+ var import_jsx_runtime = require("react/jsx-runtime");
39
+ function renderTokenNodes(tokens, options = {}) {
40
+ const prefix = options.classPrefix ?? "hlts-";
41
+ const decorated = options.decorations && options.decorations.length > 0 ? (0, import_tree_sitter_ts_highlight.applyDecorations)(tokens, options.decorations) : tokens.map((token) => ({
42
+ token,
43
+ extraClasses: [],
44
+ extraAttrs: {},
45
+ extraStyle: void 0
46
+ }));
47
+ return decorated.map(({ token, extraClasses, extraAttrs, extraStyle }, index) => {
48
+ if (token.category === "whitespace" || token.category === "newline") {
49
+ return token.value;
50
+ }
51
+ const key = `${options.keyPrefix ?? "tok"}-${index}`;
52
+ const dataAttrs = Object.fromEntries(
53
+ Object.entries(extraAttrs).map(([k, v]) => [`data-${k}`, v])
54
+ );
55
+ if (options.theme) {
56
+ const baseStyle = options.theme.styles[token.category] ?? "";
57
+ const style = cssTextToReactStyle([baseStyle, extraStyle].filter(Boolean).join(";"));
58
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style, ...dataAttrs, children: token.value }, key);
59
+ }
60
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
61
+ "span",
62
+ {
63
+ className: [prefix + token.category, ...extraClasses].join(" "),
64
+ ...dataAttrs,
65
+ children: token.value
66
+ },
67
+ key
68
+ );
69
+ });
70
+ }
71
+ function renderLineTable(tokens, options = {}) {
72
+ const groups = (0, import_tree_sitter_ts_highlight.groupTokensByLine)(tokens);
73
+ const startLine = options.startLine ?? 1;
74
+ const withDataLine = options.dataLineAttributes ?? true;
75
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { className: "hlts-table", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: groups.map((group, index) => {
76
+ const displayLine = group.lineNumber - groups[0].lineNumber + startLine;
77
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
78
+ "tr",
79
+ {
80
+ ...withDataLine ? { "data-line": displayLine } : {},
81
+ children: [
82
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "hlts-line-number", children: displayLine }),
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "hlts-line-content", children: renderTokenNodes(group.tokens, {
84
+ classPrefix: options.classPrefix,
85
+ theme: options.theme,
86
+ decorations: options.decorations,
87
+ keyPrefix: `line-${group.lineNumber}`
88
+ }) })
89
+ ]
90
+ },
91
+ `line-${group.lineNumber}-${index}`
92
+ );
93
+ }) }) });
94
+ }
95
+ function renderDiffTable(options) {
96
+ const prefix = options.classPrefix ?? "hlts-";
97
+ const view = options.view ?? "side-by-side";
98
+ if (view === "inline") {
99
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { className: `${prefix}diff ${prefix}diff-inline`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: options.rows.flatMap((row, index) => {
100
+ if (row.changeType === "context") {
101
+ return [
102
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: `${prefix}diff-row ${prefix}diff-context`, children: [
103
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-gutter`, children: row.newLineNumber ?? "" }),
104
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-sign`, children: " " }),
105
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
106
+ lineNumber: row.newLineNumber,
107
+ tokenMap: options.newLineTokens,
108
+ fallbackText: row.newText,
109
+ classPrefix: options.classPrefix,
110
+ theme: options.theme,
111
+ decorations: options.decorations,
112
+ keyPrefix: `inline-context-${index}`
113
+ }) })
114
+ ] }, `ctx-${index}`)
115
+ ];
116
+ }
117
+ const nodes = [];
118
+ if (row.oldLineNumber !== null) {
119
+ nodes.push(
120
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: `${prefix}diff-row ${prefix}diff-removed`, children: [
121
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-gutter`, children: row.oldLineNumber }),
122
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-sign`, children: "-" }),
123
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
124
+ lineNumber: row.oldLineNumber,
125
+ tokenMap: options.oldLineTokens,
126
+ fallbackText: row.oldText,
127
+ classPrefix: options.classPrefix,
128
+ theme: options.theme,
129
+ decorations: options.decorations,
130
+ keyPrefix: `inline-old-${index}`
131
+ }) })
132
+ ] }, `old-${index}`)
133
+ );
134
+ }
135
+ if (row.newLineNumber !== null) {
136
+ nodes.push(
137
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: `${prefix}diff-row ${prefix}diff-added`, children: [
138
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-gutter`, children: row.newLineNumber }),
139
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-sign`, children: "+" }),
140
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
141
+ lineNumber: row.newLineNumber,
142
+ tokenMap: options.newLineTokens,
143
+ fallbackText: row.newText,
144
+ classPrefix: options.classPrefix,
145
+ theme: options.theme,
146
+ decorations: options.decorations,
147
+ keyPrefix: `inline-new-${index}`
148
+ }) })
149
+ ] }, `new-${index}`)
150
+ );
151
+ }
152
+ return nodes;
153
+ }) }) });
154
+ }
155
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { className: `${prefix}diff ${prefix}diff-side-by-side`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tbody", { children: [
156
+ (options.showHeader ?? true) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: `${prefix}diff-header`, children: [
157
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: `${prefix}diff-label`, colSpan: 2, children: options.oldLabel }),
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: `${prefix}diff-label`, colSpan: 2, children: options.newLabel })
159
+ ] }),
160
+ options.rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
161
+ "tr",
162
+ {
163
+ className: `${prefix}diff-row ${prefix}diff-${row.changeType}`,
164
+ children: [
165
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-gutter`, children: row.oldLineNumber ?? "" }),
166
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
167
+ lineNumber: row.oldLineNumber,
168
+ tokenMap: options.oldLineTokens,
169
+ fallbackText: row.oldText,
170
+ classPrefix: options.classPrefix,
171
+ theme: options.theme,
172
+ decorations: options.decorations,
173
+ keyPrefix: `side-old-${index}`
174
+ }) }),
175
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-gutter`, children: row.newLineNumber ?? "" }),
176
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
177
+ lineNumber: row.newLineNumber,
178
+ tokenMap: options.newLineTokens,
179
+ fallbackText: row.newText,
180
+ classPrefix: options.classPrefix,
181
+ theme: options.theme,
182
+ decorations: options.decorations,
183
+ keyPrefix: `side-new-${index}`
184
+ }) })
185
+ ]
186
+ },
187
+ `row-${index}`
188
+ ))
189
+ ] }) });
190
+ }
191
+ function renderDiffLineContent(params) {
192
+ if (params.lineNumber === null) {
193
+ return "";
194
+ }
195
+ const tokens = params.tokenMap.get(params.lineNumber);
196
+ if (!tokens || tokens.length === 0) {
197
+ return params.fallbackText;
198
+ }
199
+ return renderTokenNodes(tokens, {
200
+ classPrefix: params.classPrefix,
201
+ theme: params.theme,
202
+ decorations: params.decorations,
203
+ keyPrefix: params.keyPrefix
204
+ });
205
+ }
206
+ function cssTextToReactStyle(cssText) {
207
+ const style = {};
208
+ for (const declaration of cssText.split(";")) {
209
+ const trimmed = declaration.trim();
210
+ if (!trimmed) {
211
+ continue;
212
+ }
213
+ const separatorIndex = trimmed.indexOf(":");
214
+ if (separatorIndex === -1) {
215
+ continue;
216
+ }
217
+ const property = trimmed.slice(0, separatorIndex).trim();
218
+ const value = trimmed.slice(separatorIndex + 1).trim();
219
+ if (!property || !value) {
220
+ continue;
221
+ }
222
+ style[kebabToCamel(property)] = value;
223
+ }
224
+ return style;
225
+ }
226
+ function kebabToCamel(property) {
227
+ return property.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
228
+ }
229
+
230
+ // src/components/Highlight.tsx
231
+ var import_jsx_runtime2 = require("react/jsx-runtime");
232
+ function Highlight({
233
+ code,
234
+ language,
235
+ options,
236
+ preProps,
237
+ codeProps
238
+ }) {
239
+ const tokens = (0, import_react.useMemo)(() => {
240
+ const rawTokens = (0, import_tree_sitter_ts.tokenize)(code, language);
241
+ return options?.semanticHighlighting ? (0, import_tree_sitter_ts_highlight2.enhanceSemantics)(rawTokens) : rawTokens;
242
+ }, [code, language, options?.semanticHighlighting]);
243
+ const { children: _ignoredChildren, ...safeCodeProps } = codeProps ?? {};
244
+ const mergedPreStyle = {
245
+ ...options?.theme?.background ? { background: options.theme.background } : {},
246
+ ...options?.theme?.foreground ? { color: options.theme.foreground } : {},
247
+ ...preProps?.style
248
+ };
249
+ const classPrefix = options?.classPrefix;
250
+ const content = options?.lineNumbers ? renderLineTable(tokens, {
251
+ classPrefix,
252
+ theme: options.theme,
253
+ decorations: options.decorations,
254
+ startLine: options.startLine,
255
+ dataLineAttributes: options.dataLineAttributes
256
+ }) : renderTokenNodes(tokens, {
257
+ classPrefix,
258
+ theme: options?.theme,
259
+ decorations: options?.decorations
260
+ });
261
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
262
+ "pre",
263
+ {
264
+ ...preProps,
265
+ className: ["hlts", `hlts-lang-${language}`, preProps?.className].filter(Boolean).join(" "),
266
+ style: mergedPreStyle,
267
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("code", { ...safeCodeProps, children: content })
268
+ }
269
+ );
270
+ }
271
+
272
+ // src/components/HighlightDiff.tsx
273
+ var import_tree_sitter_ts_highlight3 = require("tree-sitter-ts-highlight");
274
+ var import_react2 = require("react");
275
+ var import_jsx_runtime3 = require("react/jsx-runtime");
276
+ function HighlightDiff({
277
+ oldCode,
278
+ newCode,
279
+ language,
280
+ options,
281
+ containerProps
282
+ }) {
283
+ const diff = (0, import_react2.useMemo)(
284
+ () => (0, import_tree_sitter_ts_highlight3.createDiffModelWithTokens)(oldCode, newCode, language, options),
285
+ [oldCode, newCode, language, options]
286
+ );
287
+ const { children: _ignoredChildren, ...safeContainerProps } = containerProps ?? {};
288
+ const table = renderDiffTable({
289
+ view: options?.view,
290
+ showHeader: options?.showHeader,
291
+ classPrefix: options?.classPrefix,
292
+ decorations: options?.decorations,
293
+ theme: options?.theme,
294
+ oldLabel: diff.model.oldLabel,
295
+ newLabel: diff.model.newLabel,
296
+ rows: diff.model.rows,
297
+ oldLineTokens: diff.oldLineTokens,
298
+ newLineTokens: diff.newLineTokens
299
+ });
300
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ...safeContainerProps, children: table });
301
+ }
302
+
303
+ // src/hooks/useHighlightedHtml.ts
304
+ var import_tree_sitter_ts_highlight4 = require("tree-sitter-ts-highlight");
305
+ var import_react3 = require("react");
306
+ function useHighlightedHtml({
307
+ code,
308
+ language,
309
+ options
310
+ }) {
311
+ return (0, import_react3.useMemo)(
312
+ () => (0, import_tree_sitter_ts_highlight4.highlight)(code, language, {
313
+ ...options,
314
+ wrapInPre: false,
315
+ language
316
+ }),
317
+ [code, language, options]
318
+ );
319
+ }
320
+ function useHighlightedDiffHtml({
321
+ oldCode,
322
+ newCode,
323
+ language,
324
+ options
325
+ }) {
326
+ return (0, import_react3.useMemo)(
327
+ () => (0, import_tree_sitter_ts_highlight4.highlightDiff)(oldCode, newCode, language, options),
328
+ [oldCode, newCode, language, options]
329
+ );
330
+ }
331
+
332
+ // src/index.ts
333
+ __reExport(index_exports, require("tree-sitter-ts-highlight"), module.exports);
334
+ // Annotate the CommonJS export names for ESM import in node:
335
+ 0 && (module.exports = {
336
+ Highlight,
337
+ HighlightDiff,
338
+ useHighlightedDiffHtml,
339
+ useHighlightedHtml,
340
+ ...require("tree-sitter-ts-highlight")
341
+ });
342
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/components/Highlight.tsx","../src/react-renderer.tsx","../src/components/HighlightDiff.tsx","../src/hooks/useHighlightedHtml.ts"],"sourcesContent":["export { Highlight } from \"./components/Highlight\";\r\nexport type { HighlightProps } from \"./components/Highlight\";\r\n\r\nexport { HighlightDiff } from \"./components/HighlightDiff\";\r\nexport type { HighlightDiffProps } from \"./components/HighlightDiff\";\r\n\r\nexport {\r\n useHighlightedHtml,\r\n useHighlightedDiffHtml,\r\n} from \"./hooks/useHighlightedHtml\";\r\nexport type {\r\n UseHighlightedHtmlParams,\r\n UseHighlightedDiffHtmlParams,\r\n} from \"./hooks/useHighlightedHtml\";\r\n\r\nexport type * from \"tree-sitter-ts\";\r\nexport type * from \"tree-sitter-ts-highlight\";\r\nexport * from \"tree-sitter-ts-highlight\";\r\n","import { enhanceSemantics } from \"tree-sitter-ts-highlight\";\r\nimport type { HighlightOptions } from \"tree-sitter-ts-highlight\";\r\nimport { tokenize } from \"tree-sitter-ts\";\r\nimport { useMemo } from \"react\";\r\nimport type { HTMLAttributes, ReactElement } from \"react\";\r\nimport { renderLineTable, renderTokenNodes } from \"../react-renderer\";\r\n\r\nexport interface HighlightProps {\r\n code: string;\r\n language: string;\r\n options?: Omit<HighlightOptions, \"wrapInPre\" | \"language\">;\r\n preProps?: HTMLAttributes<HTMLPreElement>;\r\n codeProps?: HTMLAttributes<HTMLElement>;\r\n}\r\n\r\nexport function Highlight({\r\n code,\r\n language,\r\n options,\r\n preProps,\r\n codeProps,\r\n}: HighlightProps): ReactElement {\r\n const tokens = useMemo(() => {\r\n const rawTokens = tokenize(code, language);\r\n return options?.semanticHighlighting ? enhanceSemantics(rawTokens) : rawTokens;\r\n }, [code, language, options?.semanticHighlighting]);\r\n\r\n const { children: _ignoredChildren, ...safeCodeProps } = codeProps ?? {};\r\n\r\n const mergedPreStyle = {\r\n ...(options?.theme?.background ? { background: options.theme.background } : {}),\r\n ...(options?.theme?.foreground ? { color: options.theme.foreground } : {}),\r\n ...preProps?.style,\r\n };\r\n\r\n const classPrefix = options?.classPrefix;\r\n const content = options?.lineNumbers\r\n ? renderLineTable(tokens, {\r\n classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n startLine: options.startLine,\r\n dataLineAttributes: options.dataLineAttributes,\r\n })\r\n : renderTokenNodes(tokens, {\r\n classPrefix,\r\n theme: options?.theme,\r\n decorations: options?.decorations,\r\n });\r\n\r\n return (\r\n <pre\r\n {...preProps}\r\n className={[\"hlts\", `hlts-lang-${language}`, preProps?.className].filter(Boolean).join(\" \")}\r\n style={mergedPreStyle}\r\n >\r\n <code {...safeCodeProps}>{content}</code>\r\n </pre>\r\n );\r\n}\r\n","import { applyDecorations, groupTokensByLine } from \"tree-sitter-ts-highlight\";\r\nimport type {\r\n Decoration,\r\n DiffOptions,\r\n HtmlTheme,\r\n} from \"tree-sitter-ts-highlight\";\r\nimport type { Token } from \"tree-sitter-ts\";\r\nimport type { CSSProperties, ReactNode } from \"react\";\r\n\r\ninterface RenderTokenNodesOptions {\r\n classPrefix?: string;\r\n theme?: HtmlTheme;\r\n decorations?: Decoration[];\r\n keyPrefix?: string;\r\n}\r\n\r\ninterface RenderLineTableOptions extends RenderTokenNodesOptions {\r\n startLine?: number;\r\n dataLineAttributes?: boolean;\r\n}\r\n\r\ninterface RenderDiffTableOptions extends RenderTokenNodesOptions {\r\n view?: DiffOptions[\"view\"];\r\n showHeader?: boolean;\r\n oldLabel: string;\r\n newLabel: string;\r\n rows: Array<{\r\n changeType: \"context\" | \"added\" | \"removed\" | \"modified\";\r\n oldLineNumber: number | null;\r\n newLineNumber: number | null;\r\n oldText: string;\r\n newText: string;\r\n }>;\r\n oldLineTokens: Map<number, Token[]>;\r\n newLineTokens: Map<number, Token[]>;\r\n}\r\n\r\nexport function renderTokenNodes(\r\n tokens: Token[],\r\n options: RenderTokenNodesOptions = {},\r\n): ReactNode[] {\r\n const prefix = options.classPrefix ?? \"hlts-\";\r\n const decorated =\r\n options.decorations && options.decorations.length > 0\r\n ? applyDecorations(tokens, options.decorations)\r\n : tokens.map((token) => ({\r\n token,\r\n extraClasses: [],\r\n extraAttrs: {},\r\n extraStyle: undefined,\r\n }));\r\n\r\n return decorated.map(({ token, extraClasses, extraAttrs, extraStyle }, index) => {\r\n if (token.category === \"whitespace\" || token.category === \"newline\") {\r\n return token.value;\r\n }\r\n\r\n const key = `${options.keyPrefix ?? \"tok\"}-${index}`;\r\n const dataAttrs = Object.fromEntries(\r\n Object.entries(extraAttrs).map(([k, v]) => [`data-${k}`, v]),\r\n );\r\n\r\n if (options.theme) {\r\n const baseStyle = options.theme.styles[token.category] ?? \"\";\r\n const style = cssTextToReactStyle([baseStyle, extraStyle].filter(Boolean).join(\";\"));\r\n\r\n return (\r\n <span key={key} style={style} {...dataAttrs}>\r\n {token.value}\r\n </span>\r\n );\r\n }\r\n\r\n return (\r\n <span\r\n key={key}\r\n className={[prefix + token.category, ...extraClasses].join(\" \")}\r\n {...dataAttrs}\r\n >\r\n {token.value}\r\n </span>\r\n );\r\n });\r\n}\r\n\r\nexport function renderLineTable(\r\n tokens: Token[],\r\n options: RenderLineTableOptions = {},\r\n): ReactNode {\r\n const groups = groupTokensByLine(tokens);\r\n const startLine = options.startLine ?? 1;\r\n const withDataLine = options.dataLineAttributes ?? true;\r\n\r\n return (\r\n <table className=\"hlts-table\">\r\n <tbody>\r\n {groups.map((group, index) => {\r\n const displayLine = group.lineNumber - groups[0].lineNumber + startLine;\r\n return (\r\n <tr\r\n key={`line-${group.lineNumber}-${index}`}\r\n {...(withDataLine ? { \"data-line\": displayLine } : {})}\r\n >\r\n <td className=\"hlts-line-number\">{displayLine}</td>\r\n <td className=\"hlts-line-content\">\r\n {renderTokenNodes(group.tokens, {\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `line-${group.lineNumber}`,\r\n })}\r\n </td>\r\n </tr>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n );\r\n}\r\n\r\nexport function renderDiffTable(options: RenderDiffTableOptions): ReactNode {\r\n const prefix = options.classPrefix ?? \"hlts-\";\r\n const view = options.view ?? \"side-by-side\";\r\n\r\n if (view === \"inline\") {\r\n return (\r\n <table className={`${prefix}diff ${prefix}diff-inline`}>\r\n <tbody>\r\n {options.rows.flatMap((row, index) => {\r\n if (row.changeType === \"context\") {\r\n return [\r\n <tr key={`ctx-${index}`} className={`${prefix}diff-row ${prefix}diff-context`}>\r\n <td className={`${prefix}diff-gutter`}>{row.newLineNumber ?? \"\"}</td>\r\n <td className={`${prefix}diff-sign`}> </td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.newLineNumber,\r\n tokenMap: options.newLineTokens,\r\n fallbackText: row.newText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `inline-context-${index}`,\r\n })}\r\n </td>\r\n </tr>,\r\n ];\r\n }\r\n\r\n const nodes: ReactNode[] = [];\r\n\r\n if (row.oldLineNumber !== null) {\r\n nodes.push(\r\n <tr key={`old-${index}`} className={`${prefix}diff-row ${prefix}diff-removed`}>\r\n <td className={`${prefix}diff-gutter`}>{row.oldLineNumber}</td>\r\n <td className={`${prefix}diff-sign`}>-</td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.oldLineNumber,\r\n tokenMap: options.oldLineTokens,\r\n fallbackText: row.oldText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `inline-old-${index}`,\r\n })}\r\n </td>\r\n </tr>,\r\n );\r\n }\r\n\r\n if (row.newLineNumber !== null) {\r\n nodes.push(\r\n <tr key={`new-${index}`} className={`${prefix}diff-row ${prefix}diff-added`}>\r\n <td className={`${prefix}diff-gutter`}>{row.newLineNumber}</td>\r\n <td className={`${prefix}diff-sign`}>+</td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.newLineNumber,\r\n tokenMap: options.newLineTokens,\r\n fallbackText: row.newText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `inline-new-${index}`,\r\n })}\r\n </td>\r\n </tr>,\r\n );\r\n }\r\n\r\n return nodes;\r\n })}\r\n </tbody>\r\n </table>\r\n );\r\n }\r\n\r\n return (\r\n <table className={`${prefix}diff ${prefix}diff-side-by-side`}>\r\n <tbody>\r\n {(options.showHeader ?? true) && (\r\n <tr className={`${prefix}diff-header`}>\r\n <th className={`${prefix}diff-label`} colSpan={2}>\r\n {options.oldLabel}\r\n </th>\r\n <th className={`${prefix}diff-label`} colSpan={2}>\r\n {options.newLabel}\r\n </th>\r\n </tr>\r\n )}\r\n\r\n {options.rows.map((row, index) => (\r\n <tr\r\n key={`row-${index}`}\r\n className={`${prefix}diff-row ${prefix}diff-${row.changeType}`}\r\n >\r\n <td className={`${prefix}diff-gutter`}>{row.oldLineNumber ?? \"\"}</td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.oldLineNumber,\r\n tokenMap: options.oldLineTokens,\r\n fallbackText: row.oldText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `side-old-${index}`,\r\n })}\r\n </td>\r\n <td className={`${prefix}diff-gutter`}>{row.newLineNumber ?? \"\"}</td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.newLineNumber,\r\n tokenMap: options.newLineTokens,\r\n fallbackText: row.newText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `side-new-${index}`,\r\n })}\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n );\r\n}\r\n\r\nfunction renderDiffLineContent(params: {\r\n lineNumber: number | null;\r\n tokenMap: Map<number, Token[]>;\r\n fallbackText: string;\r\n classPrefix?: string;\r\n theme?: HtmlTheme;\r\n decorations?: Decoration[];\r\n keyPrefix: string;\r\n}): ReactNode {\r\n if (params.lineNumber === null) {\r\n return \"\";\r\n }\r\n\r\n const tokens = params.tokenMap.get(params.lineNumber);\r\n if (!tokens || tokens.length === 0) {\r\n return params.fallbackText;\r\n }\r\n\r\n return renderTokenNodes(tokens, {\r\n classPrefix: params.classPrefix,\r\n theme: params.theme,\r\n decorations: params.decorations,\r\n keyPrefix: params.keyPrefix,\r\n });\r\n}\r\n\r\nfunction cssTextToReactStyle(cssText: string): CSSProperties {\r\n const style: Record<string, string> = {};\r\n\r\n for (const declaration of cssText.split(\";\")) {\r\n const trimmed = declaration.trim();\r\n if (!trimmed) {\r\n continue;\r\n }\r\n\r\n const separatorIndex = trimmed.indexOf(\":\");\r\n if (separatorIndex === -1) {\r\n continue;\r\n }\r\n\r\n const property = trimmed.slice(0, separatorIndex).trim();\r\n const value = trimmed.slice(separatorIndex + 1).trim();\r\n if (!property || !value) {\r\n continue;\r\n }\r\n\r\n style[kebabToCamel(property)] = value;\r\n }\r\n\r\n return style as CSSProperties;\r\n}\r\n\r\nfunction kebabToCamel(property: string): string {\r\n return property.replace(/-([a-z])/g, (_, char: string) => char.toUpperCase());\r\n}\r\n","import { createDiffModelWithTokens } from \"tree-sitter-ts-highlight\";\r\nimport type { DiffOptions } from \"tree-sitter-ts-highlight\";\r\nimport { useMemo } from \"react\";\r\nimport type { HTMLAttributes, ReactElement } from \"react\";\r\nimport { renderDiffTable } from \"../react-renderer\";\r\n\r\ntype DataAttributes = {\r\n [key: `data-${string}`]: string | number | boolean | undefined;\r\n};\r\n\r\nexport interface HighlightDiffProps {\r\n oldCode: string;\r\n newCode: string;\r\n language: string;\r\n options?: DiffOptions;\r\n containerProps?: HTMLAttributes<HTMLDivElement> & DataAttributes;\r\n}\r\n\r\nexport function HighlightDiff({\r\n oldCode,\r\n newCode,\r\n language,\r\n options,\r\n containerProps,\r\n}: HighlightDiffProps): ReactElement {\r\n const diff = useMemo(\r\n () => createDiffModelWithTokens(oldCode, newCode, language, options),\r\n [oldCode, newCode, language, options],\r\n );\r\n\r\n const { children: _ignoredChildren, ...safeContainerProps } = containerProps ?? {};\r\n\r\n const table = renderDiffTable({\r\n view: options?.view,\r\n showHeader: options?.showHeader,\r\n classPrefix: options?.classPrefix,\r\n decorations: options?.decorations,\r\n theme: options?.theme,\r\n oldLabel: diff.model.oldLabel,\r\n newLabel: diff.model.newLabel,\r\n rows: diff.model.rows,\r\n oldLineTokens: diff.oldLineTokens,\r\n newLineTokens: diff.newLineTokens,\r\n });\r\n\r\n return <div {...safeContainerProps}>{table}</div>;\r\n}\r\n","import { highlight, highlightDiff } from \"tree-sitter-ts-highlight\";\r\nimport type { DiffOptions, HighlightOptions } from \"tree-sitter-ts-highlight\";\r\nimport { useMemo } from \"react\";\r\n\r\nexport interface UseHighlightedHtmlParams {\r\n code: string;\r\n language: string;\r\n options?: Omit<HighlightOptions, \"wrapInPre\" | \"language\">;\r\n}\r\n\r\nexport function useHighlightedHtml({\r\n code,\r\n language,\r\n options,\r\n}: UseHighlightedHtmlParams): string {\r\n return useMemo(\r\n () =>\r\n highlight(code, language, {\r\n ...options,\r\n wrapInPre: false,\r\n language,\r\n }),\r\n [code, language, options],\r\n );\r\n}\r\n\r\nexport interface UseHighlightedDiffHtmlParams {\r\n oldCode: string;\r\n newCode: string;\r\n language: string;\r\n options?: DiffOptions;\r\n}\r\n\r\nexport function useHighlightedDiffHtml({\r\n oldCode,\r\n newCode,\r\n language,\r\n options,\r\n}: UseHighlightedDiffHtmlParams): string {\r\n return useMemo(\r\n () => highlightDiff(oldCode, newCode, language, options),\r\n [oldCode, newCode, language, options],\r\n );\r\n}\r\n"],"mappings":"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","names":["import_tree_sitter_ts_highlight","import_jsx_runtime","import_tree_sitter_ts_highlight","import_react","import_jsx_runtime","import_tree_sitter_ts_highlight","import_react"]}
@@ -0,0 +1,41 @@
1
+ import { HighlightOptions, DiffOptions } from 'tree-sitter-ts-highlight';
2
+ export * from 'tree-sitter-ts-highlight';
3
+ import { HTMLAttributes, ReactElement } from 'react';
4
+ export * from 'tree-sitter-ts';
5
+
6
+ interface HighlightProps {
7
+ code: string;
8
+ language: string;
9
+ options?: Omit<HighlightOptions, "wrapInPre" | "language">;
10
+ preProps?: HTMLAttributes<HTMLPreElement>;
11
+ codeProps?: HTMLAttributes<HTMLElement>;
12
+ }
13
+ declare function Highlight({ code, language, options, preProps, codeProps, }: HighlightProps): ReactElement;
14
+
15
+ type DataAttributes = {
16
+ [key: `data-${string}`]: string | number | boolean | undefined;
17
+ };
18
+ interface HighlightDiffProps {
19
+ oldCode: string;
20
+ newCode: string;
21
+ language: string;
22
+ options?: DiffOptions;
23
+ containerProps?: HTMLAttributes<HTMLDivElement> & DataAttributes;
24
+ }
25
+ declare function HighlightDiff({ oldCode, newCode, language, options, containerProps, }: HighlightDiffProps): ReactElement;
26
+
27
+ interface UseHighlightedHtmlParams {
28
+ code: string;
29
+ language: string;
30
+ options?: Omit<HighlightOptions, "wrapInPre" | "language">;
31
+ }
32
+ declare function useHighlightedHtml({ code, language, options, }: UseHighlightedHtmlParams): string;
33
+ interface UseHighlightedDiffHtmlParams {
34
+ oldCode: string;
35
+ newCode: string;
36
+ language: string;
37
+ options?: DiffOptions;
38
+ }
39
+ declare function useHighlightedDiffHtml({ oldCode, newCode, language, options, }: UseHighlightedDiffHtmlParams): string;
40
+
41
+ export { Highlight, HighlightDiff, type HighlightDiffProps, type HighlightProps, type UseHighlightedDiffHtmlParams, type UseHighlightedHtmlParams, useHighlightedDiffHtml, useHighlightedHtml };
@@ -0,0 +1,41 @@
1
+ import { HighlightOptions, DiffOptions } from 'tree-sitter-ts-highlight';
2
+ export * from 'tree-sitter-ts-highlight';
3
+ import { HTMLAttributes, ReactElement } from 'react';
4
+ export * from 'tree-sitter-ts';
5
+
6
+ interface HighlightProps {
7
+ code: string;
8
+ language: string;
9
+ options?: Omit<HighlightOptions, "wrapInPre" | "language">;
10
+ preProps?: HTMLAttributes<HTMLPreElement>;
11
+ codeProps?: HTMLAttributes<HTMLElement>;
12
+ }
13
+ declare function Highlight({ code, language, options, preProps, codeProps, }: HighlightProps): ReactElement;
14
+
15
+ type DataAttributes = {
16
+ [key: `data-${string}`]: string | number | boolean | undefined;
17
+ };
18
+ interface HighlightDiffProps {
19
+ oldCode: string;
20
+ newCode: string;
21
+ language: string;
22
+ options?: DiffOptions;
23
+ containerProps?: HTMLAttributes<HTMLDivElement> & DataAttributes;
24
+ }
25
+ declare function HighlightDiff({ oldCode, newCode, language, options, containerProps, }: HighlightDiffProps): ReactElement;
26
+
27
+ interface UseHighlightedHtmlParams {
28
+ code: string;
29
+ language: string;
30
+ options?: Omit<HighlightOptions, "wrapInPre" | "language">;
31
+ }
32
+ declare function useHighlightedHtml({ code, language, options, }: UseHighlightedHtmlParams): string;
33
+ interface UseHighlightedDiffHtmlParams {
34
+ oldCode: string;
35
+ newCode: string;
36
+ language: string;
37
+ options?: DiffOptions;
38
+ }
39
+ declare function useHighlightedDiffHtml({ oldCode, newCode, language, options, }: UseHighlightedDiffHtmlParams): string;
40
+
41
+ export { Highlight, HighlightDiff, type HighlightDiffProps, type HighlightProps, type UseHighlightedDiffHtmlParams, type UseHighlightedHtmlParams, useHighlightedDiffHtml, useHighlightedHtml };
package/dist/index.js ADDED
@@ -0,0 +1,310 @@
1
+ // src/components/Highlight.tsx
2
+ import { enhanceSemantics } from "tree-sitter-ts-highlight";
3
+ import { tokenize } from "tree-sitter-ts";
4
+ import { useMemo } from "react";
5
+
6
+ // src/react-renderer.tsx
7
+ import { applyDecorations, groupTokensByLine } from "tree-sitter-ts-highlight";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ function renderTokenNodes(tokens, options = {}) {
10
+ const prefix = options.classPrefix ?? "hlts-";
11
+ const decorated = options.decorations && options.decorations.length > 0 ? applyDecorations(tokens, options.decorations) : tokens.map((token) => ({
12
+ token,
13
+ extraClasses: [],
14
+ extraAttrs: {},
15
+ extraStyle: void 0
16
+ }));
17
+ return decorated.map(({ token, extraClasses, extraAttrs, extraStyle }, index) => {
18
+ if (token.category === "whitespace" || token.category === "newline") {
19
+ return token.value;
20
+ }
21
+ const key = `${options.keyPrefix ?? "tok"}-${index}`;
22
+ const dataAttrs = Object.fromEntries(
23
+ Object.entries(extraAttrs).map(([k, v]) => [`data-${k}`, v])
24
+ );
25
+ if (options.theme) {
26
+ const baseStyle = options.theme.styles[token.category] ?? "";
27
+ const style = cssTextToReactStyle([baseStyle, extraStyle].filter(Boolean).join(";"));
28
+ return /* @__PURE__ */ jsx("span", { style, ...dataAttrs, children: token.value }, key);
29
+ }
30
+ return /* @__PURE__ */ jsx(
31
+ "span",
32
+ {
33
+ className: [prefix + token.category, ...extraClasses].join(" "),
34
+ ...dataAttrs,
35
+ children: token.value
36
+ },
37
+ key
38
+ );
39
+ });
40
+ }
41
+ function renderLineTable(tokens, options = {}) {
42
+ const groups = groupTokensByLine(tokens);
43
+ const startLine = options.startLine ?? 1;
44
+ const withDataLine = options.dataLineAttributes ?? true;
45
+ return /* @__PURE__ */ jsx("table", { className: "hlts-table", children: /* @__PURE__ */ jsx("tbody", { children: groups.map((group, index) => {
46
+ const displayLine = group.lineNumber - groups[0].lineNumber + startLine;
47
+ return /* @__PURE__ */ jsxs(
48
+ "tr",
49
+ {
50
+ ...withDataLine ? { "data-line": displayLine } : {},
51
+ children: [
52
+ /* @__PURE__ */ jsx("td", { className: "hlts-line-number", children: displayLine }),
53
+ /* @__PURE__ */ jsx("td", { className: "hlts-line-content", children: renderTokenNodes(group.tokens, {
54
+ classPrefix: options.classPrefix,
55
+ theme: options.theme,
56
+ decorations: options.decorations,
57
+ keyPrefix: `line-${group.lineNumber}`
58
+ }) })
59
+ ]
60
+ },
61
+ `line-${group.lineNumber}-${index}`
62
+ );
63
+ }) }) });
64
+ }
65
+ function renderDiffTable(options) {
66
+ const prefix = options.classPrefix ?? "hlts-";
67
+ const view = options.view ?? "side-by-side";
68
+ if (view === "inline") {
69
+ return /* @__PURE__ */ jsx("table", { className: `${prefix}diff ${prefix}diff-inline`, children: /* @__PURE__ */ jsx("tbody", { children: options.rows.flatMap((row, index) => {
70
+ if (row.changeType === "context") {
71
+ return [
72
+ /* @__PURE__ */ jsxs("tr", { className: `${prefix}diff-row ${prefix}diff-context`, children: [
73
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-gutter`, children: row.newLineNumber ?? "" }),
74
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-sign`, children: " " }),
75
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
76
+ lineNumber: row.newLineNumber,
77
+ tokenMap: options.newLineTokens,
78
+ fallbackText: row.newText,
79
+ classPrefix: options.classPrefix,
80
+ theme: options.theme,
81
+ decorations: options.decorations,
82
+ keyPrefix: `inline-context-${index}`
83
+ }) })
84
+ ] }, `ctx-${index}`)
85
+ ];
86
+ }
87
+ const nodes = [];
88
+ if (row.oldLineNumber !== null) {
89
+ nodes.push(
90
+ /* @__PURE__ */ jsxs("tr", { className: `${prefix}diff-row ${prefix}diff-removed`, children: [
91
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-gutter`, children: row.oldLineNumber }),
92
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-sign`, children: "-" }),
93
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
94
+ lineNumber: row.oldLineNumber,
95
+ tokenMap: options.oldLineTokens,
96
+ fallbackText: row.oldText,
97
+ classPrefix: options.classPrefix,
98
+ theme: options.theme,
99
+ decorations: options.decorations,
100
+ keyPrefix: `inline-old-${index}`
101
+ }) })
102
+ ] }, `old-${index}`)
103
+ );
104
+ }
105
+ if (row.newLineNumber !== null) {
106
+ nodes.push(
107
+ /* @__PURE__ */ jsxs("tr", { className: `${prefix}diff-row ${prefix}diff-added`, children: [
108
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-gutter`, children: row.newLineNumber }),
109
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-sign`, children: "+" }),
110
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
111
+ lineNumber: row.newLineNumber,
112
+ tokenMap: options.newLineTokens,
113
+ fallbackText: row.newText,
114
+ classPrefix: options.classPrefix,
115
+ theme: options.theme,
116
+ decorations: options.decorations,
117
+ keyPrefix: `inline-new-${index}`
118
+ }) })
119
+ ] }, `new-${index}`)
120
+ );
121
+ }
122
+ return nodes;
123
+ }) }) });
124
+ }
125
+ return /* @__PURE__ */ jsx("table", { className: `${prefix}diff ${prefix}diff-side-by-side`, children: /* @__PURE__ */ jsxs("tbody", { children: [
126
+ (options.showHeader ?? true) && /* @__PURE__ */ jsxs("tr", { className: `${prefix}diff-header`, children: [
127
+ /* @__PURE__ */ jsx("th", { className: `${prefix}diff-label`, colSpan: 2, children: options.oldLabel }),
128
+ /* @__PURE__ */ jsx("th", { className: `${prefix}diff-label`, colSpan: 2, children: options.newLabel })
129
+ ] }),
130
+ options.rows.map((row, index) => /* @__PURE__ */ jsxs(
131
+ "tr",
132
+ {
133
+ className: `${prefix}diff-row ${prefix}diff-${row.changeType}`,
134
+ children: [
135
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-gutter`, children: row.oldLineNumber ?? "" }),
136
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
137
+ lineNumber: row.oldLineNumber,
138
+ tokenMap: options.oldLineTokens,
139
+ fallbackText: row.oldText,
140
+ classPrefix: options.classPrefix,
141
+ theme: options.theme,
142
+ decorations: options.decorations,
143
+ keyPrefix: `side-old-${index}`
144
+ }) }),
145
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-gutter`, children: row.newLineNumber ?? "" }),
146
+ /* @__PURE__ */ jsx("td", { className: `${prefix}diff-content`, children: renderDiffLineContent({
147
+ lineNumber: row.newLineNumber,
148
+ tokenMap: options.newLineTokens,
149
+ fallbackText: row.newText,
150
+ classPrefix: options.classPrefix,
151
+ theme: options.theme,
152
+ decorations: options.decorations,
153
+ keyPrefix: `side-new-${index}`
154
+ }) })
155
+ ]
156
+ },
157
+ `row-${index}`
158
+ ))
159
+ ] }) });
160
+ }
161
+ function renderDiffLineContent(params) {
162
+ if (params.lineNumber === null) {
163
+ return "";
164
+ }
165
+ const tokens = params.tokenMap.get(params.lineNumber);
166
+ if (!tokens || tokens.length === 0) {
167
+ return params.fallbackText;
168
+ }
169
+ return renderTokenNodes(tokens, {
170
+ classPrefix: params.classPrefix,
171
+ theme: params.theme,
172
+ decorations: params.decorations,
173
+ keyPrefix: params.keyPrefix
174
+ });
175
+ }
176
+ function cssTextToReactStyle(cssText) {
177
+ const style = {};
178
+ for (const declaration of cssText.split(";")) {
179
+ const trimmed = declaration.trim();
180
+ if (!trimmed) {
181
+ continue;
182
+ }
183
+ const separatorIndex = trimmed.indexOf(":");
184
+ if (separatorIndex === -1) {
185
+ continue;
186
+ }
187
+ const property = trimmed.slice(0, separatorIndex).trim();
188
+ const value = trimmed.slice(separatorIndex + 1).trim();
189
+ if (!property || !value) {
190
+ continue;
191
+ }
192
+ style[kebabToCamel(property)] = value;
193
+ }
194
+ return style;
195
+ }
196
+ function kebabToCamel(property) {
197
+ return property.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
198
+ }
199
+
200
+ // src/components/Highlight.tsx
201
+ import { jsx as jsx2 } from "react/jsx-runtime";
202
+ function Highlight({
203
+ code,
204
+ language,
205
+ options,
206
+ preProps,
207
+ codeProps
208
+ }) {
209
+ const tokens = useMemo(() => {
210
+ const rawTokens = tokenize(code, language);
211
+ return options?.semanticHighlighting ? enhanceSemantics(rawTokens) : rawTokens;
212
+ }, [code, language, options?.semanticHighlighting]);
213
+ const { children: _ignoredChildren, ...safeCodeProps } = codeProps ?? {};
214
+ const mergedPreStyle = {
215
+ ...options?.theme?.background ? { background: options.theme.background } : {},
216
+ ...options?.theme?.foreground ? { color: options.theme.foreground } : {},
217
+ ...preProps?.style
218
+ };
219
+ const classPrefix = options?.classPrefix;
220
+ const content = options?.lineNumbers ? renderLineTable(tokens, {
221
+ classPrefix,
222
+ theme: options.theme,
223
+ decorations: options.decorations,
224
+ startLine: options.startLine,
225
+ dataLineAttributes: options.dataLineAttributes
226
+ }) : renderTokenNodes(tokens, {
227
+ classPrefix,
228
+ theme: options?.theme,
229
+ decorations: options?.decorations
230
+ });
231
+ return /* @__PURE__ */ jsx2(
232
+ "pre",
233
+ {
234
+ ...preProps,
235
+ className: ["hlts", `hlts-lang-${language}`, preProps?.className].filter(Boolean).join(" "),
236
+ style: mergedPreStyle,
237
+ children: /* @__PURE__ */ jsx2("code", { ...safeCodeProps, children: content })
238
+ }
239
+ );
240
+ }
241
+
242
+ // src/components/HighlightDiff.tsx
243
+ import { createDiffModelWithTokens } from "tree-sitter-ts-highlight";
244
+ import { useMemo as useMemo2 } from "react";
245
+ import { jsx as jsx3 } from "react/jsx-runtime";
246
+ function HighlightDiff({
247
+ oldCode,
248
+ newCode,
249
+ language,
250
+ options,
251
+ containerProps
252
+ }) {
253
+ const diff = useMemo2(
254
+ () => createDiffModelWithTokens(oldCode, newCode, language, options),
255
+ [oldCode, newCode, language, options]
256
+ );
257
+ const { children: _ignoredChildren, ...safeContainerProps } = containerProps ?? {};
258
+ const table = renderDiffTable({
259
+ view: options?.view,
260
+ showHeader: options?.showHeader,
261
+ classPrefix: options?.classPrefix,
262
+ decorations: options?.decorations,
263
+ theme: options?.theme,
264
+ oldLabel: diff.model.oldLabel,
265
+ newLabel: diff.model.newLabel,
266
+ rows: diff.model.rows,
267
+ oldLineTokens: diff.oldLineTokens,
268
+ newLineTokens: diff.newLineTokens
269
+ });
270
+ return /* @__PURE__ */ jsx3("div", { ...safeContainerProps, children: table });
271
+ }
272
+
273
+ // src/hooks/useHighlightedHtml.ts
274
+ import { highlight, highlightDiff } from "tree-sitter-ts-highlight";
275
+ import { useMemo as useMemo3 } from "react";
276
+ function useHighlightedHtml({
277
+ code,
278
+ language,
279
+ options
280
+ }) {
281
+ return useMemo3(
282
+ () => highlight(code, language, {
283
+ ...options,
284
+ wrapInPre: false,
285
+ language
286
+ }),
287
+ [code, language, options]
288
+ );
289
+ }
290
+ function useHighlightedDiffHtml({
291
+ oldCode,
292
+ newCode,
293
+ language,
294
+ options
295
+ }) {
296
+ return useMemo3(
297
+ () => highlightDiff(oldCode, newCode, language, options),
298
+ [oldCode, newCode, language, options]
299
+ );
300
+ }
301
+
302
+ // src/index.ts
303
+ export * from "tree-sitter-ts-highlight";
304
+ export {
305
+ Highlight,
306
+ HighlightDiff,
307
+ useHighlightedDiffHtml,
308
+ useHighlightedHtml
309
+ };
310
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Highlight.tsx","../src/react-renderer.tsx","../src/components/HighlightDiff.tsx","../src/hooks/useHighlightedHtml.ts","../src/index.ts"],"sourcesContent":["import { enhanceSemantics } from \"tree-sitter-ts-highlight\";\r\nimport type { HighlightOptions } from \"tree-sitter-ts-highlight\";\r\nimport { tokenize } from \"tree-sitter-ts\";\r\nimport { useMemo } from \"react\";\r\nimport type { HTMLAttributes, ReactElement } from \"react\";\r\nimport { renderLineTable, renderTokenNodes } from \"../react-renderer\";\r\n\r\nexport interface HighlightProps {\r\n code: string;\r\n language: string;\r\n options?: Omit<HighlightOptions, \"wrapInPre\" | \"language\">;\r\n preProps?: HTMLAttributes<HTMLPreElement>;\r\n codeProps?: HTMLAttributes<HTMLElement>;\r\n}\r\n\r\nexport function Highlight({\r\n code,\r\n language,\r\n options,\r\n preProps,\r\n codeProps,\r\n}: HighlightProps): ReactElement {\r\n const tokens = useMemo(() => {\r\n const rawTokens = tokenize(code, language);\r\n return options?.semanticHighlighting ? enhanceSemantics(rawTokens) : rawTokens;\r\n }, [code, language, options?.semanticHighlighting]);\r\n\r\n const { children: _ignoredChildren, ...safeCodeProps } = codeProps ?? {};\r\n\r\n const mergedPreStyle = {\r\n ...(options?.theme?.background ? { background: options.theme.background } : {}),\r\n ...(options?.theme?.foreground ? { color: options.theme.foreground } : {}),\r\n ...preProps?.style,\r\n };\r\n\r\n const classPrefix = options?.classPrefix;\r\n const content = options?.lineNumbers\r\n ? renderLineTable(tokens, {\r\n classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n startLine: options.startLine,\r\n dataLineAttributes: options.dataLineAttributes,\r\n })\r\n : renderTokenNodes(tokens, {\r\n classPrefix,\r\n theme: options?.theme,\r\n decorations: options?.decorations,\r\n });\r\n\r\n return (\r\n <pre\r\n {...preProps}\r\n className={[\"hlts\", `hlts-lang-${language}`, preProps?.className].filter(Boolean).join(\" \")}\r\n style={mergedPreStyle}\r\n >\r\n <code {...safeCodeProps}>{content}</code>\r\n </pre>\r\n );\r\n}\r\n","import { applyDecorations, groupTokensByLine } from \"tree-sitter-ts-highlight\";\r\nimport type {\r\n Decoration,\r\n DiffOptions,\r\n HtmlTheme,\r\n} from \"tree-sitter-ts-highlight\";\r\nimport type { Token } from \"tree-sitter-ts\";\r\nimport type { CSSProperties, ReactNode } from \"react\";\r\n\r\ninterface RenderTokenNodesOptions {\r\n classPrefix?: string;\r\n theme?: HtmlTheme;\r\n decorations?: Decoration[];\r\n keyPrefix?: string;\r\n}\r\n\r\ninterface RenderLineTableOptions extends RenderTokenNodesOptions {\r\n startLine?: number;\r\n dataLineAttributes?: boolean;\r\n}\r\n\r\ninterface RenderDiffTableOptions extends RenderTokenNodesOptions {\r\n view?: DiffOptions[\"view\"];\r\n showHeader?: boolean;\r\n oldLabel: string;\r\n newLabel: string;\r\n rows: Array<{\r\n changeType: \"context\" | \"added\" | \"removed\" | \"modified\";\r\n oldLineNumber: number | null;\r\n newLineNumber: number | null;\r\n oldText: string;\r\n newText: string;\r\n }>;\r\n oldLineTokens: Map<number, Token[]>;\r\n newLineTokens: Map<number, Token[]>;\r\n}\r\n\r\nexport function renderTokenNodes(\r\n tokens: Token[],\r\n options: RenderTokenNodesOptions = {},\r\n): ReactNode[] {\r\n const prefix = options.classPrefix ?? \"hlts-\";\r\n const decorated =\r\n options.decorations && options.decorations.length > 0\r\n ? applyDecorations(tokens, options.decorations)\r\n : tokens.map((token) => ({\r\n token,\r\n extraClasses: [],\r\n extraAttrs: {},\r\n extraStyle: undefined,\r\n }));\r\n\r\n return decorated.map(({ token, extraClasses, extraAttrs, extraStyle }, index) => {\r\n if (token.category === \"whitespace\" || token.category === \"newline\") {\r\n return token.value;\r\n }\r\n\r\n const key = `${options.keyPrefix ?? \"tok\"}-${index}`;\r\n const dataAttrs = Object.fromEntries(\r\n Object.entries(extraAttrs).map(([k, v]) => [`data-${k}`, v]),\r\n );\r\n\r\n if (options.theme) {\r\n const baseStyle = options.theme.styles[token.category] ?? \"\";\r\n const style = cssTextToReactStyle([baseStyle, extraStyle].filter(Boolean).join(\";\"));\r\n\r\n return (\r\n <span key={key} style={style} {...dataAttrs}>\r\n {token.value}\r\n </span>\r\n );\r\n }\r\n\r\n return (\r\n <span\r\n key={key}\r\n className={[prefix + token.category, ...extraClasses].join(\" \")}\r\n {...dataAttrs}\r\n >\r\n {token.value}\r\n </span>\r\n );\r\n });\r\n}\r\n\r\nexport function renderLineTable(\r\n tokens: Token[],\r\n options: RenderLineTableOptions = {},\r\n): ReactNode {\r\n const groups = groupTokensByLine(tokens);\r\n const startLine = options.startLine ?? 1;\r\n const withDataLine = options.dataLineAttributes ?? true;\r\n\r\n return (\r\n <table className=\"hlts-table\">\r\n <tbody>\r\n {groups.map((group, index) => {\r\n const displayLine = group.lineNumber - groups[0].lineNumber + startLine;\r\n return (\r\n <tr\r\n key={`line-${group.lineNumber}-${index}`}\r\n {...(withDataLine ? { \"data-line\": displayLine } : {})}\r\n >\r\n <td className=\"hlts-line-number\">{displayLine}</td>\r\n <td className=\"hlts-line-content\">\r\n {renderTokenNodes(group.tokens, {\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `line-${group.lineNumber}`,\r\n })}\r\n </td>\r\n </tr>\r\n );\r\n })}\r\n </tbody>\r\n </table>\r\n );\r\n}\r\n\r\nexport function renderDiffTable(options: RenderDiffTableOptions): ReactNode {\r\n const prefix = options.classPrefix ?? \"hlts-\";\r\n const view = options.view ?? \"side-by-side\";\r\n\r\n if (view === \"inline\") {\r\n return (\r\n <table className={`${prefix}diff ${prefix}diff-inline`}>\r\n <tbody>\r\n {options.rows.flatMap((row, index) => {\r\n if (row.changeType === \"context\") {\r\n return [\r\n <tr key={`ctx-${index}`} className={`${prefix}diff-row ${prefix}diff-context`}>\r\n <td className={`${prefix}diff-gutter`}>{row.newLineNumber ?? \"\"}</td>\r\n <td className={`${prefix}diff-sign`}> </td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.newLineNumber,\r\n tokenMap: options.newLineTokens,\r\n fallbackText: row.newText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `inline-context-${index}`,\r\n })}\r\n </td>\r\n </tr>,\r\n ];\r\n }\r\n\r\n const nodes: ReactNode[] = [];\r\n\r\n if (row.oldLineNumber !== null) {\r\n nodes.push(\r\n <tr key={`old-${index}`} className={`${prefix}diff-row ${prefix}diff-removed`}>\r\n <td className={`${prefix}diff-gutter`}>{row.oldLineNumber}</td>\r\n <td className={`${prefix}diff-sign`}>-</td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.oldLineNumber,\r\n tokenMap: options.oldLineTokens,\r\n fallbackText: row.oldText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `inline-old-${index}`,\r\n })}\r\n </td>\r\n </tr>,\r\n );\r\n }\r\n\r\n if (row.newLineNumber !== null) {\r\n nodes.push(\r\n <tr key={`new-${index}`} className={`${prefix}diff-row ${prefix}diff-added`}>\r\n <td className={`${prefix}diff-gutter`}>{row.newLineNumber}</td>\r\n <td className={`${prefix}diff-sign`}>+</td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.newLineNumber,\r\n tokenMap: options.newLineTokens,\r\n fallbackText: row.newText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `inline-new-${index}`,\r\n })}\r\n </td>\r\n </tr>,\r\n );\r\n }\r\n\r\n return nodes;\r\n })}\r\n </tbody>\r\n </table>\r\n );\r\n }\r\n\r\n return (\r\n <table className={`${prefix}diff ${prefix}diff-side-by-side`}>\r\n <tbody>\r\n {(options.showHeader ?? true) && (\r\n <tr className={`${prefix}diff-header`}>\r\n <th className={`${prefix}diff-label`} colSpan={2}>\r\n {options.oldLabel}\r\n </th>\r\n <th className={`${prefix}diff-label`} colSpan={2}>\r\n {options.newLabel}\r\n </th>\r\n </tr>\r\n )}\r\n\r\n {options.rows.map((row, index) => (\r\n <tr\r\n key={`row-${index}`}\r\n className={`${prefix}diff-row ${prefix}diff-${row.changeType}`}\r\n >\r\n <td className={`${prefix}diff-gutter`}>{row.oldLineNumber ?? \"\"}</td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.oldLineNumber,\r\n tokenMap: options.oldLineTokens,\r\n fallbackText: row.oldText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `side-old-${index}`,\r\n })}\r\n </td>\r\n <td className={`${prefix}diff-gutter`}>{row.newLineNumber ?? \"\"}</td>\r\n <td className={`${prefix}diff-content`}>\r\n {renderDiffLineContent({\r\n lineNumber: row.newLineNumber,\r\n tokenMap: options.newLineTokens,\r\n fallbackText: row.newText,\r\n classPrefix: options.classPrefix,\r\n theme: options.theme,\r\n decorations: options.decorations,\r\n keyPrefix: `side-new-${index}`,\r\n })}\r\n </td>\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n );\r\n}\r\n\r\nfunction renderDiffLineContent(params: {\r\n lineNumber: number | null;\r\n tokenMap: Map<number, Token[]>;\r\n fallbackText: string;\r\n classPrefix?: string;\r\n theme?: HtmlTheme;\r\n decorations?: Decoration[];\r\n keyPrefix: string;\r\n}): ReactNode {\r\n if (params.lineNumber === null) {\r\n return \"\";\r\n }\r\n\r\n const tokens = params.tokenMap.get(params.lineNumber);\r\n if (!tokens || tokens.length === 0) {\r\n return params.fallbackText;\r\n }\r\n\r\n return renderTokenNodes(tokens, {\r\n classPrefix: params.classPrefix,\r\n theme: params.theme,\r\n decorations: params.decorations,\r\n keyPrefix: params.keyPrefix,\r\n });\r\n}\r\n\r\nfunction cssTextToReactStyle(cssText: string): CSSProperties {\r\n const style: Record<string, string> = {};\r\n\r\n for (const declaration of cssText.split(\";\")) {\r\n const trimmed = declaration.trim();\r\n if (!trimmed) {\r\n continue;\r\n }\r\n\r\n const separatorIndex = trimmed.indexOf(\":\");\r\n if (separatorIndex === -1) {\r\n continue;\r\n }\r\n\r\n const property = trimmed.slice(0, separatorIndex).trim();\r\n const value = trimmed.slice(separatorIndex + 1).trim();\r\n if (!property || !value) {\r\n continue;\r\n }\r\n\r\n style[kebabToCamel(property)] = value;\r\n }\r\n\r\n return style as CSSProperties;\r\n}\r\n\r\nfunction kebabToCamel(property: string): string {\r\n return property.replace(/-([a-z])/g, (_, char: string) => char.toUpperCase());\r\n}\r\n","import { createDiffModelWithTokens } from \"tree-sitter-ts-highlight\";\r\nimport type { DiffOptions } from \"tree-sitter-ts-highlight\";\r\nimport { useMemo } from \"react\";\r\nimport type { HTMLAttributes, ReactElement } from \"react\";\r\nimport { renderDiffTable } from \"../react-renderer\";\r\n\r\ntype DataAttributes = {\r\n [key: `data-${string}`]: string | number | boolean | undefined;\r\n};\r\n\r\nexport interface HighlightDiffProps {\r\n oldCode: string;\r\n newCode: string;\r\n language: string;\r\n options?: DiffOptions;\r\n containerProps?: HTMLAttributes<HTMLDivElement> & DataAttributes;\r\n}\r\n\r\nexport function HighlightDiff({\r\n oldCode,\r\n newCode,\r\n language,\r\n options,\r\n containerProps,\r\n}: HighlightDiffProps): ReactElement {\r\n const diff = useMemo(\r\n () => createDiffModelWithTokens(oldCode, newCode, language, options),\r\n [oldCode, newCode, language, options],\r\n );\r\n\r\n const { children: _ignoredChildren, ...safeContainerProps } = containerProps ?? {};\r\n\r\n const table = renderDiffTable({\r\n view: options?.view,\r\n showHeader: options?.showHeader,\r\n classPrefix: options?.classPrefix,\r\n decorations: options?.decorations,\r\n theme: options?.theme,\r\n oldLabel: diff.model.oldLabel,\r\n newLabel: diff.model.newLabel,\r\n rows: diff.model.rows,\r\n oldLineTokens: diff.oldLineTokens,\r\n newLineTokens: diff.newLineTokens,\r\n });\r\n\r\n return <div {...safeContainerProps}>{table}</div>;\r\n}\r\n","import { highlight, highlightDiff } from \"tree-sitter-ts-highlight\";\r\nimport type { DiffOptions, HighlightOptions } from \"tree-sitter-ts-highlight\";\r\nimport { useMemo } from \"react\";\r\n\r\nexport interface UseHighlightedHtmlParams {\r\n code: string;\r\n language: string;\r\n options?: Omit<HighlightOptions, \"wrapInPre\" | \"language\">;\r\n}\r\n\r\nexport function useHighlightedHtml({\r\n code,\r\n language,\r\n options,\r\n}: UseHighlightedHtmlParams): string {\r\n return useMemo(\r\n () =>\r\n highlight(code, language, {\r\n ...options,\r\n wrapInPre: false,\r\n language,\r\n }),\r\n [code, language, options],\r\n );\r\n}\r\n\r\nexport interface UseHighlightedDiffHtmlParams {\r\n oldCode: string;\r\n newCode: string;\r\n language: string;\r\n options?: DiffOptions;\r\n}\r\n\r\nexport function useHighlightedDiffHtml({\r\n oldCode,\r\n newCode,\r\n language,\r\n options,\r\n}: UseHighlightedDiffHtmlParams): string {\r\n return useMemo(\r\n () => highlightDiff(oldCode, newCode, language, options),\r\n [oldCode, newCode, language, options],\r\n );\r\n}\r\n","export { Highlight } from \"./components/Highlight\";\r\nexport type { HighlightProps } from \"./components/Highlight\";\r\n\r\nexport { HighlightDiff } from \"./components/HighlightDiff\";\r\nexport type { HighlightDiffProps } from \"./components/HighlightDiff\";\r\n\r\nexport {\r\n useHighlightedHtml,\r\n useHighlightedDiffHtml,\r\n} from \"./hooks/useHighlightedHtml\";\r\nexport type {\r\n UseHighlightedHtmlParams,\r\n UseHighlightedDiffHtmlParams,\r\n} from \"./hooks/useHighlightedHtml\";\r\n\r\nexport type * from \"tree-sitter-ts\";\r\nexport type * from \"tree-sitter-ts-highlight\";\r\nexport * from \"tree-sitter-ts-highlight\";\r\n"],"mappings":";AAAA,SAAS,wBAAwB;AAEjC,SAAS,gBAAgB;AACzB,SAAS,eAAe;;;ACHxB,SAAS,kBAAkB,yBAAyB;AAmEpC,cAgCQ,YAhCR;AA9BT,SAAS,iBACZ,QACA,UAAmC,CAAC,GACzB;AACX,QAAM,SAAS,QAAQ,eAAe;AACtC,QAAM,YACF,QAAQ,eAAe,QAAQ,YAAY,SAAS,IAC9C,iBAAiB,QAAQ,QAAQ,WAAW,IAC5C,OAAO,IAAI,CAAC,WAAW;AAAA,IACrB;AAAA,IACA,cAAc,CAAC;AAAA,IACf,YAAY,CAAC;AAAA,IACb,YAAY;AAAA,EAChB,EAAE;AAEV,SAAO,UAAU,IAAI,CAAC,EAAE,OAAO,cAAc,YAAY,WAAW,GAAG,UAAU;AAC7E,QAAI,MAAM,aAAa,gBAAgB,MAAM,aAAa,WAAW;AACjE,aAAO,MAAM;AAAA,IACjB;AAEA,UAAM,MAAM,GAAG,QAAQ,aAAa,KAAK,IAAI,KAAK;AAClD,UAAM,YAAY,OAAO;AAAA,MACrB,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAAA,IAC/D;AAEA,QAAI,QAAQ,OAAO;AACf,YAAM,YAAY,QAAQ,MAAM,OAAO,MAAM,QAAQ,KAAK;AAC1D,YAAM,QAAQ,oBAAoB,CAAC,WAAW,UAAU,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAAC;AAEnF,aACI,oBAAC,UAAe,OAAe,GAAG,WAC7B,gBAAM,SADA,GAEX;AAAA,IAER;AAEA,WACI;AAAA,MAAC;AAAA;AAAA,QAEG,WAAW,CAAC,SAAS,MAAM,UAAU,GAAG,YAAY,EAAE,KAAK,GAAG;AAAA,QAC7D,GAAG;AAAA,QAEH,gBAAM;AAAA;AAAA,MAJF;AAAA,IAKT;AAAA,EAER,CAAC;AACL;AAEO,SAAS,gBACZ,QACA,UAAkC,CAAC,GAC1B;AACT,QAAM,SAAS,kBAAkB,MAAM;AACvC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,eAAe,QAAQ,sBAAsB;AAEnD,SACI,oBAAC,WAAM,WAAU,cACb,8BAAC,WACI,iBAAO,IAAI,CAAC,OAAO,UAAU;AAC1B,UAAM,cAAc,MAAM,aAAa,OAAO,CAAC,EAAE,aAAa;AAC9D,WACI;AAAA,MAAC;AAAA;AAAA,QAEI,GAAI,eAAe,EAAE,aAAa,YAAY,IAAI,CAAC;AAAA,QAEpD;AAAA,8BAAC,QAAG,WAAU,oBAAoB,uBAAY;AAAA,UAC9C,oBAAC,QAAG,WAAU,qBACT,2BAAiB,MAAM,QAAQ;AAAA,YAC5B,aAAa,QAAQ;AAAA,YACrB,OAAO,QAAQ;AAAA,YACf,aAAa,QAAQ;AAAA,YACrB,WAAW,QAAQ,MAAM,UAAU;AAAA,UACvC,CAAC,GACL;AAAA;AAAA;AAAA,MAXK,QAAQ,MAAM,UAAU,IAAI,KAAK;AAAA,IAY1C;AAAA,EAER,CAAC,GACL,GACJ;AAER;AAEO,SAAS,gBAAgB,SAA4C;AACxE,QAAM,SAAS,QAAQ,eAAe;AACtC,QAAM,OAAO,QAAQ,QAAQ;AAE7B,MAAI,SAAS,UAAU;AACnB,WACI,oBAAC,WAAM,WAAW,GAAG,MAAM,QAAQ,MAAM,eACrC,8BAAC,WACI,kBAAQ,KAAK,QAAQ,CAAC,KAAK,UAAU;AAClC,UAAI,IAAI,eAAe,WAAW;AAC9B,eAAO;AAAA,UACH,qBAAC,QAAwB,WAAW,GAAG,MAAM,YAAY,MAAM,gBAC3D;AAAA,gCAAC,QAAG,WAAW,GAAG,MAAM,eAAgB,cAAI,iBAAiB,IAAG;AAAA,YAChE,oBAAC,QAAG,WAAW,GAAG,MAAM,aAAa,eAAC;AAAA,YACtC,oBAAC,QAAG,WAAW,GAAG,MAAM,gBACnB,gCAAsB;AAAA,cACnB,YAAY,IAAI;AAAA,cAChB,UAAU,QAAQ;AAAA,cAClB,cAAc,IAAI;AAAA,cAClB,aAAa,QAAQ;AAAA,cACrB,OAAO,QAAQ;AAAA,cACf,aAAa,QAAQ;AAAA,cACrB,WAAW,kBAAkB,KAAK;AAAA,YACtC,CAAC,GACL;AAAA,eAbK,OAAO,KAAK,EAcrB;AAAA,QACJ;AAAA,MACJ;AAEA,YAAM,QAAqB,CAAC;AAE5B,UAAI,IAAI,kBAAkB,MAAM;AAC5B,cAAM;AAAA,UACF,qBAAC,QAAwB,WAAW,GAAG,MAAM,YAAY,MAAM,gBAC3D;AAAA,gCAAC,QAAG,WAAW,GAAG,MAAM,eAAgB,cAAI,eAAc;AAAA,YAC1D,oBAAC,QAAG,WAAW,GAAG,MAAM,aAAa,eAAC;AAAA,YACtC,oBAAC,QAAG,WAAW,GAAG,MAAM,gBACnB,gCAAsB;AAAA,cACnB,YAAY,IAAI;AAAA,cAChB,UAAU,QAAQ;AAAA,cAClB,cAAc,IAAI;AAAA,cAClB,aAAa,QAAQ;AAAA,cACrB,OAAO,QAAQ;AAAA,cACf,aAAa,QAAQ;AAAA,cACrB,WAAW,cAAc,KAAK;AAAA,YAClC,CAAC,GACL;AAAA,eAbK,OAAO,KAAK,EAcrB;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI,IAAI,kBAAkB,MAAM;AAC5B,cAAM;AAAA,UACF,qBAAC,QAAwB,WAAW,GAAG,MAAM,YAAY,MAAM,cAC3D;AAAA,gCAAC,QAAG,WAAW,GAAG,MAAM,eAAgB,cAAI,eAAc;AAAA,YAC1D,oBAAC,QAAG,WAAW,GAAG,MAAM,aAAa,eAAC;AAAA,YACtC,oBAAC,QAAG,WAAW,GAAG,MAAM,gBACnB,gCAAsB;AAAA,cACnB,YAAY,IAAI;AAAA,cAChB,UAAU,QAAQ;AAAA,cAClB,cAAc,IAAI;AAAA,cAClB,aAAa,QAAQ;AAAA,cACrB,OAAO,QAAQ;AAAA,cACf,aAAa,QAAQ;AAAA,cACrB,WAAW,cAAc,KAAK;AAAA,YAClC,CAAC,GACL;AAAA,eAbK,OAAO,KAAK,EAcrB;AAAA,QACJ;AAAA,MACJ;AAEA,aAAO;AAAA,IACX,CAAC,GACL,GACJ;AAAA,EAER;AAEA,SACI,oBAAC,WAAM,WAAW,GAAG,MAAM,QAAQ,MAAM,qBACrC,+BAAC,WACK;AAAA,aAAQ,cAAc,SACpB,qBAAC,QAAG,WAAW,GAAG,MAAM,eACpB;AAAA,0BAAC,QAAG,WAAW,GAAG,MAAM,cAAc,SAAS,GAC1C,kBAAQ,UACb;AAAA,MACA,oBAAC,QAAG,WAAW,GAAG,MAAM,cAAc,SAAS,GAC1C,kBAAQ,UACb;AAAA,OACJ;AAAA,IAGH,QAAQ,KAAK,IAAI,CAAC,KAAK,UACpB;AAAA,MAAC;AAAA;AAAA,QAEG,WAAW,GAAG,MAAM,YAAY,MAAM,QAAQ,IAAI,UAAU;AAAA,QAE5D;AAAA,8BAAC,QAAG,WAAW,GAAG,MAAM,eAAgB,cAAI,iBAAiB,IAAG;AAAA,UAChE,oBAAC,QAAG,WAAW,GAAG,MAAM,gBACnB,gCAAsB;AAAA,YACnB,YAAY,IAAI;AAAA,YAChB,UAAU,QAAQ;AAAA,YAClB,cAAc,IAAI;AAAA,YAClB,aAAa,QAAQ;AAAA,YACrB,OAAO,QAAQ;AAAA,YACf,aAAa,QAAQ;AAAA,YACrB,WAAW,YAAY,KAAK;AAAA,UAChC,CAAC,GACL;AAAA,UACA,oBAAC,QAAG,WAAW,GAAG,MAAM,eAAgB,cAAI,iBAAiB,IAAG;AAAA,UAChE,oBAAC,QAAG,WAAW,GAAG,MAAM,gBACnB,gCAAsB;AAAA,YACnB,YAAY,IAAI;AAAA,YAChB,UAAU,QAAQ;AAAA,YAClB,cAAc,IAAI;AAAA,YAClB,aAAa,QAAQ;AAAA,YACrB,OAAO,QAAQ;AAAA,YACf,aAAa,QAAQ;AAAA,YACrB,WAAW,YAAY,KAAK;AAAA,UAChC,CAAC,GACL;AAAA;AAAA;AAAA,MA1BK,OAAO,KAAK;AAAA,IA2BrB,CACH;AAAA,KACL,GACJ;AAER;AAEA,SAAS,sBAAsB,QAQjB;AACV,MAAI,OAAO,eAAe,MAAM;AAC5B,WAAO;AAAA,EACX;AAEA,QAAM,SAAS,OAAO,SAAS,IAAI,OAAO,UAAU;AACpD,MAAI,CAAC,UAAU,OAAO,WAAW,GAAG;AAChC,WAAO,OAAO;AAAA,EAClB;AAEA,SAAO,iBAAiB,QAAQ;AAAA,IAC5B,aAAa,OAAO;AAAA,IACpB,OAAO,OAAO;AAAA,IACd,aAAa,OAAO;AAAA,IACpB,WAAW,OAAO;AAAA,EACtB,CAAC;AACL;AAEA,SAAS,oBAAoB,SAAgC;AACzD,QAAM,QAAgC,CAAC;AAEvC,aAAW,eAAe,QAAQ,MAAM,GAAG,GAAG;AAC1C,UAAM,UAAU,YAAY,KAAK;AACjC,QAAI,CAAC,SAAS;AACV;AAAA,IACJ;AAEA,UAAM,iBAAiB,QAAQ,QAAQ,GAAG;AAC1C,QAAI,mBAAmB,IAAI;AACvB;AAAA,IACJ;AAEA,UAAM,WAAW,QAAQ,MAAM,GAAG,cAAc,EAAE,KAAK;AACvD,UAAM,QAAQ,QAAQ,MAAM,iBAAiB,CAAC,EAAE,KAAK;AACrD,QAAI,CAAC,YAAY,CAAC,OAAO;AACrB;AAAA,IACJ;AAEA,UAAM,aAAa,QAAQ,CAAC,IAAI;AAAA,EACpC;AAEA,SAAO;AACX;AAEA,SAAS,aAAa,UAA0B;AAC5C,SAAO,SAAS,QAAQ,aAAa,CAAC,GAAG,SAAiB,KAAK,YAAY,CAAC;AAChF;;;ADtPY,gBAAAA,YAAA;AAzCL,SAAS,UAAU;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAiC;AAC7B,QAAM,SAAS,QAAQ,MAAM;AACzB,UAAM,YAAY,SAAS,MAAM,QAAQ;AACzC,WAAO,SAAS,uBAAuB,iBAAiB,SAAS,IAAI;AAAA,EACzE,GAAG,CAAC,MAAM,UAAU,SAAS,oBAAoB,CAAC;AAElD,QAAM,EAAE,UAAU,kBAAkB,GAAG,cAAc,IAAI,aAAa,CAAC;AAEvE,QAAM,iBAAiB;AAAA,IACnB,GAAI,SAAS,OAAO,aAAa,EAAE,YAAY,QAAQ,MAAM,WAAW,IAAI,CAAC;AAAA,IAC7E,GAAI,SAAS,OAAO,aAAa,EAAE,OAAO,QAAQ,MAAM,WAAW,IAAI,CAAC;AAAA,IACxE,GAAG,UAAU;AAAA,EACjB;AAEA,QAAM,cAAc,SAAS;AAC7B,QAAM,UAAU,SAAS,cACnB,gBAAgB,QAAQ;AAAA,IACtB;AAAA,IACA,OAAO,QAAQ;AAAA,IACf,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,IACnB,oBAAoB,QAAQ;AAAA,EAChC,CAAC,IACC,iBAAiB,QAAQ;AAAA,IACvB;AAAA,IACA,OAAO,SAAS;AAAA,IAChB,aAAa,SAAS;AAAA,EAC1B,CAAC;AAEL,SACI,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACI,GAAG;AAAA,MACJ,WAAW,CAAC,QAAQ,aAAa,QAAQ,IAAI,UAAU,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,MAC1F,OAAO;AAAA,MAEP,0BAAAA,KAAC,UAAM,GAAG,eAAgB,mBAAQ;AAAA;AAAA,EACtC;AAER;;;AE3DA,SAAS,iCAAiC;AAE1C,SAAS,WAAAC,gBAAe;AA2Cb,gBAAAC,YAAA;AA3BJ,SAAS,cAAc;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAqC;AACjC,QAAM,OAAOC;AAAA,IACT,MAAM,0BAA0B,SAAS,SAAS,UAAU,OAAO;AAAA,IACnE,CAAC,SAAS,SAAS,UAAU,OAAO;AAAA,EACxC;AAEA,QAAM,EAAE,UAAU,kBAAkB,GAAG,mBAAmB,IAAI,kBAAkB,CAAC;AAEjF,QAAM,QAAQ,gBAAgB;AAAA,IAC1B,MAAM,SAAS;AAAA,IACf,YAAY,SAAS;AAAA,IACrB,aAAa,SAAS;AAAA,IACtB,aAAa,SAAS;AAAA,IACtB,OAAO,SAAS;AAAA,IAChB,UAAU,KAAK,MAAM;AAAA,IACrB,UAAU,KAAK,MAAM;AAAA,IACrB,MAAM,KAAK,MAAM;AAAA,IACjB,eAAe,KAAK;AAAA,IACpB,eAAe,KAAK;AAAA,EACxB,CAAC;AAED,SAAO,gBAAAD,KAAC,SAAK,GAAG,oBAAqB,iBAAM;AAC/C;;;AC9CA,SAAS,WAAW,qBAAqB;AAEzC,SAAS,WAAAE,gBAAe;AAQjB,SAAS,mBAAmB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AACJ,GAAqC;AACjC,SAAOA;AAAA,IACH,MACI,UAAU,MAAM,UAAU;AAAA,MACtB,GAAG;AAAA,MACH,WAAW;AAAA,MACX;AAAA,IACJ,CAAC;AAAA,IACL,CAAC,MAAM,UAAU,OAAO;AAAA,EAC5B;AACJ;AASO,SAAS,uBAAuB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAyC;AACrC,SAAOA;AAAA,IACH,MAAM,cAAc,SAAS,SAAS,UAAU,OAAO;AAAA,IACvD,CAAC,SAAS,SAAS,UAAU,OAAO;AAAA,EACxC;AACJ;;;AC1BA,cAAc;","names":["jsx","useMemo","jsx","useMemo","useMemo"]}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "tree-sitter-ts-highlight-react",
3
+ "version": "0.1.2",
4
+ "description": "React wrapper components and hooks 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
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "typecheck": "tsc --noEmit",
27
+ "test": "jest",
28
+ "test:watch": "jest --watch"
29
+ },
30
+ "peerDependencies": {
31
+ "react": "^18.0.0 || ^19.0.0",
32
+ "tree-sitter-ts": "^0.1.2",
33
+ "tree-sitter-ts-highlight": "^0.1.2"
34
+ },
35
+ "devDependencies": {
36
+ "@swc/core": "^1.11.22",
37
+ "@swc/jest": "^0.2.39",
38
+ "@testing-library/jest-dom": "^6.8.0",
39
+ "@testing-library/react": "^16.3.0",
40
+ "@types/jest": "^30.0.0",
41
+ "@types/react": "^19.1.10",
42
+ "jest": "^30.0.5",
43
+ "jest-environment-jsdom": "^30.0.5",
44
+ "react": "^19.1.1",
45
+ "react-dom": "^19.1.1",
46
+ "tree-sitter-ts": "^0.1.2",
47
+ "tree-sitter-ts-highlight": "^0.1.2",
48
+ "tsup": "^8.0.0",
49
+ "typescript": "^5.4.0"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public",
53
+ "provenance": false
54
+ },
55
+ "keywords": [
56
+ "react",
57
+ "tree-sitter",
58
+ "syntax-highlighting",
59
+ "typescript",
60
+ "code-highlighting"
61
+ ],
62
+ "repository": {
63
+ "type": "git",
64
+ "url": "https://github.com/hieutran512/tree-sitter-ts-highlight-react"
65
+ },
66
+ "license": "MIT",
67
+ "engines": {
68
+ "node": ">=18.0.0"
69
+ }
70
+ }