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
@@ -0,0 +1,108 @@
1
+ import * as __core_js from './core.js';
2
+ import { ParseOptions } from './core.js';
3
+
4
+ /** Mutable registry that maps a canonical language id to its parse config. */
5
+
6
+ declare function getLanguageConfig(id: string): ParseOptions | undefined;
7
+ declare function resetLanguageConfigRegistry(): void;
8
+
9
+ /** Mutable language metadata registry with alias/extension normalization. */
10
+
11
+ interface Language {
12
+ id: string;
13
+ extension: string;
14
+ aliases: readonly string[];
15
+ }
16
+ declare function registerLanguage(language: Language, config?: ParseOptions): void;
17
+ declare function setDefaults(languages: readonly Language[]): void;
18
+ declare function setDefaults(configs: Record<string, ParseOptions>): void;
19
+ declare function importDefaults(ids: string[]): Promise<void>;
20
+ /** Find canonical language metadata by name, alias, or extension. */
21
+ declare function findLanguage(name: string): Language | undefined;
22
+ /** Resolve a name/alias/extension to its canonical language id. */
23
+ declare function lang(name: string): string | undefined;
24
+ /** Alias for {@link lang}. */
25
+ declare const canonicalizeLang: typeof lang;
26
+ declare function getRegisteredLanguages(): readonly Language[];
27
+ declare function resetLanguageRegistry(): void;
28
+
29
+ declare const allLanguages: readonly Language[];
30
+
31
+ /**
32
+ * fractalpop core — token model, line assembly, and rendering.
33
+ *
34
+ * Design: tokens are numeric `[type, value]` pairs during lexing (fast Set/array
35
+ * work); the string type names are resolved only at render. Output is an HTML
36
+ * string with no DOM required — so SSR and client produce identical markup.
37
+ */
38
+ /** The stable, ordered token-type list. This list is the theming contract:
39
+ * each type maps to one CSS variable `--fp-<type>` and one class `fp__token--<type>`. */
40
+ declare const TokenTypes: readonly ["identifier", "keyword", "string", "class", "property", "entity", "jsxliterals", "sign", "comment", "break", "space"];
41
+ type TokenType = (typeof TokenTypes)[number];
42
+ interface ParsedToken {
43
+ type: TokenType;
44
+ value: string;
45
+ }
46
+ /** Mutable token handed to `mark`. Hooks may change className/style/properties. */
47
+ interface MarkToken {
48
+ type: TokenType;
49
+ value: string;
50
+ className: string;
51
+ style: Record<string, string | number>;
52
+ properties: Record<string, string | number | boolean>;
53
+ }
54
+ /** Mutable line handed to `markLine`. Hooks may change className/style/properties. */
55
+ interface MarkLine {
56
+ index: number;
57
+ value: string;
58
+ tokens: ParsedToken[];
59
+ annotations: string[];
60
+ className: string;
61
+ style: Record<string, string | number>;
62
+ properties: Record<string, string | number | boolean>;
63
+ }
64
+ interface DisplayOptions {
65
+ /** Extra class name appended per token type, e.g. `{ keyword: 'font-bold' }`. */
66
+ cx?: Partial<Record<TokenType, string>>;
67
+ /** Mutate a single token before it renders. */
68
+ mark?: (token: MarkToken) => void;
69
+ /** Mutate a whole line before it renders (used for line highlighting). */
70
+ markLine?: (line: MarkLine) => void;
71
+ }
72
+
73
+ /** Highlight range: either a single 1-based line or an inclusive [start, end] pair. */
74
+ type HighlightRange = number | [number, number];
75
+ /**
76
+ * Parse `{1,3-5,7}` fence metadata into a Set of 1-based line numbers.
77
+ *
78
+ * Tolerates whitespace (`{ 1 , 3 - 5 }`) and silently ignores invalid or
79
+ * negative numbers.
80
+ */
81
+ declare function parseHighlightMeta(meta?: string | null): Set<number>;
82
+ /**
83
+ * Convert `{1,3-5,7}` fence metadata into remark-compatible highlight ranges.
84
+ *
85
+ * Returns single numbers for individual lines and `[start, end]` tuples for
86
+ * explicit ranges. Invalid/negative numbers are ignored.
87
+ */
88
+ declare function toHighlightRanges(meta?: string | null): HighlightRange[];
89
+ /** Escape characters Svelte's compiler would otherwise interpret in markup. */
90
+ declare function escapeSvelte(html: string): string;
91
+
92
+ interface HighlightOptions extends DisplayOptions {
93
+ /** Language id, extension, or alias. Defaults to 'typescript'. */
94
+ lang?: string;
95
+ /** Explicit parse config that overrides the registry. */
96
+ config?: __core_js.ParseOptions;
97
+ }
98
+ interface LanguagePair {
99
+ language: Language;
100
+ config: __core_js.ParseOptions;
101
+ }
102
+ /** Register multiple languages with their parse configs. */
103
+ declare function registerLanguages(languages: readonly LanguagePair[]): void;
104
+ /** Highlight `code` to an HTML string. No DOM required. */
105
+ declare function highlight(code: string, options?: HighlightOptions): string;
106
+
107
+ export { allLanguages, canonicalizeLang, escapeSvelte, findLanguage, getLanguageConfig, getRegisteredLanguages, highlight, importDefaults, lang, parseHighlightMeta, registerLanguage, registerLanguages, resetLanguageConfigRegistry, resetLanguageRegistry, setDefaults, toHighlightRanges };
108
+ export type { DisplayOptions, HighlightOptions, HighlightRange, LanguagePair, MarkLine, MarkToken, HighlightOptions as Options, TokenType };
package/dist/index.js ADDED
@@ -0,0 +1,523 @@
1
+ import { parse } from './core.js';
2
+ import { config as config$1 } from './lang/typescript.js';
3
+ import { config } from './lang/plaintext.js';
4
+
5
+ /**
6
+ * fractalpop core — token model, line assembly, and rendering.
7
+ *
8
+ * Design: tokens are numeric `[type, value]` pairs during lexing (fast Set/array
9
+ * work); the string type names are resolved only at render. Output is an HTML
10
+ * string with no DOM required — so SSR and client produce identical markup.
11
+ */ /** The stable, ordered token-type list. This list is the theming contract:
12
+ * each type maps to one CSS variable `--fp-<type>` and one class `fp__token--<type>`. */ const TokenTypes = [
13
+ 'identifier',
14
+ 'keyword',
15
+ 'string',
16
+ 'class',
17
+ 'property',
18
+ 'entity',
19
+ 'jsxliterals',
20
+ 'sign',
21
+ 'comment',
22
+ 'break',
23
+ 'space'
24
+ ];
25
+ ({
26
+ TokenMap: new Map(TokenTypes.map((type, index)=>[
27
+ type,
28
+ index
29
+ ]))
30
+ });
31
+ function lineClassName(annotations) {
32
+ return `fp__line${annotations.map((annotation)=>` fp__line--${annotation}`).join('')}`;
33
+ }
34
+ function createLine(parsedLine, markLine) {
35
+ const line = {
36
+ index: parsedLine.index,
37
+ value: parsedLine.value,
38
+ tokens: parsedLine.tokens,
39
+ annotations: parsedLine.annotations,
40
+ className: lineClassName(parsedLine.annotations),
41
+ style: {},
42
+ properties: {}
43
+ };
44
+ markLine?.(line);
45
+ return line;
46
+ }
47
+ function createToken({ type, value }, cx, mark) {
48
+ const extraClassName = cx?.[type];
49
+ const token = {
50
+ type,
51
+ value,
52
+ className: `fp__token--${type}${extraClassName ? ` ${extraClassName}` : ''}`,
53
+ style: {
54
+ color: `var(--fp-${type})`
55
+ },
56
+ properties: {}
57
+ };
58
+ mark?.(token);
59
+ return token;
60
+ }
61
+ /** Render parsed lines to an HTML string. Fast path when no display hooks are set. */ function render(parsed, options) {
62
+ const cx = options?.cx;
63
+ const mark = options?.mark;
64
+ const markLine = options?.markLine;
65
+ // Fast path: no per-token object allocation, straight string concat.
66
+ if (!cx && !mark && !markLine) {
67
+ return parsed.lines.map((line)=>{
68
+ const className = lineClassName(line.annotations);
69
+ const children = line.tokens.map(({ type, value })=>`<span class="fp__token--${type}" style="color:var(--fp-${type})">${encode(value)}</span>`).join('');
70
+ return `<span class="${encode(className)}">${children}</span>`;
71
+ }).join('\n');
72
+ }
73
+ // Hook path: build mutable objects and run cx/mark/markLine.
74
+ return parsed.lines.map((parsedLine)=>{
75
+ const line = createLine(parsedLine, markLine);
76
+ const children = parsedLine.tokens.map((parsedToken)=>{
77
+ const token = createToken(parsedToken, cx, mark);
78
+ return `<span ${attributes({
79
+ ...token.properties,
80
+ className: token.className,
81
+ style: token.style
82
+ })}>${encode(token.value)}</span>`;
83
+ }).join('');
84
+ return `<span ${attributes({
85
+ ...line.properties,
86
+ className: line.className,
87
+ style: line.style
88
+ })}>${children}</span>`;
89
+ }).join('\n');
90
+ }
91
+ const entities = {
92
+ '&': '&amp;',
93
+ '<': '&lt;',
94
+ '>': '&gt;',
95
+ '"': '&quot;',
96
+ "'": '&#039;'
97
+ };
98
+ const encode = (value)=>value.replace(/[&<>"']/g, (character)=>entities[character]);
99
+ function attributes(values) {
100
+ const styleValue = values.style ?? {};
101
+ const style = Object.entries(styleValue).map(([key, value])=>`${key.replace(/[A-Z]/g, (match)=>`-${match.toLowerCase()}`)}:${value}`).join(';');
102
+ 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(' ');
103
+ const className = values.className || '';
104
+ return `class="${encode(className)}"${style ? ` style="${encode(style)}"` : ''}${properties ? ` ${properties}` : ''}`;
105
+ }
106
+
107
+ /** Mutable registry that maps a canonical language id to its parse config. */ const configRegistry = new Map();
108
+ function registerLanguageConfig(id, config) {
109
+ configRegistry.set(id, config);
110
+ }
111
+ function getLanguageConfig(id) {
112
+ return configRegistry.get(id);
113
+ }
114
+ function resetLanguageConfigRegistry() {
115
+ configRegistry.clear();
116
+ }
117
+
118
+ const languageRegistry = new Map();
119
+ function normalizeLanguageName(value) {
120
+ return value.trim().toLowerCase().replace(/^\./, '');
121
+ }
122
+ function registerName(name, language) {
123
+ const normalized = normalizeLanguageName(name);
124
+ if (!normalized) return;
125
+ const existing = languageRegistry.get(normalized);
126
+ if (existing && existing.id !== language.id) {
127
+ throw new Error(`Language name "${normalized}" is shared by "${existing.id}" and "${language.id}"`);
128
+ }
129
+ languageRegistry.set(normalized, language);
130
+ }
131
+ function registerLanguage(language, config) {
132
+ const names = new Set([
133
+ language.id,
134
+ language.extension,
135
+ ...language.aliases
136
+ ]);
137
+ for (const name of names){
138
+ registerName(name, language);
139
+ }
140
+ if (config) {
141
+ registerLanguageConfig(language.id, config);
142
+ }
143
+ }
144
+ function setDefaults(input) {
145
+ resetLanguageRegistry();
146
+ resetLanguageConfigRegistry();
147
+ if (Array.isArray(input)) {
148
+ for (const language of input){
149
+ registerLanguage(language);
150
+ }
151
+ } else {
152
+ for (const [id, config] of Object.entries(input)){
153
+ const language = allLanguages.find((l)=>l.id === id);
154
+ if (language) {
155
+ registerLanguage(language, config);
156
+ } else {
157
+ registerLanguage({
158
+ id,
159
+ extension: id,
160
+ aliases: []
161
+ }, config);
162
+ }
163
+ }
164
+ }
165
+ }
166
+ const configImporters = {
167
+ javascript: ()=>import('./lang/javascript.js'),
168
+ typescript: ()=>import('./lang/typescript.js'),
169
+ css: ()=>import('./lang/css.js'),
170
+ scss: ()=>import('./lang/scss.js'),
171
+ sass: ()=>import('./lang/sass.js'),
172
+ html: ()=>import('./lang/html.js'),
173
+ svelte: ()=>import('./lang/svelte.js'),
174
+ markdown: ()=>import('./lang/markdown.js'),
175
+ diff: ()=>import('./lang/diff.js'),
176
+ plaintext: ()=>import('./lang/plaintext.js'),
177
+ c: ()=>import('./lang/c.js'),
178
+ cpp: ()=>import('./lang/cpp.js'),
179
+ csharp: ()=>import('./lang/csharp.js'),
180
+ dockerfile: ()=>import('./lang/dockerfile.js'),
181
+ go: ()=>import('./lang/go.js'),
182
+ graphql: ()=>import('./lang/graphql.js'),
183
+ hcl: ()=>import('./lang/hcl.js'),
184
+ java: ()=>import('./lang/java.js'),
185
+ json: ()=>import('./lang/json.js'),
186
+ kotlin: ()=>import('./lang/kotlin.js'),
187
+ lua: ()=>import('./lang/lua.js'),
188
+ php: ()=>import('./lang/php.js'),
189
+ powershell: ()=>import('./lang/powershell.js'),
190
+ python: ()=>import('./lang/python.js'),
191
+ ruby: ()=>import('./lang/ruby.js'),
192
+ rust: ()=>import('./lang/rust.js'),
193
+ shell: ()=>import('./lang/shell.js'),
194
+ sql: ()=>import('./lang/sql.js'),
195
+ swift: ()=>import('./lang/swift.js'),
196
+ toml: ()=>import('./lang/toml.js'),
197
+ yaml: ()=>import('./lang/yaml.js'),
198
+ zig: ()=>import('./lang/zig.js')
199
+ };
200
+ async function importDefaults(ids) {
201
+ await Promise.all(ids.map(async (id)=>{
202
+ const importer = configImporters[id];
203
+ if (!importer) return;
204
+ const { config } = await importer();
205
+ const language = allLanguages.find((l)=>l.id === id);
206
+ if (language) {
207
+ registerLanguage(language, config);
208
+ } else {
209
+ registerLanguage({
210
+ id,
211
+ extension: id,
212
+ aliases: []
213
+ }, config);
214
+ }
215
+ }));
216
+ }
217
+ /** Find canonical language metadata by name, alias, or extension. */ function findLanguage(name) {
218
+ if (typeof name !== 'string') return undefined;
219
+ return languageRegistry.get(normalizeLanguageName(name));
220
+ }
221
+ /** Resolve a name/alias/extension to its canonical language id. */ function lang(name) {
222
+ return findLanguage(name)?.id;
223
+ }
224
+ /** Alias for {@link lang}. */ const canonicalizeLang = lang;
225
+ function getRegisteredLanguages() {
226
+ return [
227
+ ...new Set(languageRegistry.values())
228
+ ];
229
+ }
230
+ function resetLanguageRegistry() {
231
+ languageRegistry.clear();
232
+ }
233
+ const allLanguages = [
234
+ {
235
+ id: 'javascript',
236
+ extension: 'js',
237
+ aliases: [
238
+ 'jsx',
239
+ 'node'
240
+ ]
241
+ },
242
+ {
243
+ id: 'typescript',
244
+ extension: 'ts',
245
+ aliases: [
246
+ 'tsx'
247
+ ]
248
+ },
249
+ {
250
+ id: 'css',
251
+ extension: 'css',
252
+ aliases: []
253
+ },
254
+ {
255
+ id: 'scss',
256
+ extension: 'scss',
257
+ aliases: []
258
+ },
259
+ {
260
+ id: 'sass',
261
+ extension: 'sass',
262
+ aliases: [
263
+ 'indented-sass'
264
+ ]
265
+ },
266
+ {
267
+ id: 'html',
268
+ extension: 'html',
269
+ aliases: [
270
+ 'htm',
271
+ 'xml'
272
+ ]
273
+ },
274
+ {
275
+ id: 'svelte',
276
+ extension: 'svelte',
277
+ aliases: []
278
+ },
279
+ {
280
+ id: 'markdown',
281
+ extension: 'md',
282
+ aliases: [
283
+ 'md',
284
+ 'mdx',
285
+ 'svx'
286
+ ]
287
+ },
288
+ {
289
+ id: 'diff',
290
+ extension: 'diff',
291
+ aliases: [
292
+ 'patch'
293
+ ]
294
+ },
295
+ {
296
+ id: 'plaintext',
297
+ extension: 'txt',
298
+ aliases: [
299
+ 'text',
300
+ 'plain'
301
+ ]
302
+ },
303
+ {
304
+ id: 'c',
305
+ extension: 'c',
306
+ aliases: []
307
+ },
308
+ {
309
+ id: 'cpp',
310
+ extension: 'cpp',
311
+ aliases: [
312
+ 'c++',
313
+ 'cc',
314
+ 'cxx'
315
+ ]
316
+ },
317
+ {
318
+ id: 'csharp',
319
+ extension: 'cs',
320
+ aliases: [
321
+ 'c#',
322
+ 'dotnet'
323
+ ]
324
+ },
325
+ {
326
+ id: 'dockerfile',
327
+ extension: 'dockerfile',
328
+ aliases: [
329
+ 'docker'
330
+ ]
331
+ },
332
+ {
333
+ id: 'go',
334
+ extension: 'go',
335
+ aliases: [
336
+ 'golang'
337
+ ]
338
+ },
339
+ {
340
+ id: 'graphql',
341
+ extension: 'graphql',
342
+ aliases: [
343
+ 'gql'
344
+ ]
345
+ },
346
+ {
347
+ id: 'hcl',
348
+ extension: 'hcl',
349
+ aliases: [
350
+ 'terraform',
351
+ 'tf'
352
+ ]
353
+ },
354
+ {
355
+ id: 'java',
356
+ extension: 'java',
357
+ aliases: []
358
+ },
359
+ {
360
+ id: 'json',
361
+ extension: 'json',
362
+ aliases: [
363
+ 'jsonc'
364
+ ]
365
+ },
366
+ {
367
+ id: 'kotlin',
368
+ extension: 'kt',
369
+ aliases: [
370
+ 'kts'
371
+ ]
372
+ },
373
+ {
374
+ id: 'lua',
375
+ extension: 'lua',
376
+ aliases: []
377
+ },
378
+ {
379
+ id: 'php',
380
+ extension: 'php',
381
+ aliases: []
382
+ },
383
+ {
384
+ id: 'powershell',
385
+ extension: 'ps1',
386
+ aliases: [
387
+ 'pwsh'
388
+ ]
389
+ },
390
+ {
391
+ id: 'python',
392
+ extension: 'py',
393
+ aliases: [
394
+ 'python3'
395
+ ]
396
+ },
397
+ {
398
+ id: 'ruby',
399
+ extension: 'rb',
400
+ aliases: []
401
+ },
402
+ {
403
+ id: 'rust',
404
+ extension: 'rs',
405
+ aliases: []
406
+ },
407
+ {
408
+ id: 'shell',
409
+ extension: 'sh',
410
+ aliases: [
411
+ 'bash',
412
+ 'zsh'
413
+ ]
414
+ },
415
+ {
416
+ id: 'sql',
417
+ extension: 'sql',
418
+ aliases: []
419
+ },
420
+ {
421
+ id: 'swift',
422
+ extension: 'swift',
423
+ aliases: []
424
+ },
425
+ {
426
+ id: 'toml',
427
+ extension: 'toml',
428
+ aliases: []
429
+ },
430
+ {
431
+ id: 'yaml',
432
+ extension: 'yaml',
433
+ aliases: [
434
+ 'yml'
435
+ ]
436
+ },
437
+ {
438
+ id: 'zig',
439
+ extension: 'zig',
440
+ aliases: []
441
+ }
442
+ ];
443
+ setDefaults({
444
+ typescript: config$1,
445
+ plaintext: config
446
+ });
447
+
448
+ /** Highlight range: either a single 1-based line or an inclusive [start, end] pair. */ function parseMetaParts(meta) {
449
+ const match = meta?.match(/\{([^}]*)\}/);
450
+ return match ? match[1].split(',') : undefined;
451
+ }
452
+ /**
453
+ * Parse `{1,3-5,7}` fence metadata into a Set of 1-based line numbers.
454
+ *
455
+ * Tolerates whitespace (`{ 1 , 3 - 5 }`) and silently ignores invalid or
456
+ * negative numbers.
457
+ */ function parseHighlightMeta(meta) {
458
+ const lines = new Set();
459
+ const parts = parseMetaParts(meta);
460
+ if (!parts) return lines;
461
+ for (const part of parts){
462
+ const range = part.trim();
463
+ if (!range) continue;
464
+ if (range.includes('-')) {
465
+ const [start, end] = range.split('-').map((n)=>Number(n.trim()));
466
+ if (Number.isFinite(start) && Number.isFinite(end) && start > 0 && end >= start) {
467
+ for(let i = start; i <= end; i++)lines.add(i);
468
+ }
469
+ } else {
470
+ const n = Number(range);
471
+ if (Number.isFinite(n) && n > 0) lines.add(n);
472
+ }
473
+ }
474
+ return lines;
475
+ }
476
+ /**
477
+ * Convert `{1,3-5,7}` fence metadata into remark-compatible highlight ranges.
478
+ *
479
+ * Returns single numbers for individual lines and `[start, end]` tuples for
480
+ * explicit ranges. Invalid/negative numbers are ignored.
481
+ */ function toHighlightRanges(meta) {
482
+ const out = [];
483
+ const parts = parseMetaParts(meta);
484
+ if (!parts) return out;
485
+ for (const part of parts){
486
+ const range = part.trim();
487
+ if (!range) continue;
488
+ if (range.includes('-')) {
489
+ const [start, end] = range.split('-').map((n)=>Number(n.trim()));
490
+ if (Number.isFinite(start) && Number.isFinite(end) && start > 0 && end >= start) {
491
+ out.push([
492
+ start,
493
+ end
494
+ ]);
495
+ }
496
+ } else {
497
+ const n = Number(range);
498
+ if (Number.isFinite(n) && n > 0) out.push(n);
499
+ }
500
+ }
501
+ return out;
502
+ }
503
+ /** Escape characters Svelte's compiler would otherwise interpret in markup. */ function escapeSvelte(html) {
504
+ return html.replace(/\{/g, '&#123;').replace(/\}/g, '&#125;').replace(/`/g, '&#96;');
505
+ }
506
+
507
+ /** Register multiple languages with their parse configs. */ function registerLanguages(languages) {
508
+ for (const { language, config } of languages){
509
+ registerLanguage(language, config);
510
+ }
511
+ }
512
+ /** Highlight `code` to an HTML string. No DOM required. */ function highlight(code, options) {
513
+ const { lang, config, cx, mark, markLine } = options || {};
514
+ const resolvedConfig = config ?? (lang ? getLanguageConfig(canonicalizeLang(lang) ?? lang) : undefined) ?? getLanguageConfig('typescript') ?? {};
515
+ const parsed = parse(code, resolvedConfig);
516
+ return render(parsed, {
517
+ cx,
518
+ mark,
519
+ markLine
520
+ });
521
+ }
522
+
523
+ export { allLanguages, canonicalizeLang, escapeSvelte, findLanguage, getLanguageConfig, getRegisteredLanguages, highlight, importDefaults, lang, parseHighlightMeta, registerLanguage, registerLanguages, resetLanguageConfigRegistry, resetLanguageRegistry, setDefaults, toHighlightRanges };
@@ -0,0 +1,5 @@
1
+ import { ParseOptions } from '../core.js';
2
+
3
+ declare const config: ParseOptions;
4
+
5
+ export { config };