fractalpop 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +232 -0
  3. package/dist/core.d.ts +110 -0
  4. package/dist/core.js +313 -0
  5. package/dist/full.d.ts +1 -0
  6. package/dist/full.js +356 -0
  7. package/dist/gpu.d.ts +59 -0
  8. package/dist/gpu.js +215 -0
  9. package/dist/index.d.ts +108 -0
  10. package/dist/index.js +523 -0
  11. package/dist/lang/c.d.ts +5 -0
  12. package/dist/lang/c.js +90 -0
  13. package/dist/lang/cpp.d.ts +5 -0
  14. package/dist/lang/cpp.js +138 -0
  15. package/dist/lang/csharp.d.ts +5 -0
  16. package/dist/lang/csharp.js +148 -0
  17. package/dist/lang/css.d.ts +21 -0
  18. package/dist/lang/css.js +164 -0
  19. package/dist/lang/diff.d.ts +30 -0
  20. package/dist/lang/diff.js +18 -0
  21. package/dist/lang/dockerfile.d.ts +5 -0
  22. package/dist/lang/dockerfile.js +60 -0
  23. package/dist/lang/go.d.ts +5 -0
  24. package/dist/lang/go.js +91 -0
  25. package/dist/lang/graphql.d.ts +5 -0
  26. package/dist/lang/graphql.js +66 -0
  27. package/dist/lang/hcl.d.ts +5 -0
  28. package/dist/lang/hcl.js +51 -0
  29. package/dist/lang/html.d.ts +12 -0
  30. package/dist/lang/html.js +168 -0
  31. package/dist/lang/java.d.ts +5 -0
  32. package/dist/lang/java.js +96 -0
  33. package/dist/lang/javascript.d.ts +5 -0
  34. package/dist/lang/javascript.js +0 -0
  35. package/dist/lang/json.d.ts +5 -0
  36. package/dist/lang/json.js +47 -0
  37. package/dist/lang/kotlin.d.ts +5 -0
  38. package/dist/lang/kotlin.js +113 -0
  39. package/dist/lang/lua.d.ts +5 -0
  40. package/dist/lang/lua.js +65 -0
  41. package/dist/lang/markdown.d.ts +12 -0
  42. package/dist/lang/markdown.js +172 -0
  43. package/dist/lang/php.d.ts +5 -0
  44. package/dist/lang/php.js +129 -0
  45. package/dist/lang/plaintext.d.ts +7 -0
  46. package/dist/lang/plaintext.js +3 -0
  47. package/dist/lang/powershell.d.ts +5 -0
  48. package/dist/lang/powershell.js +74 -0
  49. package/dist/lang/python.d.ts +5 -0
  50. package/dist/lang/python.js +75 -0
  51. package/dist/lang/ruby.d.ts +5 -0
  52. package/dist/lang/ruby.js +84 -0
  53. package/dist/lang/rust.d.ts +5 -0
  54. package/dist/lang/rust.js +95 -0
  55. package/dist/lang/sass.d.ts +15 -0
  56. package/dist/lang/sass.js +201 -0
  57. package/dist/lang/scss.d.ts +14 -0
  58. package/dist/lang/scss.js +105 -0
  59. package/dist/lang/shell.d.ts +5 -0
  60. package/dist/lang/shell.js +64 -0
  61. package/dist/lang/sql.d.ts +5 -0
  62. package/dist/lang/sql.js +129 -0
  63. package/dist/lang/svelte.d.ts +15 -0
  64. package/dist/lang/svelte.js +0 -0
  65. package/dist/lang/swift.d.ts +5 -0
  66. package/dist/lang/swift.js +125 -0
  67. package/dist/lang/toml.d.ts +5 -0
  68. package/dist/lang/toml.js +45 -0
  69. package/dist/lang/typescript.d.ts +5 -0
  70. package/dist/lang/typescript.js +0 -0
  71. package/dist/lang/yaml.d.ts +5 -0
  72. package/dist/lang/yaml.js +64 -0
  73. package/dist/lang/zig.d.ts +5 -0
  74. package/dist/lang/zig.js +133 -0
  75. package/dist/lang.d.ts +30 -0
  76. package/dist/lang.js +345 -0
  77. package/package.json +68 -0
package/dist/full.js ADDED
@@ -0,0 +1,356 @@
1
+ import { registerLanguages } from './index.js';
2
+ export * from './index.js';
3
+ import { config as config$1 } from './lang/typescript.js';
4
+ import { config } from './lang/plaintext.js';
5
+ import { config as config$v } from './lang/javascript.js';
6
+ import { config as config$u } from './lang/css.js';
7
+ import { config as config$t } from './lang/scss.js';
8
+ import { config as config$s } from './lang/sass.js';
9
+ import { config as config$r } from './lang/html.js';
10
+ import { config as config$q } from './lang/svelte.js';
11
+ import { config as config$p } from './lang/markdown.js';
12
+ import { config as config$o } from './lang/diff.js';
13
+ import { config as config$n } from './lang/c.js';
14
+ import { config as config$m } from './lang/cpp.js';
15
+ import { config as config$l } from './lang/csharp.js';
16
+ import { config as config$k } from './lang/dockerfile.js';
17
+ import { config as config$j } from './lang/go.js';
18
+ import { config as config$i } from './lang/graphql.js';
19
+ import { config as config$h } from './lang/hcl.js';
20
+ import { config as config$g } from './lang/java.js';
21
+ import { config as config$f } from './lang/json.js';
22
+ import { config as config$e } from './lang/kotlin.js';
23
+ import { config as config$d } from './lang/lua.js';
24
+ import { config as config$c } from './lang/php.js';
25
+ import { config as config$b } from './lang/powershell.js';
26
+ import { config as config$a } from './lang/python.js';
27
+ import { config as config$9 } from './lang/ruby.js';
28
+ import { config as config$8 } from './lang/rust.js';
29
+ import { config as config$7 } from './lang/shell.js';
30
+ import { config as config$6 } from './lang/sql.js';
31
+ import { config as config$5 } from './lang/swift.js';
32
+ import { config as config$4 } from './lang/toml.js';
33
+ import { config as config$3 } from './lang/yaml.js';
34
+ import { config as config$2 } from './lang/zig.js';
35
+
36
+ /** Mutable registry that maps a canonical language id to its parse config. */ const configRegistry = new Map();
37
+ function registerLanguageConfig(id, config) {
38
+ configRegistry.set(id, config);
39
+ }
40
+ function resetLanguageConfigRegistry() {
41
+ configRegistry.clear();
42
+ }
43
+
44
+ const languageRegistry = new Map();
45
+ function normalizeLanguageName(value) {
46
+ return value.trim().toLowerCase().replace(/^\./, '');
47
+ }
48
+ function registerName(name, language) {
49
+ const normalized = normalizeLanguageName(name);
50
+ if (!normalized) return;
51
+ const existing = languageRegistry.get(normalized);
52
+ if (existing && existing.id !== language.id) {
53
+ throw new Error(`Language name "${normalized}" is shared by "${existing.id}" and "${language.id}"`);
54
+ }
55
+ languageRegistry.set(normalized, language);
56
+ }
57
+ function registerLanguage(language, config) {
58
+ const names = new Set([
59
+ language.id,
60
+ language.extension,
61
+ ...language.aliases
62
+ ]);
63
+ for (const name of names){
64
+ registerName(name, language);
65
+ }
66
+ if (config) {
67
+ registerLanguageConfig(language.id, config);
68
+ }
69
+ }
70
+ function setDefaults(input) {
71
+ resetLanguageRegistry();
72
+ resetLanguageConfigRegistry();
73
+ if (Array.isArray(input)) {
74
+ for (const language of input){
75
+ registerLanguage(language);
76
+ }
77
+ } else {
78
+ for (const [id, config] of Object.entries(input)){
79
+ const language = allLanguages.find((l)=>l.id === id);
80
+ if (language) {
81
+ registerLanguage(language, config);
82
+ } else {
83
+ registerLanguage({
84
+ id,
85
+ extension: id,
86
+ aliases: []
87
+ }, config);
88
+ }
89
+ }
90
+ }
91
+ }
92
+ function resetLanguageRegistry() {
93
+ languageRegistry.clear();
94
+ }
95
+ const allLanguages = [
96
+ {
97
+ id: 'javascript',
98
+ extension: 'js',
99
+ aliases: [
100
+ 'jsx',
101
+ 'node'
102
+ ]
103
+ },
104
+ {
105
+ id: 'typescript',
106
+ extension: 'ts',
107
+ aliases: [
108
+ 'tsx'
109
+ ]
110
+ },
111
+ {
112
+ id: 'css',
113
+ extension: 'css',
114
+ aliases: []
115
+ },
116
+ {
117
+ id: 'scss',
118
+ extension: 'scss',
119
+ aliases: []
120
+ },
121
+ {
122
+ id: 'sass',
123
+ extension: 'sass',
124
+ aliases: [
125
+ 'indented-sass'
126
+ ]
127
+ },
128
+ {
129
+ id: 'html',
130
+ extension: 'html',
131
+ aliases: [
132
+ 'htm',
133
+ 'xml'
134
+ ]
135
+ },
136
+ {
137
+ id: 'svelte',
138
+ extension: 'svelte',
139
+ aliases: []
140
+ },
141
+ {
142
+ id: 'markdown',
143
+ extension: 'md',
144
+ aliases: [
145
+ 'md',
146
+ 'mdx',
147
+ 'svx'
148
+ ]
149
+ },
150
+ {
151
+ id: 'diff',
152
+ extension: 'diff',
153
+ aliases: [
154
+ 'patch'
155
+ ]
156
+ },
157
+ {
158
+ id: 'plaintext',
159
+ extension: 'txt',
160
+ aliases: [
161
+ 'text',
162
+ 'plain'
163
+ ]
164
+ },
165
+ {
166
+ id: 'c',
167
+ extension: 'c',
168
+ aliases: []
169
+ },
170
+ {
171
+ id: 'cpp',
172
+ extension: 'cpp',
173
+ aliases: [
174
+ 'c++',
175
+ 'cc',
176
+ 'cxx'
177
+ ]
178
+ },
179
+ {
180
+ id: 'csharp',
181
+ extension: 'cs',
182
+ aliases: [
183
+ 'c#',
184
+ 'dotnet'
185
+ ]
186
+ },
187
+ {
188
+ id: 'dockerfile',
189
+ extension: 'dockerfile',
190
+ aliases: [
191
+ 'docker'
192
+ ]
193
+ },
194
+ {
195
+ id: 'go',
196
+ extension: 'go',
197
+ aliases: [
198
+ 'golang'
199
+ ]
200
+ },
201
+ {
202
+ id: 'graphql',
203
+ extension: 'graphql',
204
+ aliases: [
205
+ 'gql'
206
+ ]
207
+ },
208
+ {
209
+ id: 'hcl',
210
+ extension: 'hcl',
211
+ aliases: [
212
+ 'terraform',
213
+ 'tf'
214
+ ]
215
+ },
216
+ {
217
+ id: 'java',
218
+ extension: 'java',
219
+ aliases: []
220
+ },
221
+ {
222
+ id: 'json',
223
+ extension: 'json',
224
+ aliases: [
225
+ 'jsonc'
226
+ ]
227
+ },
228
+ {
229
+ id: 'kotlin',
230
+ extension: 'kt',
231
+ aliases: [
232
+ 'kts'
233
+ ]
234
+ },
235
+ {
236
+ id: 'lua',
237
+ extension: 'lua',
238
+ aliases: []
239
+ },
240
+ {
241
+ id: 'php',
242
+ extension: 'php',
243
+ aliases: []
244
+ },
245
+ {
246
+ id: 'powershell',
247
+ extension: 'ps1',
248
+ aliases: [
249
+ 'pwsh'
250
+ ]
251
+ },
252
+ {
253
+ id: 'python',
254
+ extension: 'py',
255
+ aliases: [
256
+ 'python3'
257
+ ]
258
+ },
259
+ {
260
+ id: 'ruby',
261
+ extension: 'rb',
262
+ aliases: []
263
+ },
264
+ {
265
+ id: 'rust',
266
+ extension: 'rs',
267
+ aliases: []
268
+ },
269
+ {
270
+ id: 'shell',
271
+ extension: 'sh',
272
+ aliases: [
273
+ 'bash',
274
+ 'zsh'
275
+ ]
276
+ },
277
+ {
278
+ id: 'sql',
279
+ extension: 'sql',
280
+ aliases: []
281
+ },
282
+ {
283
+ id: 'swift',
284
+ extension: 'swift',
285
+ aliases: []
286
+ },
287
+ {
288
+ id: 'toml',
289
+ extension: 'toml',
290
+ aliases: []
291
+ },
292
+ {
293
+ id: 'yaml',
294
+ extension: 'yaml',
295
+ aliases: [
296
+ 'yml'
297
+ ]
298
+ },
299
+ {
300
+ id: 'zig',
301
+ extension: 'zig',
302
+ aliases: []
303
+ }
304
+ ];
305
+ setDefaults({
306
+ typescript: config$1,
307
+ plaintext: config
308
+ });
309
+
310
+ const configs = {
311
+ typescript: config$1,
312
+ javascript: config$v,
313
+ css: config$u,
314
+ scss: config$t,
315
+ sass: config$s,
316
+ html: config$r,
317
+ svelte: config$q,
318
+ markdown: config$p,
319
+ diff: config$o,
320
+ plaintext: config,
321
+ c: config$n,
322
+ cpp: config$m,
323
+ csharp: config$l,
324
+ dockerfile: config$k,
325
+ go: config$j,
326
+ graphql: config$i,
327
+ hcl: config$h,
328
+ java: config$g,
329
+ json: config$f,
330
+ kotlin: config$e,
331
+ lua: config$d,
332
+ php: config$c,
333
+ powershell: config$b,
334
+ python: config$a,
335
+ ruby: config$9,
336
+ rust: config$8,
337
+ shell: config$7,
338
+ sql: config$6,
339
+ swift: config$5,
340
+ toml: config$4,
341
+ yaml: config$3,
342
+ zig: config$2
343
+ };
344
+
345
+ const languages = allLanguages.map((language)=>{
346
+ const config = configs[language.id];
347
+ if (!config) {
348
+ throw new Error(`Missing parse config for language "${language.id}"`);
349
+ }
350
+ return {
351
+ language,
352
+ config
353
+ };
354
+ });
355
+
356
+ registerLanguages(languages);
package/dist/gpu.d.ts ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * fractalpop core — token model, line assembly, and rendering.
3
+ *
4
+ * Design: tokens are numeric `[type, value]` pairs during lexing (fast Set/array
5
+ * work); the string type names are resolved only at render. Output is an HTML
6
+ * string with no DOM required — so SSR and client produce identical markup.
7
+ */
8
+ /** The stable, ordered token-type list. This list is the theming contract:
9
+ * each type maps to one CSS variable `--fp-<type>` and one class `fp__token--<type>`. */
10
+ declare const TokenTypes: readonly ["identifier", "keyword", "string", "class", "property", "entity", "jsxliterals", "sign", "comment", "break", "space"];
11
+ type TokenType = (typeof TokenTypes)[number];
12
+ interface ParsedToken {
13
+ type: TokenType;
14
+ value: string;
15
+ }
16
+ interface ParsedLine {
17
+ index: number;
18
+ value: string;
19
+ tokens: ParsedToken[];
20
+ annotations: string[];
21
+ }
22
+ interface ParsedCode {
23
+ value: string;
24
+ lines: ParsedLine[];
25
+ }
26
+ /** Mutable token handed to `mark`. Hooks may change className/style/properties. */
27
+ interface MarkToken {
28
+ type: TokenType;
29
+ value: string;
30
+ className: string;
31
+ style: Record<string, string | number>;
32
+ properties: Record<string, string | number | boolean>;
33
+ }
34
+ /** Mutable line handed to `markLine`. Hooks may change className/style/properties. */
35
+ interface MarkLine {
36
+ index: number;
37
+ value: string;
38
+ tokens: ParsedToken[];
39
+ annotations: string[];
40
+ className: string;
41
+ style: Record<string, string | number>;
42
+ properties: Record<string, string | number | boolean>;
43
+ }
44
+ interface DisplayOptions {
45
+ /** Extra class name appended per token type, e.g. `{ keyword: 'font-bold' }`. */
46
+ cx?: Partial<Record<TokenType, string>>;
47
+ /** Mutate a single token before it renders. */
48
+ mark?: (token: MarkToken) => void;
49
+ /** Mutate a whole line before it renders (used for line highlighting). */
50
+ markLine?: (line: MarkLine) => void;
51
+ }
52
+
53
+ /** Parse `code` through the GPU lexer and assemble it into a `ParsedCode` shape. */
54
+ declare function parse(code: string): Promise<ParsedCode>;
55
+ /** Highlight `code` using the GPU lexer, returning an HTML string. */
56
+ declare function highlight(code: string, options?: DisplayOptions): Promise<string>;
57
+
58
+ export { highlight, parse };
59
+ export type { DisplayOptions, ParsedCode };
package/dist/gpu.js ADDED
@@ -0,0 +1,215 @@
1
+ import { parse as parse$1 } from 'gpu-lexer';
2
+
3
+ /**
4
+ * fractalpop core — token model, line assembly, and rendering.
5
+ *
6
+ * Design: tokens are numeric `[type, value]` pairs during lexing (fast Set/array
7
+ * work); the string type names are resolved only at render. Output is an HTML
8
+ * string with no DOM required — so SSR and client produce identical markup.
9
+ */ /** The stable, ordered token-type list. This list is the theming contract:
10
+ * each type maps to one CSS variable `--fp-<type>` and one class `fp__token--<type>`. */ const TokenTypes = [
11
+ 'identifier',
12
+ 'keyword',
13
+ 'string',
14
+ 'class',
15
+ 'property',
16
+ 'entity',
17
+ 'jsxliterals',
18
+ 'sign',
19
+ 'comment',
20
+ 'break',
21
+ 'space'
22
+ ];
23
+ // Numeric indices, used everywhere in the hot path.
24
+ const T_IDENTIFIER = 0;
25
+ const T_KEYWORD = 1;
26
+ const T_STRING = 2;
27
+ const T_CLASS = 3;
28
+ const T_ENTITY = 5;
29
+ const T_SIGN = 7;
30
+ const T_COMMENT = 8;
31
+ const T_BREAK = 9;
32
+ ({
33
+ TokenMap: new Map(TokenTypes.map((type, index)=>[
34
+ type,
35
+ index
36
+ ]))
37
+ });
38
+ /** Split a flat token stream into lines, handling embedded newlines. */ function assemble(value, tokens) {
39
+ const lines = [];
40
+ let lineIndex = 0;
41
+ const lineTokens = [];
42
+ let lastWasBreak = false;
43
+ function flushLine(tokens) {
44
+ lines.push({
45
+ index: lineIndex++,
46
+ value: tokens.map(([, tokenValue])=>tokenValue).join(''),
47
+ tokens: tokens.map(([type, tokenValue])=>({
48
+ type: TokenTypes[type],
49
+ value: tokenValue
50
+ })),
51
+ annotations: []
52
+ });
53
+ }
54
+ for(let index = 0; index < tokens.length; index++){
55
+ const token = tokens[index];
56
+ const [type, tokenValue] = token;
57
+ if (type !== T_BREAK) {
58
+ if (tokenValue.includes('\n')) {
59
+ const values = tokenValue.split('\n');
60
+ for(let part = 0; part < values.length; part++){
61
+ lineTokens.push([
62
+ type,
63
+ values[part]
64
+ ]);
65
+ if (part < values.length - 1) {
66
+ flushLine(lineTokens);
67
+ lineTokens.length = 0;
68
+ }
69
+ }
70
+ } else {
71
+ lineTokens.push(token);
72
+ }
73
+ lastWasBreak = false;
74
+ } else {
75
+ if (lastWasBreak) {
76
+ flushLine([]);
77
+ } else {
78
+ flushLine(lineTokens);
79
+ lineTokens.length = 0;
80
+ }
81
+ if (index === tokens.length - 1) flushLine([]);
82
+ lastWasBreak = true;
83
+ }
84
+ }
85
+ if (lineTokens.length) flushLine(lineTokens);
86
+ return {
87
+ value,
88
+ lines
89
+ };
90
+ }
91
+ function lineClassName(annotations) {
92
+ return `fp__line${annotations.map((annotation)=>` fp__line--${annotation}`).join('')}`;
93
+ }
94
+ function createLine(parsedLine, markLine) {
95
+ const line = {
96
+ index: parsedLine.index,
97
+ value: parsedLine.value,
98
+ tokens: parsedLine.tokens,
99
+ annotations: parsedLine.annotations,
100
+ className: lineClassName(parsedLine.annotations),
101
+ style: {},
102
+ properties: {}
103
+ };
104
+ markLine?.(line);
105
+ return line;
106
+ }
107
+ function createToken({ type, value }, cx, mark) {
108
+ const extraClassName = cx?.[type];
109
+ const token = {
110
+ type,
111
+ value,
112
+ className: `fp__token--${type}${extraClassName ? ` ${extraClassName}` : ''}`,
113
+ style: {
114
+ color: `var(--fp-${type})`
115
+ },
116
+ properties: {}
117
+ };
118
+ mark?.(token);
119
+ return token;
120
+ }
121
+ /** Render parsed lines to an HTML string. Fast path when no display hooks are set. */ function render(parsed, options) {
122
+ const cx = options?.cx;
123
+ const mark = options?.mark;
124
+ const markLine = options?.markLine;
125
+ // Fast path: no per-token object allocation, straight string concat.
126
+ if (!cx && !mark && !markLine) {
127
+ return parsed.lines.map((line)=>{
128
+ const className = lineClassName(line.annotations);
129
+ const children = line.tokens.map(({ type, value })=>`<span class="fp__token--${type}" style="color:var(--fp-${type})">${encode(value)}</span>`).join('');
130
+ return `<span class="${encode(className)}">${children}</span>`;
131
+ }).join('\n');
132
+ }
133
+ // Hook path: build mutable objects and run cx/mark/markLine.
134
+ return parsed.lines.map((parsedLine)=>{
135
+ const line = createLine(parsedLine, markLine);
136
+ const children = parsedLine.tokens.map((parsedToken)=>{
137
+ const token = createToken(parsedToken, cx, mark);
138
+ return `<span ${attributes({
139
+ ...token.properties,
140
+ className: token.className,
141
+ style: token.style
142
+ })}>${encode(token.value)}</span>`;
143
+ }).join('');
144
+ return `<span ${attributes({
145
+ ...line.properties,
146
+ className: line.className,
147
+ style: line.style
148
+ })}>${children}</span>`;
149
+ }).join('\n');
150
+ }
151
+ const entities = {
152
+ '&': '&amp;',
153
+ '<': '&lt;',
154
+ '>': '&gt;',
155
+ '"': '&quot;',
156
+ "'": '&#039;'
157
+ };
158
+ const encode = (value)=>value.replace(/[&<>"']/g, (character)=>entities[character]);
159
+ function attributes(values) {
160
+ const styleValue = values.style ?? {};
161
+ const style = Object.entries(styleValue).map(([key, value])=>`${key.replace(/[A-Z]/g, (match)=>`-${match.toLowerCase()}`)}:${value}`).join(';');
162
+ const properties = Object.entries(values).filter(([key, value])=>/^[\w:-]+$/.test(key) && key !== 'className' && key !== 'style' && value !== false && value != null).map(([key, value])=>value === true ? key : `${key}="${encode(String(value))}"`).join(' ');
163
+ const className = values.className || '';
164
+ return `class="${encode(className)}"${style ? ` style="${encode(style)}"` : ''}${properties ? ` ${properties}` : ''}`;
165
+ }
166
+
167
+ const labelToType = {
168
+ plain: T_IDENTIFIER,
169
+ comment: T_COMMENT,
170
+ string: T_STRING,
171
+ number: T_CLASS,
172
+ keyword: T_KEYWORD,
173
+ type: T_CLASS,
174
+ function: T_ENTITY,
175
+ constant: T_CLASS,
176
+ operator: T_SIGN
177
+ };
178
+ function appendPlain(tokens, value) {
179
+ tokens.push([
180
+ T_IDENTIFIER,
181
+ value
182
+ ]);
183
+ }
184
+ /** Parse `code` through the GPU lexer and assemble it into a `ParsedCode` shape. */ async function parse(code) {
185
+ if (code.length === 0) {
186
+ return {
187
+ value: '',
188
+ lines: []
189
+ };
190
+ }
191
+ const spans = await parse$1(code);
192
+ const tokens = [];
193
+ let position = 0;
194
+ for (const span of spans){
195
+ if (span.start > position) {
196
+ appendPlain(tokens, code.slice(position, span.start));
197
+ }
198
+ const type = labelToType[span.type] ?? T_IDENTIFIER;
199
+ tokens.push([
200
+ type,
201
+ code.slice(span.start, span.end)
202
+ ]);
203
+ position = span.end;
204
+ }
205
+ if (position < code.length) {
206
+ appendPlain(tokens, code.slice(position));
207
+ }
208
+ return assemble(code, tokens);
209
+ }
210
+ /** Highlight `code` using the GPU lexer, returning an HTML string. */ async function highlight(code, options) {
211
+ const parsed = await parse(code);
212
+ return render(parsed, options);
213
+ }
214
+
215
+ export { highlight, parse };