@fuzdev/fuz_code 0.45.0 → 0.46.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 (42) hide show
  1. package/README.md +2 -1
  2. package/dist/Code.svelte +2 -2
  3. package/dist/Code.svelte.d.ts +2 -2
  4. package/dist/CodeHighlight.svelte +4 -4
  5. package/dist/CodeHighlight.svelte.d.ts +3 -3
  6. package/dist/code_sample.d.ts +1 -1
  7. package/dist/code_sample.d.ts.map +1 -1
  8. package/dist/code_sample.js +1 -1
  9. package/dist/grammar_bash.d.ts +17 -0
  10. package/dist/grammar_bash.d.ts.map +1 -0
  11. package/dist/grammar_bash.js +153 -0
  12. package/dist/grammar_markdown.d.ts.map +1 -1
  13. package/dist/grammar_markdown.js +4 -3
  14. package/dist/grammar_markup.d.ts +8 -7
  15. package/dist/grammar_markup.d.ts.map +1 -1
  16. package/dist/grammar_markup.js +8 -7
  17. package/dist/highlight_manager.d.ts +4 -4
  18. package/dist/highlight_manager.js +6 -6
  19. package/dist/svelte_preprocess_fuz_code.d.ts +4 -4
  20. package/dist/svelte_preprocess_fuz_code.d.ts.map +1 -1
  21. package/dist/svelte_preprocess_fuz_code.js +3 -3
  22. package/dist/syntax_styler.d.ts +28 -32
  23. package/dist/syntax_styler.d.ts.map +1 -1
  24. package/dist/syntax_styler.js +32 -36
  25. package/dist/syntax_styler_global.d.ts.map +1 -1
  26. package/dist/syntax_styler_global.js +2 -0
  27. package/dist/syntax_token.d.ts +4 -4
  28. package/dist/syntax_token.js +2 -2
  29. package/dist/tokenize_syntax.d.ts +2 -4
  30. package/dist/tokenize_syntax.d.ts.map +1 -1
  31. package/dist/tokenize_syntax.js +2 -4
  32. package/package.json +27 -31
  33. package/src/lib/code_sample.ts +1 -1
  34. package/src/lib/grammar_bash.ts +175 -0
  35. package/src/lib/grammar_markdown.ts +4 -3
  36. package/src/lib/grammar_markup.ts +8 -7
  37. package/src/lib/highlight_manager.ts +6 -6
  38. package/src/lib/svelte_preprocess_fuz_code.ts +6 -6
  39. package/src/lib/syntax_styler.ts +35 -39
  40. package/src/lib/syntax_styler_global.ts +2 -0
  41. package/src/lib/syntax_token.ts +4 -4
  42. package/src/lib/tokenize_syntax.ts +2 -4
@@ -34,15 +34,14 @@ export declare class SyntaxStyler {
34
34
  * - Custom grammar: `stylize(code, 'ts', customGrammar)` - uses custom grammar but keeps 'ts' label
35
35
  * - Extended grammar: `stylize(code, 'custom', this.extend_grammar('ts', extension))` - new language variant
36
36
  *
37
- * @param text - The source code to syntax highlight.
38
- * @param lang - Language identifier (e.g., 'ts', 'css', 'html'). Used for:
39
- * - Grammar lookup when `grammar` is undefined
40
- * - Hook context (`lang` field passed to hooks)
41
- * - Language identification in output
42
- * @param grammar - Optional custom grammar object. When undefined, automatically
43
- * looks up the grammar via `this.get_lang(lang)`. Provide this to use a custom
44
- * or modified grammar instead of the registered one.
45
- *
37
+ * @param text - the source code to syntax highlight
38
+ * @param lang - language identifier (e.g., 'ts', 'css', 'html'), used for:
39
+ * - grammar lookup when `grammar` is undefined
40
+ * - hook context (`lang` field passed to hooks)
41
+ * - language identification in output
42
+ * @param grammar - optional custom `SyntaxGrammar` object; when undefined, automatically
43
+ * looks up the grammar via `this.get_lang(lang)`; provide this to use a custom
44
+ * or modified grammar instead of the registered one
46
45
  * @returns HTML string with syntax highlighting using CSS classes (`.token_*`)
47
46
  *
48
47
  * @example
@@ -83,7 +82,7 @@ export declare class SyntaxStyler {
83
82
  * };
84
83
  * ```
85
84
  *
86
- * then the `style` token will be added (and processed) at the end. `insert_before` allows you to insert tokens
85
+ * then the `style` token will be added (and processed) at the end. `grammar_insert_before` allows you to insert tokens
87
86
  * before existing tokens. For the CSS example above, you would use it like this:
88
87
  *
89
88
  * ```js
@@ -110,12 +109,12 @@ export declare class SyntaxStyler {
110
109
  *
111
110
  * ## Limitations
112
111
  *
113
- * The main problem `insert_before` has to solve is iteration order. Since ES2015, the iteration order for object
112
+ * The main problem `grammar_insert_before` has to solve is iteration order. Since ES2015, the iteration order for object
114
113
  * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave
115
- * differently when keys are deleted and re-inserted. So `insert_before` can't be implemented by temporarily
114
+ * differently when keys are deleted and re-inserted. So `grammar_insert_before` can't be implemented by temporarily
116
115
  * deleting properties which is necessary to insert at arbitrary positions.
117
116
  *
118
- * To solve this problem, `insert_before` doesn't actually insert the given tokens into the target object.
117
+ * To solve this problem, `grammar_insert_before` doesn't actually insert the given tokens into the target object.
119
118
  * Instead, it will create a new object and replace all references to the target object with the new one. This
120
119
  * can be done without temporarily deleting properties, so the iteration order is well-defined.
121
120
  *
@@ -130,16 +129,13 @@ export declare class SyntaxStyler {
130
129
  * assert(newMarkup === syntax_styler.get_lang('markup'));
131
130
  * ```
132
131
  *
133
- * @param inside - The property of `root` (e.g. a language id in `syntax_styler.langs`) that contains the
134
- * object to be modified.
135
- * @param before - The key to insert before.
136
- * @param insert - An object containing the key-value pairs to be inserted.
137
- * @param root - The object containing `inside`, i.e. the object that contains the
138
- * object to be modified.
139
- *
140
- * Defaults to `syntax_styler.langs`.
141
- *
142
- * @returns the new grammar object
132
+ * @param inside - the property of `root` (e.g. a language id in `syntax_styler.langs`) that contains the
133
+ * object to be modified
134
+ * @param before - the key to insert before
135
+ * @param insert - an object containing the key-value pairs to be inserted
136
+ * @param root - the object containing `inside`, i.e. the object that contains the
137
+ * object to be modified; defaults to `syntax_styler.langs`
138
+ * @returns the new `SyntaxGrammar` object
143
139
  */
144
140
  grammar_insert_before(inside: string, before: string, insert: SyntaxGrammarRaw, root?: Record<string, any>): SyntaxGrammar;
145
141
  /**
@@ -147,9 +143,9 @@ export declare class SyntaxStyler {
147
143
  *
148
144
  * Runs the `wrap` hook on each `SyntaxToken`.
149
145
  *
150
- * @param o - The token or token stream to be converted.
151
- * @param lang - The name of current language.
152
- * @returns The HTML representation of the token or token stream.
146
+ * @param o - the token or `SyntaxTokenStream` to be converted
147
+ * @param lang - the name of current language
148
+ * @returns HTML representation of the token or token stream
153
149
  */
154
150
  stringify_token(o: string | SyntaxToken | SyntaxTokenStream, lang: string): string;
155
151
  /**
@@ -167,9 +163,9 @@ export declare class SyntaxStyler {
167
163
  * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens.
168
164
  * Furthermore, all non-overwriting tokens should be placed after the overwriting ones.
169
165
  *
170
- * @param base_id - The id of the language to extend. This has to be a key in `syntax_styler.langs`.
171
- * @param extension - The new tokens to append.
172
- * @returns the new grammar
166
+ * @param base_id - the id of the language to extend, must be a key in `syntax_styler.langs`
167
+ * @param extension - the new tokens to append
168
+ * @returns the new `SyntaxGrammar`
173
169
  */
174
170
  extend_grammar(base_id: string, extension: SyntaxGrammarRaw): SyntaxGrammar;
175
171
  plugins: Record<string, any>;
@@ -221,13 +217,13 @@ export interface SyntaxGrammarTokenRaw {
221
217
  */
222
218
  alias?: string | Array<string>;
223
219
  /**
224
- * The nested grammar of this token.
220
+ * The nested `SyntaxGrammarRaw` of this token.
225
221
  */
226
222
  inside?: SyntaxGrammarRaw | null;
227
223
  }
228
224
  /**
229
225
  * Grammar token with all properties required.
230
- * This is the normalized representation used at runtime.
226
+ * This is the normalized representation of `SyntaxGrammarTokenRaw` used at runtime.
231
227
  */
232
228
  export interface SyntaxGrammarToken {
233
229
  pattern: RegExp;
@@ -238,7 +234,7 @@ export interface SyntaxGrammarToken {
238
234
  }
239
235
  /**
240
236
  * A grammar after normalization.
241
- * All values are arrays of normalized tokens with consistent shapes.
237
+ * All values are arrays of normalized `SyntaxGrammarToken` with consistent shapes.
242
238
  */
243
239
  export type SyntaxGrammar = Record<string, Array<SyntaxGrammarToken>>;
244
240
  export type HookBeforeTokenizeCallback = (ctx: HookBeforeTokenizeCallbackContext) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"syntax_styler.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/syntax_styler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"syntax_styler.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/syntax_styler.ts"],"names":[],"mappings":"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"}
@@ -79,15 +79,14 @@ export class SyntaxStyler {
79
79
  * - Custom grammar: `stylize(code, 'ts', customGrammar)` - uses custom grammar but keeps 'ts' label
80
80
  * - Extended grammar: `stylize(code, 'custom', this.extend_grammar('ts', extension))` - new language variant
81
81
  *
82
- * @param text - The source code to syntax highlight.
83
- * @param lang - Language identifier (e.g., 'ts', 'css', 'html'). Used for:
84
- * - Grammar lookup when `grammar` is undefined
85
- * - Hook context (`lang` field passed to hooks)
86
- * - Language identification in output
87
- * @param grammar - Optional custom grammar object. When undefined, automatically
88
- * looks up the grammar via `this.get_lang(lang)`. Provide this to use a custom
89
- * or modified grammar instead of the registered one.
90
- *
82
+ * @param text - the source code to syntax highlight
83
+ * @param lang - language identifier (e.g., 'ts', 'css', 'html'), used for:
84
+ * - grammar lookup when `grammar` is undefined
85
+ * - hook context (`lang` field passed to hooks)
86
+ * - language identification in output
87
+ * @param grammar - optional custom `SyntaxGrammar` object; when undefined, automatically
88
+ * looks up the grammar via `this.get_lang(lang)`; provide this to use a custom
89
+ * or modified grammar instead of the registered one
91
90
  * @returns HTML string with syntax highlighting using CSS classes (`.token_*`)
92
91
  *
93
92
  * @example
@@ -140,7 +139,7 @@ export class SyntaxStyler {
140
139
  * };
141
140
  * ```
142
141
  *
143
- * then the `style` token will be added (and processed) at the end. `insert_before` allows you to insert tokens
142
+ * then the `style` token will be added (and processed) at the end. `grammar_insert_before` allows you to insert tokens
144
143
  * before existing tokens. For the CSS example above, you would use it like this:
145
144
  *
146
145
  * ```js
@@ -167,12 +166,12 @@ export class SyntaxStyler {
167
166
  *
168
167
  * ## Limitations
169
168
  *
170
- * The main problem `insert_before` has to solve is iteration order. Since ES2015, the iteration order for object
169
+ * The main problem `grammar_insert_before` has to solve is iteration order. Since ES2015, the iteration order for object
171
170
  * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave
172
- * differently when keys are deleted and re-inserted. So `insert_before` can't be implemented by temporarily
171
+ * differently when keys are deleted and re-inserted. So `grammar_insert_before` can't be implemented by temporarily
173
172
  * deleting properties which is necessary to insert at arbitrary positions.
174
173
  *
175
- * To solve this problem, `insert_before` doesn't actually insert the given tokens into the target object.
174
+ * To solve this problem, `grammar_insert_before` doesn't actually insert the given tokens into the target object.
176
175
  * Instead, it will create a new object and replace all references to the target object with the new one. This
177
176
  * can be done without temporarily deleting properties, so the iteration order is well-defined.
178
177
  *
@@ -187,16 +186,13 @@ export class SyntaxStyler {
187
186
  * assert(newMarkup === syntax_styler.get_lang('markup'));
188
187
  * ```
189
188
  *
190
- * @param inside - The property of `root` (e.g. a language id in `syntax_styler.langs`) that contains the
191
- * object to be modified.
192
- * @param before - The key to insert before.
193
- * @param insert - An object containing the key-value pairs to be inserted.
194
- * @param root - The object containing `inside`, i.e. the object that contains the
195
- * object to be modified.
196
- *
197
- * Defaults to `syntax_styler.langs`.
198
- *
199
- * @returns the new grammar object
189
+ * @param inside - the property of `root` (e.g. a language id in `syntax_styler.langs`) that contains the
190
+ * object to be modified
191
+ * @param before - the key to insert before
192
+ * @param insert - an object containing the key-value pairs to be inserted
193
+ * @param root - the object containing `inside`, i.e. the object that contains the
194
+ * object to be modified; defaults to `syntax_styler.langs`
195
+ * @returns the new `SyntaxGrammar` object
200
196
  */
201
197
  grammar_insert_before(inside, before, insert, root = this.langs) {
202
198
  var grammar = root[inside];
@@ -231,9 +227,9 @@ export class SyntaxStyler {
231
227
  *
232
228
  * Runs the `wrap` hook on each `SyntaxToken`.
233
229
  *
234
- * @param o - The token or token stream to be converted.
235
- * @param lang - The name of current language.
236
- * @returns The HTML representation of the token or token stream.
230
+ * @param o - the token or `SyntaxTokenStream` to be converted
231
+ * @param lang - the name of current language
232
+ * @returns HTML representation of the token or token stream
237
233
  */
238
234
  stringify_token(o, lang) {
239
235
  if (typeof o === 'string') {
@@ -294,9 +290,9 @@ export class SyntaxStyler {
294
290
  * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens.
295
291
  * Furthermore, all non-overwriting tokens should be placed after the overwriting ones.
296
292
  *
297
- * @param base_id - The id of the language to extend. This has to be a key in `syntax_styler.langs`.
298
- * @param extension - The new tokens to append.
299
- * @returns the new grammar
293
+ * @param base_id - the id of the language to extend, must be a key in `syntax_styler.langs`
294
+ * @param extension - the new tokens to append
295
+ * @returns the new `SyntaxGrammar`
300
296
  */
301
297
  extend_grammar(base_id, extension) {
302
298
  // Merge normalized base with un-normalized extension
@@ -307,7 +303,7 @@ export class SyntaxStyler {
307
303
  return extended;
308
304
  }
309
305
  /**
310
- * Normalize a single pattern to have consistent shape.
306
+ * Normalizes a single pattern to have consistent shape.
311
307
  * This ensures all patterns have the same object shape for V8 optimization.
312
308
  */
313
309
  #normalize_pattern(pattern, visited) {
@@ -339,15 +335,15 @@ export class SyntaxStyler {
339
335
  };
340
336
  }
341
337
  /**
342
- * Normalize a grammar to have consistent object shapes.
338
+ * Normalizes a grammar to have consistent object shapes.
343
339
  * This performs several optimizations:
344
- * 1. Merges `rest` property into main grammar
345
- * 2. Ensures all pattern values are arrays
346
- * 3. Normalizes all pattern objects to have consistent shapes
347
- * 4. Adds global flag to greedy patterns
340
+ * 1. Merges `rest` property into main grammar.
341
+ * 2. Ensures all pattern values are arrays.
342
+ * 3. Normalizes all pattern objects to have consistent shapes.
343
+ * 4. Adds global flag to greedy patterns.
348
344
  *
349
345
  * This is called once at registration time to avoid runtime overhead.
350
- * @param visited - Set of grammar object IDs already normalized (for circular references)
346
+ * @param visited - set of grammar object IDs already normalized (for circular references)
351
347
  */
352
348
  #normalize_grammar(grammar, visited) {
353
349
  // Check if we've already normalized this grammar (circular reference)
@@ -1 +1 @@
1
- {"version":3,"file":"syntax_styler_global.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/syntax_styler_global.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAUhD;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,cAAqB,CAAC"}
1
+ {"version":3,"file":"syntax_styler_global.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/syntax_styler_global.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAWhD;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,cAAqB,CAAC"}
@@ -6,6 +6,7 @@ import { add_grammar_js } from './grammar_js.js';
6
6
  import { add_grammar_ts } from './grammar_ts.js';
7
7
  import { add_grammar_svelte } from './grammar_svelte.js';
8
8
  import { add_grammar_json } from './grammar_json.js';
9
+ import { add_grammar_bash } from './grammar_bash.js';
9
10
  import { add_grammar_markdown } from './grammar_markdown.js';
10
11
  /**
11
12
  * Pre-configured `SyntaxStyler` instance with all built-in grammars registered.
@@ -25,4 +26,5 @@ add_grammar_js(syntax_styler_global);
25
26
  add_grammar_ts(syntax_styler_global);
26
27
  add_grammar_svelte(syntax_styler_global);
27
28
  add_grammar_json(syntax_styler_global);
29
+ add_grammar_bash(syntax_styler_global); // before markdown — markdown references bash for fenced code blocks
28
30
  add_grammar_markdown(syntax_styler_global);
@@ -2,13 +2,13 @@ export declare class SyntaxToken {
2
2
  /**
3
3
  * The type of the token.
4
4
  *
5
- * This is usually the key of a pattern in a `Grammar`.
5
+ * This is usually the key of a pattern in a `SyntaxGrammar`.
6
6
  */
7
7
  type: string;
8
8
  /**
9
9
  * The strings or tokens contained by this token.
10
10
  *
11
- * This will be a token stream if the pattern matched also defined an `inside` grammar.
11
+ * This will be a `SyntaxTokenStream` if the pattern matched also defined an `inside` grammar.
12
12
  */
13
13
  content: string | SyntaxTokenStream;
14
14
  /**
@@ -22,8 +22,8 @@ export declare class SyntaxToken {
22
22
  /**
23
23
  * A token stream is an array of strings and `SyntaxToken` objects.
24
24
  *
25
- * Syntax token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process
26
- * them.
25
+ * `SyntaxTokenStream` values have to fulfill a few properties that are assumed by most functions
26
+ * (mostly internal ones) that process them.
27
27
  *
28
28
  * 1. No adjacent strings.
29
29
  * 2. No empty strings.
@@ -2,13 +2,13 @@ export class SyntaxToken {
2
2
  /**
3
3
  * The type of the token.
4
4
  *
5
- * This is usually the key of a pattern in a `Grammar`.
5
+ * This is usually the key of a pattern in a `SyntaxGrammar`.
6
6
  */
7
7
  type;
8
8
  /**
9
9
  * The strings or tokens contained by this token.
10
10
  *
11
- * This will be a token stream if the pattern matched also defined an `inside` grammar.
11
+ * This will be a `SyntaxTokenStream` if the pattern matched also defined an `inside` grammar.
12
12
  */
13
13
  content;
14
14
  /**
@@ -9,11 +9,9 @@ import { type SyntaxTokenStream } from './syntax_token.js';
9
9
  * This method could be useful in other contexts as well, as a very crude parser.
10
10
  *
11
11
  * @param text - a string with the code to be styled
12
- * @param grammar - an object containing the tokens to use
13
- *
12
+ * @param grammar - a `SyntaxGrammar` object containing the tokens to use.
14
13
  * Usually a language definition like `syntax_styler.get_lang('markup')`.
15
- *
16
- * @returns an array of strings and tokens, a token stream
14
+ * @returns a `SyntaxTokenStream` array of strings and tokens
17
15
  *
18
16
  * @example
19
17
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"tokenize_syntax.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/tokenize_syntax.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAc,KAAK,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,SAAS,aAAa,KAAG,iBAQtE,CAAC"}
1
+ {"version":3,"file":"tokenize_syntax.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/tokenize_syntax.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAc,KAAK,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,SAAS,aAAa,KAAG,iBAQtE,CAAC"}
@@ -8,11 +8,9 @@ import { SyntaxToken } from './syntax_token.js';
8
8
  * This method could be useful in other contexts as well, as a very crude parser.
9
9
  *
10
10
  * @param text - a string with the code to be styled
11
- * @param grammar - an object containing the tokens to use
12
- *
11
+ * @param grammar - a `SyntaxGrammar` object containing the tokens to use.
13
12
  * Usually a language definition like `syntax_styler.get_lang('markup')`.
14
- *
15
- * @returns an array of strings and tokens, a token stream
13
+ * @returns a `SyntaxTokenStream` array of strings and tokens
16
14
  *
17
15
  * @example
18
16
  * ```ts
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_code",
3
- "version": "0.45.0",
4
- "description": "syntax styling utilities and components for TypeScript, Svelte, and Markdown",
3
+ "version": "0.46.0",
4
+ "description": "syntax styling utilities and components for TypeScript, Svelte, Markdown, and more",
5
5
  "glyph": "🎨",
6
6
  "logo": "logo.svg",
7
7
  "logo_alt": "a friendly pink spider facing you",
@@ -24,49 +24,45 @@
24
24
  "preview": "vite preview",
25
25
  "deploy": "gro deploy",
26
26
  "benchmark": "gro run benchmark/run_benchmarks.ts",
27
- "benchmark:compare": "gro run benchmark/compare/run_compare.ts",
27
+ "benchmark:save": "gro run benchmark/run_benchmarks.ts --save",
28
+ "benchmark:clean": "rm -f benchmark/baseline.json",
29
+ "benchmark:vs": "gro run benchmark/compare/run_compare.ts",
30
+ "benchmark:vs:write": "gro run benchmark/compare/run_compare.ts --write",
28
31
  "fixtures:update": "gro src/test/fixtures/update"
29
32
  },
30
33
  "type": "module",
31
34
  "engines": {
32
- "node": ">=22.15"
35
+ "node": ">=24.14"
33
36
  },
34
37
  "peerDependencies": {
35
- "@fuzdev/fuz_css": ">=0.47.0",
36
- "@fuzdev/fuz_util": ">=0.49.2",
38
+ "@fuzdev/fuz_css": ">=0.62.0",
39
+ "@fuzdev/fuz_util": ">=0.65.1",
37
40
  "esm-env": "^1",
38
- "magic-string": "^0.30",
39
- "svelte": "^5",
40
- "zimmerframe": "^1"
41
+ "svelte": "^5"
41
42
  },
42
43
  "peerDependenciesMeta": {
43
44
  "@fuzdev/fuz_css": {
44
45
  "optional": true
45
46
  },
46
- "@fuzdev/fuz_util": {
47
- "optional": true
48
- },
49
- "magic-string": {
50
- "optional": true
51
- },
52
47
  "svelte": {
53
48
  "optional": true
54
- },
55
- "zimmerframe": {
56
- "optional": true
57
49
  }
58
50
  },
51
+ "dependencies": {
52
+ "magic-string": "^0.30.21",
53
+ "zimmerframe": "^1.1.4"
54
+ },
59
55
  "devDependencies": {
60
56
  "@changesets/changelog-git": "^0.2.1",
61
- "@fuzdev/fuz_css": "^0.48.0",
62
- "@fuzdev/fuz_ui": "^0.182.1",
63
- "@fuzdev/fuz_util": "^0.50.1",
64
- "@fuzdev/gro": "^0.192.1",
65
- "@jridgewell/trace-mapping": "^0.3.31",
66
- "@ryanatkn/eslint-config": "^0.9.0",
67
- "@ryanatkn/gro": "^0.191.0",
57
+ "@fuzdev/blake3_wasm": "^0.1.1",
58
+ "@fuzdev/fuz_css": "^0.62.0",
59
+ "@fuzdev/fuz_ui": "^0.199.0",
60
+ "@fuzdev/fuz_util": "^0.65.1",
61
+ "@fuzdev/gro": "^0.203.0",
62
+ "@ryanatkn/eslint-config": "^0.12.1",
63
+ "@sveltejs/acorn-typescript": "^1.0.9",
68
64
  "@sveltejs/adapter-static": "^3.0.10",
69
- "@sveltejs/kit": "^2.50.1",
65
+ "@sveltejs/kit": "^2.63.0",
70
66
  "@sveltejs/package": "^2.5.7",
71
67
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
72
68
  "@types/estree": "^1.0.8",
@@ -75,17 +71,17 @@
75
71
  "eslint": "^9.39.1",
76
72
  "eslint-plugin-svelte": "^3.13.1",
77
73
  "esm-env": "^1.2.2",
78
- "magic-string": "^0.30.21",
79
74
  "prettier": "^3.7.4",
80
75
  "prettier-plugin-svelte": "^3.4.1",
81
- "svelte": "^5.49.1",
82
- "svelte-check": "^4.3.6",
83
- "svelte2tsx": "^0.7.47",
76
+ "svelte": "^5.56.2",
77
+ "svelte-check": "^4.6.0",
78
+ "svelte-docinfo": "^0.3.0",
79
+ "svelte2tsx": "^0.7.55",
84
80
  "tslib": "^2.8.1",
85
81
  "typescript": "^5.9.3",
86
82
  "typescript-eslint": "^8.48.1",
83
+ "vite": "^7.3.1",
87
84
  "vitest": "^4.0.15",
88
- "zimmerframe": "^1.1.4",
89
85
  "zod": "^4.3.6"
90
86
  },
91
87
  "prettier": {
@@ -5,6 +5,6 @@ export interface CodeSample {
5
5
  }
6
6
 
7
7
  // Languages ordered from simple to complex
8
- export const sample_langs = ['json', 'css', 'ts', 'html', 'svelte', 'md'] as const;
8
+ export const sample_langs = ['json', 'css', 'ts', 'html', 'svelte', 'md', 'bash'] as const;
9
9
 
10
10
  export type SampleLang = (typeof sample_langs)[number];
@@ -0,0 +1,175 @@
1
+ import type {AddSyntaxGrammar, SyntaxGrammarRaw} from './syntax_styler.js';
2
+
3
+ /**
4
+ * Bash/shell grammar for syntax highlighting.
5
+ *
6
+ * Standalone grammar (no base extension). Covers core bash syntax:
7
+ * comments, strings, variables, functions, keywords, builtins,
8
+ * operators, and redirections.
9
+ *
10
+ * Based on Prism (https://github.com/PrismJS/prism)
11
+ * by Lea Verou (https://lea.verou.me/)
12
+ *
13
+ * MIT license
14
+ *
15
+ * @see LICENSE
16
+ */
17
+ export const add_grammar_bash: AddSyntaxGrammar = (syntax_styler) => {
18
+ // Shared inside grammar for command substitution — `rest` wired after construction
19
+ const command_sub_inside: SyntaxGrammarRaw = {
20
+ punctuation: /^\$\(|\)$/,
21
+ };
22
+
23
+ // Reusable balanced-paren pattern for $(...) — handles 2 levels of inner () nesting,
24
+ // which supports up to 3 levels of $() command substitution (4+ is vanishingly rare)
25
+ const command_sub_pattern = /\$\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\)/;
26
+
27
+ const grammar_bash = {
28
+ // Shebang at file start — matched before general comments
29
+ shebang: {
30
+ pattern: /^#!.*/,
31
+ alias: 'comment',
32
+ },
33
+
34
+ // Line comments — require whitespace or start-of-string before #
35
+ comment: {
36
+ pattern: /(^|\s)#.*/,
37
+ lookbehind: true,
38
+ greedy: true,
39
+ },
40
+
41
+ // Here-documents — must precede string to avoid delimiter consumption
42
+ heredoc: [
43
+ // Quoted delimiter (<<'DELIM' or <<"DELIM") — no expansion
44
+ {
45
+ pattern: /(^|[^<])<<-?\s*(?:['"])(\w+)(?:['"])[\t ]*\n[\s\S]*?\n[\t ]*\2(?=\s*$)/m,
46
+ lookbehind: true,
47
+ greedy: true,
48
+ alias: 'string',
49
+ inside: {
50
+ // No `m` flag — `^` matches start-of-string (opening) and `$` matches
51
+ // end-of-string (closing), so single-word content lines can't false-positive
52
+ heredoc_delimiter: [
53
+ {
54
+ pattern: /^<<-?\s*(?:['"])\w+(?:['"])/,
55
+ alias: 'punctuation',
56
+ },
57
+ {
58
+ pattern: /\w+$/,
59
+ alias: 'punctuation',
60
+ },
61
+ ],
62
+ } as SyntaxGrammarRaw,
63
+ },
64
+ // Unquoted delimiter (<<DELIM) — with variable/command expansion
65
+ {
66
+ pattern: /(^|[^<])<<-?\s*(\w+)[\t ]*\n[\s\S]*?\n[\t ]*\2(?=\s*$)/m,
67
+ lookbehind: true,
68
+ greedy: true,
69
+ alias: 'string',
70
+ inside: {
71
+ heredoc_delimiter: [
72
+ {
73
+ pattern: /^<<-?\s*\w+/,
74
+ alias: 'punctuation',
75
+ },
76
+ {
77
+ pattern: /\w+$/,
78
+ alias: 'punctuation',
79
+ },
80
+ ],
81
+ command_substitution: {
82
+ pattern: command_sub_pattern,
83
+ greedy: true,
84
+ inside: command_sub_inside,
85
+ },
86
+ variable: /\$\{[^}]+\}|\$(?:\w+|[!@#$*?\-0-9])/,
87
+ } as SyntaxGrammarRaw,
88
+ },
89
+ ],
90
+
91
+ // Strings — three variants
92
+ string: [
93
+ // Double-quoted: supports escape sequences, variable interpolation, command substitution
94
+ {
95
+ pattern:
96
+ /(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\)|\$(?!\()|[^"\\$])*"/,
97
+ lookbehind: true,
98
+ greedy: true,
99
+ inside: {
100
+ command_substitution: {
101
+ pattern: command_sub_pattern,
102
+ greedy: true,
103
+ inside: command_sub_inside,
104
+ },
105
+ variable: /\$\{[^}]+\}|\$(?:\w+|[!@#$*?\-0-9])/,
106
+ } as SyntaxGrammarRaw,
107
+ },
108
+ // Single-quoted: completely literal
109
+ {
110
+ pattern: /(^|[^\\](?:\\\\)*)'[^']*'/,
111
+ lookbehind: true,
112
+ greedy: true,
113
+ },
114
+ // ANSI-C quoting: $'...' with C-style escapes
115
+ {
116
+ pattern: /\$'(?:[^'\\]|\\[\s\S])*'/,
117
+ greedy: true,
118
+ },
119
+ ],
120
+
121
+ // Command substitution $(...) — before variable since both start with $
122
+ command_substitution: {
123
+ pattern: command_sub_pattern,
124
+ greedy: true,
125
+ inside: command_sub_inside,
126
+ },
127
+
128
+ // Variables and parameter expansion
129
+ variable: /\$\{[^}]+\}|\$(?:\w+|[!@#$*?\-0-9])/,
130
+
131
+ // Function definitions — both styles
132
+ function: [
133
+ // function fname style
134
+ {
135
+ pattern: /(\bfunction\s+)\w+/,
136
+ lookbehind: true,
137
+ },
138
+ // fname() style
139
+ {
140
+ pattern: /\b\w+(?=\s*\(\s*\))/,
141
+ },
142
+ ],
143
+
144
+ // Shell keywords
145
+ keyword:
146
+ /\b(?:if|then|else|elif|fi|for|while|until|do|done|case|esac|in|select|function|return|local|export|declare|typeset|readonly|unset|set|shift|trap|break|continue|coproc|time)\b/,
147
+
148
+ // Builtin commands
149
+ builtin:
150
+ /\b(?:echo|printf|cd|pwd|read|test|source|eval|exec|exit|getopts|hash|type|ulimit|umask|wait|kill|jobs|bg|fg|disown|alias|unalias|command|shopt)\b/,
151
+
152
+ // Boolean commands
153
+ boolean: /\b(?:true|false)\b/,
154
+
155
+ // File descriptors before redirections — must precede number
156
+ file_descriptor: {
157
+ pattern: /\B&\d\b|\b\d(?=>>?|<)/,
158
+ alias: 'important',
159
+ },
160
+
161
+ // Numbers: hex, octal, base-N, decimal
162
+ number: /\b(?:0x[\da-fA-F]+|0[0-7]+|\d+#[\da-zA-Z]+|\d+)\b/,
163
+
164
+ // Operators — longest first
165
+ operator: /\|\||&&|;;|&>>?|<<<?|>>?|=~|[!=]=|[<>]|[|&!]/,
166
+
167
+ // Punctuation
168
+ punctuation: /[{}[\]();,]/,
169
+ } satisfies SyntaxGrammarRaw;
170
+
171
+ // Wire circular reference so command substitutions get full bash highlighting
172
+ command_sub_inside.rest = grammar_bash;
173
+
174
+ syntax_styler.add_lang('bash', grammar_bash, ['sh', 'shell']);
175
+ };