@fuzdev/fuz_code 0.44.1 → 0.45.1
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 +1 -1
- package/dist/code_sample.d.ts +1 -1
- package/dist/code_sample.d.ts.map +1 -1
- package/dist/code_sample.js +1 -1
- package/dist/grammar_bash.d.ts +17 -0
- package/dist/grammar_bash.d.ts.map +1 -0
- package/dist/grammar_bash.js +153 -0
- package/dist/grammar_markdown.d.ts.map +1 -1
- package/dist/grammar_markdown.js +1 -0
- package/dist/highlight_manager.d.ts +9 -1
- package/dist/highlight_manager.d.ts.map +1 -1
- package/dist/highlight_manager.js +9 -1
- package/dist/highlight_priorities.gen.d.ts +1 -1
- package/dist/highlight_priorities.gen.d.ts.map +1 -1
- package/dist/svelte_preprocess_fuz_code.d.ts +20 -0
- package/dist/svelte_preprocess_fuz_code.d.ts.map +1 -1
- package/dist/svelte_preprocess_fuz_code.js +17 -0
- package/dist/syntax_styler.d.ts +6 -0
- package/dist/syntax_styler.d.ts.map +1 -1
- package/dist/syntax_styler.js +6 -0
- package/dist/syntax_styler_global.d.ts +10 -0
- package/dist/syntax_styler_global.d.ts.map +1 -1
- package/dist/syntax_styler_global.js +12 -0
- package/dist/tokenize_syntax.d.ts +2 -0
- package/dist/tokenize_syntax.d.ts.map +1 -1
- package/dist/tokenize_syntax.js +2 -0
- package/package.json +11 -7
- package/src/lib/code_sample.ts +1 -1
- package/src/lib/grammar_bash.ts +175 -0
- package/src/lib/grammar_markdown.ts +1 -0
- package/src/lib/highlight_manager.ts +9 -1
- package/src/lib/highlight_priorities.gen.ts +1 -1
- package/src/lib/svelte_preprocess_fuz_code.ts +20 -0
- package/src/lib/syntax_styler.ts +6 -0
- package/src/lib/syntax_styler_global.ts +12 -0
- package/src/lib/tokenize_syntax.ts +2 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[<img src="static/logo.svg" alt="a friendly pink spider facing you" align="right" width="192" height="192">](https://code.fuz.dev/)
|
|
4
4
|
|
|
5
|
-
> syntax styling utilities and components for TypeScript, Svelte, and
|
|
5
|
+
> syntax styling utilities and components for TypeScript, Svelte, Markdown, and more 🎨
|
|
6
6
|
|
|
7
7
|
**[code.fuz.dev](https://code.fuz.dev/)**
|
|
8
8
|
|
package/dist/code_sample.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export interface CodeSample {
|
|
|
3
3
|
lang: string;
|
|
4
4
|
content: string;
|
|
5
5
|
}
|
|
6
|
-
export declare const sample_langs: readonly ["json", "css", "ts", "html", "svelte", "md"];
|
|
6
|
+
export declare const sample_langs: readonly ["json", "css", "ts", "html", "svelte", "md", "bash"];
|
|
7
7
|
export type SampleLang = (typeof sample_langs)[number];
|
|
8
8
|
//# sourceMappingURL=code_sample.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code_sample.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/code_sample.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAGD,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"code_sample.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/code_sample.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAGD,eAAO,MAAM,YAAY,gEAAiE,CAAC;AAE3F,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/code_sample.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Languages ordered from simple to complex
|
|
2
|
-
export const sample_langs = ['json', 'css', 'ts', 'html', 'svelte', 'md'];
|
|
2
|
+
export const sample_langs = ['json', 'css', 'ts', 'html', 'svelte', 'md', 'bash'];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AddSyntaxGrammar } from './syntax_styler.js';
|
|
2
|
+
/**
|
|
3
|
+
* Bash/shell grammar for syntax highlighting.
|
|
4
|
+
*
|
|
5
|
+
* Standalone grammar (no base extension). Covers core bash syntax:
|
|
6
|
+
* comments, strings, variables, functions, keywords, builtins,
|
|
7
|
+
* operators, and redirections.
|
|
8
|
+
*
|
|
9
|
+
* Based on Prism (https://github.com/PrismJS/prism)
|
|
10
|
+
* by Lea Verou (https://lea.verou.me/)
|
|
11
|
+
*
|
|
12
|
+
* MIT license
|
|
13
|
+
*
|
|
14
|
+
* @see LICENSE
|
|
15
|
+
*/
|
|
16
|
+
export declare const add_grammar_bash: AddSyntaxGrammar;
|
|
17
|
+
//# sourceMappingURL=grammar_bash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grammar_bash.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/grammar_bash.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAmB,MAAM,oBAAoB,CAAC;AAE3E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBA8J9B,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bash/shell grammar for syntax highlighting.
|
|
3
|
+
*
|
|
4
|
+
* Standalone grammar (no base extension). Covers core bash syntax:
|
|
5
|
+
* comments, strings, variables, functions, keywords, builtins,
|
|
6
|
+
* operators, and redirections.
|
|
7
|
+
*
|
|
8
|
+
* Based on Prism (https://github.com/PrismJS/prism)
|
|
9
|
+
* by Lea Verou (https://lea.verou.me/)
|
|
10
|
+
*
|
|
11
|
+
* MIT license
|
|
12
|
+
*
|
|
13
|
+
* @see LICENSE
|
|
14
|
+
*/
|
|
15
|
+
export const add_grammar_bash = (syntax_styler) => {
|
|
16
|
+
// Shared inside grammar for command substitution — `rest` wired after construction
|
|
17
|
+
const command_sub_inside = {
|
|
18
|
+
punctuation: /^\$\(|\)$/,
|
|
19
|
+
};
|
|
20
|
+
// Reusable balanced-paren pattern for $(...) — handles 2 levels of inner () nesting,
|
|
21
|
+
// which supports up to 3 levels of $() command substitution (4+ is vanishingly rare)
|
|
22
|
+
const command_sub_pattern = /\$\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\)/;
|
|
23
|
+
const grammar_bash = {
|
|
24
|
+
// Shebang at file start — matched before general comments
|
|
25
|
+
shebang: {
|
|
26
|
+
pattern: /^#!.*/,
|
|
27
|
+
alias: 'comment',
|
|
28
|
+
},
|
|
29
|
+
// Line comments — require whitespace or start-of-string before #
|
|
30
|
+
comment: {
|
|
31
|
+
pattern: /(^|\s)#.*/,
|
|
32
|
+
lookbehind: true,
|
|
33
|
+
greedy: true,
|
|
34
|
+
},
|
|
35
|
+
// Here-documents — must precede string to avoid delimiter consumption
|
|
36
|
+
heredoc: [
|
|
37
|
+
// Quoted delimiter (<<'DELIM' or <<"DELIM") — no expansion
|
|
38
|
+
{
|
|
39
|
+
pattern: /(^|[^<])<<-?\s*(?:['"])(\w+)(?:['"])[\t ]*\n[\s\S]*?\n[\t ]*\2(?=\s*$)/m,
|
|
40
|
+
lookbehind: true,
|
|
41
|
+
greedy: true,
|
|
42
|
+
alias: 'string',
|
|
43
|
+
inside: {
|
|
44
|
+
// No `m` flag — `^` matches start-of-string (opening) and `$` matches
|
|
45
|
+
// end-of-string (closing), so single-word content lines can't false-positive
|
|
46
|
+
heredoc_delimiter: [
|
|
47
|
+
{
|
|
48
|
+
pattern: /^<<-?\s*(?:['"])\w+(?:['"])/,
|
|
49
|
+
alias: 'punctuation',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
pattern: /\w+$/,
|
|
53
|
+
alias: 'punctuation',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
// Unquoted delimiter (<<DELIM) — with variable/command expansion
|
|
59
|
+
{
|
|
60
|
+
pattern: /(^|[^<])<<-?\s*(\w+)[\t ]*\n[\s\S]*?\n[\t ]*\2(?=\s*$)/m,
|
|
61
|
+
lookbehind: true,
|
|
62
|
+
greedy: true,
|
|
63
|
+
alias: 'string',
|
|
64
|
+
inside: {
|
|
65
|
+
heredoc_delimiter: [
|
|
66
|
+
{
|
|
67
|
+
pattern: /^<<-?\s*\w+/,
|
|
68
|
+
alias: 'punctuation',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
pattern: /\w+$/,
|
|
72
|
+
alias: 'punctuation',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
command_substitution: {
|
|
76
|
+
pattern: command_sub_pattern,
|
|
77
|
+
greedy: true,
|
|
78
|
+
inside: command_sub_inside,
|
|
79
|
+
},
|
|
80
|
+
variable: /\$\{[^}]+\}|\$(?:\w+|[!@#$*?\-0-9])/,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
// Strings — three variants
|
|
85
|
+
string: [
|
|
86
|
+
// Double-quoted: supports escape sequences, variable interpolation, command substitution
|
|
87
|
+
{
|
|
88
|
+
pattern: /(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\)|\$(?!\()|[^"\\$])*"/,
|
|
89
|
+
lookbehind: true,
|
|
90
|
+
greedy: true,
|
|
91
|
+
inside: {
|
|
92
|
+
command_substitution: {
|
|
93
|
+
pattern: command_sub_pattern,
|
|
94
|
+
greedy: true,
|
|
95
|
+
inside: command_sub_inside,
|
|
96
|
+
},
|
|
97
|
+
variable: /\$\{[^}]+\}|\$(?:\w+|[!@#$*?\-0-9])/,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
// Single-quoted: completely literal
|
|
101
|
+
{
|
|
102
|
+
pattern: /(^|[^\\](?:\\\\)*)'[^']*'/,
|
|
103
|
+
lookbehind: true,
|
|
104
|
+
greedy: true,
|
|
105
|
+
},
|
|
106
|
+
// ANSI-C quoting: $'...' with C-style escapes
|
|
107
|
+
{
|
|
108
|
+
pattern: /\$'(?:[^'\\]|\\[\s\S])*'/,
|
|
109
|
+
greedy: true,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
// Command substitution $(...) — before variable since both start with $
|
|
113
|
+
command_substitution: {
|
|
114
|
+
pattern: command_sub_pattern,
|
|
115
|
+
greedy: true,
|
|
116
|
+
inside: command_sub_inside,
|
|
117
|
+
},
|
|
118
|
+
// Variables and parameter expansion
|
|
119
|
+
variable: /\$\{[^}]+\}|\$(?:\w+|[!@#$*?\-0-9])/,
|
|
120
|
+
// Function definitions — both styles
|
|
121
|
+
function: [
|
|
122
|
+
// function fname style
|
|
123
|
+
{
|
|
124
|
+
pattern: /(\bfunction\s+)\w+/,
|
|
125
|
+
lookbehind: true,
|
|
126
|
+
},
|
|
127
|
+
// fname() style
|
|
128
|
+
{
|
|
129
|
+
pattern: /\b\w+(?=\s*\(\s*\))/,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
// Shell keywords
|
|
133
|
+
keyword: /\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/,
|
|
134
|
+
// Builtin commands
|
|
135
|
+
builtin: /\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/,
|
|
136
|
+
// Boolean commands
|
|
137
|
+
boolean: /\b(?:true|false)\b/,
|
|
138
|
+
// File descriptors before redirections — must precede number
|
|
139
|
+
file_descriptor: {
|
|
140
|
+
pattern: /\B&\d\b|\b\d(?=>>?|<)/,
|
|
141
|
+
alias: 'important',
|
|
142
|
+
},
|
|
143
|
+
// Numbers: hex, octal, base-N, decimal
|
|
144
|
+
number: /\b(?:0x[\da-fA-F]+|0[0-7]+|\d+#[\da-zA-Z]+|\d+)\b/,
|
|
145
|
+
// Operators — longest first
|
|
146
|
+
operator: /\|\||&&|;;|&>>?|<<<?|>>?|=~|[!=]=|[<>]|[|&!]/,
|
|
147
|
+
// Punctuation
|
|
148
|
+
punctuation: /[{}[\]();,]/,
|
|
149
|
+
};
|
|
150
|
+
// Wire circular reference so command substitutions get full bash highlighting
|
|
151
|
+
command_sub_inside.rest = grammar_bash;
|
|
152
|
+
syntax_styler.add_lang('bash', grammar_bash, ['sh', 'shell']);
|
|
153
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grammar_markdown.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/grammar_markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,gBAAgB,EAIhB,MAAM,oBAAoB,CAAC;AAsF5B;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"grammar_markdown.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/grammar_markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,gBAAgB,EAIhB,MAAM,oBAAoB,CAAC;AAsF5B;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,gBAiMlC,CAAC"}
|
package/dist/grammar_markdown.js
CHANGED
|
@@ -69,6 +69,7 @@ export const add_grammar_markdown = (syntax_styler) => {
|
|
|
69
69
|
{ aliases: ['html', 'markup'], id: 'markup' },
|
|
70
70
|
{ aliases: ['json'], id: 'json' },
|
|
71
71
|
{ aliases: ['svelte'], id: 'svelte' },
|
|
72
|
+
{ aliases: ['bash', 'sh', 'shell'], id: 'bash' },
|
|
72
73
|
];
|
|
73
74
|
// Fence types: higher counts first (for proper precedence in tokenization)
|
|
74
75
|
const fence_types = [
|
|
@@ -5,8 +5,16 @@ export type HighlightMode = 'auto' | 'ranges' | 'html';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare const supports_css_highlight_api: () => boolean;
|
|
7
7
|
/**
|
|
8
|
-
* Manages
|
|
8
|
+
* Manages CSS Custom Highlight API ranges for a single element.
|
|
9
9
|
* Tracks ranges per element and only removes its own ranges when clearing.
|
|
10
|
+
*
|
|
11
|
+
* **Experimental** — limited browser support. Use `Code` for production.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const manager = new HighlightManager();
|
|
16
|
+
* manager.highlight_from_syntax_tokens(element, tokens);
|
|
17
|
+
* ```
|
|
10
18
|
*/
|
|
11
19
|
export declare class HighlightManager {
|
|
12
20
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"highlight_manager.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/highlight_manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAGzD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,0BAA0B,QAAO,OACS,CAAC;AAExD
|
|
1
|
+
{"version":3,"file":"highlight_manager.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/highlight_manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAGzD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,0BAA0B,QAAO,OACS,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAgB;;IAC5B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;;IAS1C;;OAEG;IACH,4BAA4B,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAkD/E;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAmB5B,OAAO,IAAI,IAAI;CAiFf"}
|
|
@@ -4,8 +4,16 @@ import { highlight_priorities } from './highlight_priorities.js';
|
|
|
4
4
|
*/
|
|
5
5
|
export const supports_css_highlight_api = () => !!(globalThis.CSS?.highlights && globalThis.Highlight); // eslint-disable-line @typescript-eslint/no-unnecessary-condition
|
|
6
6
|
/**
|
|
7
|
-
* Manages
|
|
7
|
+
* Manages CSS Custom Highlight API ranges for a single element.
|
|
8
8
|
* Tracks ranges per element and only removes its own ranges when clearing.
|
|
9
|
+
*
|
|
10
|
+
* **Experimental** — limited browser support. Use `Code` for production.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const manager = new HighlightManager();
|
|
15
|
+
* manager.highlight_from_syntax_tokens(element, tokens);
|
|
16
|
+
* ```
|
|
9
17
|
*/
|
|
10
18
|
export class HighlightManager {
|
|
11
19
|
element_ranges;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"highlight_priorities.gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/highlight_priorities.gen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"highlight_priorities.gen.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/highlight_priorities.gen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,aAAa,CAAC;AAKrC,cAAc;AACd,eAAO,MAAM,GAAG,EAAE,GAgEjB,CAAC"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { type PreprocessorGroup } from 'svelte/compiler';
|
|
2
2
|
import type { SyntaxStyler } from './syntax_styler.js';
|
|
3
|
+
/**
|
|
4
|
+
* Options for `svelte_preprocess_fuz_code`.
|
|
5
|
+
*/
|
|
3
6
|
export interface PreprocessFuzCodeOptions {
|
|
4
7
|
/** File patterns to exclude. */
|
|
5
8
|
exclude?: Array<string | RegExp>;
|
|
@@ -20,5 +23,22 @@ export interface PreprocessFuzCodeOptions {
|
|
|
20
23
|
*/
|
|
21
24
|
on_error?: 'log' | 'throw';
|
|
22
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Svelte preprocessor that compiles static `Code` component content at build time,
|
|
28
|
+
* replacing runtime syntax highlighting with pre-rendered HTML.
|
|
29
|
+
*
|
|
30
|
+
* @param options preprocessor configuration
|
|
31
|
+
* @returns a Svelte preprocessor group
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* // svelte.config.js
|
|
36
|
+
* import {svelte_preprocess_fuz_code} from './svelte_preprocess_fuz_code.js';
|
|
37
|
+
*
|
|
38
|
+
* export default {
|
|
39
|
+
* preprocess: [svelte_preprocess_fuz_code(), vitePreprocess()],
|
|
40
|
+
* };
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
23
43
|
export declare const svelte_preprocess_fuz_code: (options?: PreprocessFuzCodeOptions) => PreprocessorGroup;
|
|
24
44
|
//# sourceMappingURL=svelte_preprocess_fuz_code.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svelte_preprocess_fuz_code.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/svelte_preprocess_fuz_code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,iBAAiB,EAAW,MAAM,iBAAiB,CAAC;AAgBxE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,wBAAwB;IACxC,gCAAgC;IAChC,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAEjC,0DAA0D;IAC1D,aAAa,CAAC,EAAE,YAAY,CAAC;IAE7B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAElC;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;CAC3B;AAED,eAAO,MAAM,0BAA0B,GACtC,UAAS,wBAA6B,KACpC,iBA6DF,CAAC"}
|
|
1
|
+
{"version":3,"file":"svelte_preprocess_fuz_code.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/svelte_preprocess_fuz_code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,iBAAiB,EAAW,MAAM,iBAAiB,CAAC;AAgBxE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,gCAAgC;IAChC,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAEjC,0DAA0D;IAC1D,aAAa,CAAC,EAAE,YAAY,CAAC;IAE7B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAElC;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B,GACtC,UAAS,wBAA6B,KACpC,iBA6DF,CAAC"}
|
|
@@ -5,6 +5,23 @@ import { should_exclude_path } from '@fuzdev/fuz_util/path.js';
|
|
|
5
5
|
import { escape_js_string } from '@fuzdev/fuz_util/string.js';
|
|
6
6
|
import { find_attribute, extract_static_string, try_extract_conditional_chain, build_static_bindings, resolve_component_names, handle_preprocess_error, } from '@fuzdev/fuz_util/svelte_preprocess_helpers.js';
|
|
7
7
|
import { syntax_styler_global } from './syntax_styler_global.js';
|
|
8
|
+
/**
|
|
9
|
+
* Svelte preprocessor that compiles static `Code` component content at build time,
|
|
10
|
+
* replacing runtime syntax highlighting with pre-rendered HTML.
|
|
11
|
+
*
|
|
12
|
+
* @param options preprocessor configuration
|
|
13
|
+
* @returns a Svelte preprocessor group
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* // svelte.config.js
|
|
18
|
+
* import {svelte_preprocess_fuz_code} from './svelte_preprocess_fuz_code.js';
|
|
19
|
+
*
|
|
20
|
+
* export default {
|
|
21
|
+
* preprocess: [svelte_preprocess_fuz_code(), vitePreprocess()],
|
|
22
|
+
* };
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
8
25
|
export const svelte_preprocess_fuz_code = (options = {}) => {
|
|
9
26
|
const { exclude = [], syntax_styler = syntax_styler_global, cache = true, component_imports = ['@fuzdev/fuz_code/Code.svelte'], on_error = process.env.CI === 'true' ? 'throw' : 'log', } = options;
|
|
10
27
|
// In-memory cache: content+lang hash → highlighted HTML
|
package/dist/syntax_styler.d.ts
CHANGED
|
@@ -46,18 +46,24 @@ export declare class SyntaxStyler {
|
|
|
46
46
|
* @returns HTML string with syntax highlighting using CSS classes (`.token_*`)
|
|
47
47
|
*
|
|
48
48
|
* @example
|
|
49
|
+
* ```ts
|
|
49
50
|
* // Standard usage - uses registered grammar
|
|
50
51
|
* stylize('var foo = true;', 'ts');
|
|
52
|
+
* ```
|
|
51
53
|
*
|
|
52
54
|
* @example
|
|
55
|
+
* ```ts
|
|
53
56
|
* // Custom grammar - overrides registered grammar
|
|
54
57
|
* const customGrammar = { keyword: [...], string: [...] };
|
|
55
58
|
* stylize('var foo = false;', 'ts', customGrammar);
|
|
59
|
+
* ```
|
|
56
60
|
*
|
|
57
61
|
* @example
|
|
62
|
+
* ```ts
|
|
58
63
|
* // Extended grammar - builds on existing grammar
|
|
59
64
|
* const extended = this.extend_grammar('ts', { customToken: [...] });
|
|
60
65
|
* stylize('var foo = 42;', 'ts-extended', extended);
|
|
66
|
+
* ```
|
|
61
67
|
*/
|
|
62
68
|
stylize(text: string, lang: string, grammar?: SyntaxGrammar | undefined): string;
|
|
63
69
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syntax_styler.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/syntax_styler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,KAAK,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAGtE,MAAM,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC;AAErE;;;;;;;GAOG;AACH,qBAAa,YAAY;;IACxB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC,CAE9C;IAkBF,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI;IAc9E,iBAAiB,CAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,gBAAgB,EAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GACrB,aAAa;IAahB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa;IAQnC
|
|
1
|
+
{"version":3,"file":"syntax_styler.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/syntax_styler.ts"],"names":[],"mappings":"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"}
|
package/dist/syntax_styler.js
CHANGED
|
@@ -91,18 +91,24 @@ export class SyntaxStyler {
|
|
|
91
91
|
* @returns HTML string with syntax highlighting using CSS classes (`.token_*`)
|
|
92
92
|
*
|
|
93
93
|
* @example
|
|
94
|
+
* ```ts
|
|
94
95
|
* // Standard usage - uses registered grammar
|
|
95
96
|
* stylize('var foo = true;', 'ts');
|
|
97
|
+
* ```
|
|
96
98
|
*
|
|
97
99
|
* @example
|
|
100
|
+
* ```ts
|
|
98
101
|
* // Custom grammar - overrides registered grammar
|
|
99
102
|
* const customGrammar = { keyword: [...], string: [...] };
|
|
100
103
|
* stylize('var foo = false;', 'ts', customGrammar);
|
|
104
|
+
* ```
|
|
101
105
|
*
|
|
102
106
|
* @example
|
|
107
|
+
* ```ts
|
|
103
108
|
* // Extended grammar - builds on existing grammar
|
|
104
109
|
* const extended = this.extend_grammar('ts', { customToken: [...] });
|
|
105
110
|
* stylize('var foo = 42;', 'ts-extended', extended);
|
|
111
|
+
* ```
|
|
106
112
|
*/
|
|
107
113
|
stylize(text, lang, grammar = this.get_lang(lang)) {
|
|
108
114
|
var ctx = {
|
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
import { SyntaxStyler } from './syntax_styler.js';
|
|
2
|
+
/**
|
|
3
|
+
* Pre-configured `SyntaxStyler` instance with all built-in grammars registered.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* import {syntax_styler_global} from './syntax_styler_global.js';
|
|
8
|
+
*
|
|
9
|
+
* const html = syntax_styler_global.stylize('const x = 1;', 'ts');
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
2
12
|
export declare const syntax_styler_global: SyntaxStyler;
|
|
3
13
|
//# sourceMappingURL=syntax_styler_global.d.ts.map
|
|
@@ -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;
|
|
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,7 +6,18 @@ 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';
|
|
11
|
+
/**
|
|
12
|
+
* Pre-configured `SyntaxStyler` instance with all built-in grammars registered.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import {syntax_styler_global} from './syntax_styler_global.js';
|
|
17
|
+
*
|
|
18
|
+
* const html = syntax_styler_global.stylize('const x = 1;', 'ts');
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
10
21
|
export const syntax_styler_global = new SyntaxStyler();
|
|
11
22
|
add_grammar_markup(syntax_styler_global);
|
|
12
23
|
add_grammar_css(syntax_styler_global);
|
|
@@ -15,4 +26,5 @@ add_grammar_js(syntax_styler_global);
|
|
|
15
26
|
add_grammar_ts(syntax_styler_global);
|
|
16
27
|
add_grammar_svelte(syntax_styler_global);
|
|
17
28
|
add_grammar_json(syntax_styler_global);
|
|
29
|
+
add_grammar_bash(syntax_styler_global); // before markdown — markdown references bash for fenced code blocks
|
|
18
30
|
add_grammar_markdown(syntax_styler_global);
|
|
@@ -16,6 +16,7 @@ import { type SyntaxTokenStream } from './syntax_token.js';
|
|
|
16
16
|
* @returns an array of strings and tokens, a token stream
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
|
+
* ```ts
|
|
19
20
|
* var code = `var foo = 0;`;
|
|
20
21
|
* var tokens = tokenize_syntax(code, SyntaxStyler.langs.js);
|
|
21
22
|
* for (var token of tokens) {
|
|
@@ -23,6 +24,7 @@ import { type SyntaxTokenStream } from './syntax_token.js';
|
|
|
23
24
|
* console.log(`Found numeric literal: ${token.content}`);
|
|
24
25
|
* }
|
|
25
26
|
* }
|
|
27
|
+
* ```
|
|
26
28
|
*/
|
|
27
29
|
export declare const tokenize_syntax: (text: string, grammar: SyntaxGrammar) => SyntaxTokenStream;
|
|
28
30
|
//# sourceMappingURL=tokenize_syntax.d.ts.map
|
|
@@ -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
|
|
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"}
|
package/dist/tokenize_syntax.js
CHANGED
|
@@ -15,6 +15,7 @@ import { SyntaxToken } from './syntax_token.js';
|
|
|
15
15
|
* @returns an array of strings and tokens, a token stream
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
|
+
* ```ts
|
|
18
19
|
* var code = `var foo = 0;`;
|
|
19
20
|
* var tokens = tokenize_syntax(code, SyntaxStyler.langs.js);
|
|
20
21
|
* for (var token of tokens) {
|
|
@@ -22,6 +23,7 @@ import { SyntaxToken } from './syntax_token.js';
|
|
|
22
23
|
* console.log(`Found numeric literal: ${token.content}`);
|
|
23
24
|
* }
|
|
24
25
|
* }
|
|
26
|
+
* ```
|
|
25
27
|
*/
|
|
26
28
|
export const tokenize_syntax = (text, grammar) => {
|
|
27
29
|
// Grammar is already normalized (rest merged, patterns in arrays, etc.)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuzdev/fuz_code",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "syntax styling utilities and components for TypeScript, Svelte, and
|
|
3
|
+
"version": "0.45.1",
|
|
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",
|
|
@@ -58,15 +58,17 @@
|
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@changesets/changelog-git": "^0.2.1",
|
|
61
|
-
"@fuzdev/fuz_css": "^0.
|
|
62
|
-
"@fuzdev/fuz_ui": "^0.
|
|
63
|
-
"@fuzdev/fuz_util": "^0.
|
|
61
|
+
"@fuzdev/fuz_css": "^0.50.0",
|
|
62
|
+
"@fuzdev/fuz_ui": "^0.183.1",
|
|
63
|
+
"@fuzdev/fuz_util": "^0.51.0",
|
|
64
|
+
"@fuzdev/gro": "^0.194.0",
|
|
65
|
+
"@jridgewell/trace-mapping": "^0.3.31",
|
|
64
66
|
"@ryanatkn/eslint-config": "^0.9.0",
|
|
65
|
-
"@ryanatkn/gro": "^0.191.0",
|
|
66
67
|
"@sveltejs/adapter-static": "^3.0.10",
|
|
67
68
|
"@sveltejs/kit": "^2.50.1",
|
|
68
69
|
"@sveltejs/package": "^2.5.7",
|
|
69
70
|
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
|
71
|
+
"@types/estree": "^1.0.8",
|
|
70
72
|
"@types/node": "^24.10.1",
|
|
71
73
|
"@webref/css": "^8.2.0",
|
|
72
74
|
"eslint": "^9.39.1",
|
|
@@ -77,11 +79,13 @@
|
|
|
77
79
|
"prettier-plugin-svelte": "^3.4.1",
|
|
78
80
|
"svelte": "^5.49.1",
|
|
79
81
|
"svelte-check": "^4.3.6",
|
|
82
|
+
"svelte2tsx": "^0.7.47",
|
|
80
83
|
"tslib": "^2.8.1",
|
|
81
84
|
"typescript": "^5.9.3",
|
|
82
85
|
"typescript-eslint": "^8.48.1",
|
|
83
86
|
"vitest": "^4.0.15",
|
|
84
|
-
"zimmerframe": "^1.1.4"
|
|
87
|
+
"zimmerframe": "^1.1.4",
|
|
88
|
+
"zod": "^4.3.6"
|
|
85
89
|
},
|
|
86
90
|
"prettier": {
|
|
87
91
|
"plugins": [
|
package/src/lib/code_sample.ts
CHANGED
|
@@ -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
|
+
};
|
|
@@ -103,6 +103,7 @@ export const add_grammar_markdown: AddSyntaxGrammar = (syntax_styler) => {
|
|
|
103
103
|
{aliases: ['html', 'markup'], id: 'markup'},
|
|
104
104
|
{aliases: ['json'], id: 'json'},
|
|
105
105
|
{aliases: ['svelte'], id: 'svelte'},
|
|
106
|
+
{aliases: ['bash', 'sh', 'shell'], id: 'bash'},
|
|
106
107
|
];
|
|
107
108
|
|
|
108
109
|
// Fence types: higher counts first (for proper precedence in tokenization)
|
|
@@ -10,8 +10,16 @@ export const supports_css_highlight_api = (): boolean =>
|
|
|
10
10
|
!!(globalThis.CSS?.highlights && globalThis.Highlight); // eslint-disable-line @typescript-eslint/no-unnecessary-condition
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Manages
|
|
13
|
+
* Manages CSS Custom Highlight API ranges for a single element.
|
|
14
14
|
* Tracks ranges per element and only removes its own ranges when clearing.
|
|
15
|
+
*
|
|
16
|
+
* **Experimental** — limited browser support. Use `Code` for production.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const manager = new HighlightManager();
|
|
21
|
+
* manager.highlight_from_syntax_tokens(element, tokens);
|
|
22
|
+
* ```
|
|
15
23
|
*/
|
|
16
24
|
export class HighlightManager {
|
|
17
25
|
element_ranges: Map<string, Array<Range>>;
|
|
@@ -16,6 +16,9 @@ import {
|
|
|
16
16
|
import {syntax_styler_global} from './syntax_styler_global.js';
|
|
17
17
|
import type {SyntaxStyler} from './syntax_styler.js';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Options for `svelte_preprocess_fuz_code`.
|
|
21
|
+
*/
|
|
19
22
|
export interface PreprocessFuzCodeOptions {
|
|
20
23
|
/** File patterns to exclude. */
|
|
21
24
|
exclude?: Array<string | RegExp>;
|
|
@@ -41,6 +44,23 @@ export interface PreprocessFuzCodeOptions {
|
|
|
41
44
|
on_error?: 'log' | 'throw';
|
|
42
45
|
}
|
|
43
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Svelte preprocessor that compiles static `Code` component content at build time,
|
|
49
|
+
* replacing runtime syntax highlighting with pre-rendered HTML.
|
|
50
|
+
*
|
|
51
|
+
* @param options preprocessor configuration
|
|
52
|
+
* @returns a Svelte preprocessor group
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* // svelte.config.js
|
|
57
|
+
* import {svelte_preprocess_fuz_code} from '@fuzdev/fuz_code/svelte_preprocess_fuz_code.js';
|
|
58
|
+
*
|
|
59
|
+
* export default {
|
|
60
|
+
* preprocess: [svelte_preprocess_fuz_code(), vitePreprocess()],
|
|
61
|
+
* };
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
44
64
|
export const svelte_preprocess_fuz_code = (
|
|
45
65
|
options: PreprocessFuzCodeOptions = {},
|
|
46
66
|
): PreprocessorGroup => {
|
package/src/lib/syntax_styler.ts
CHANGED
|
@@ -104,18 +104,24 @@ export class SyntaxStyler {
|
|
|
104
104
|
* @returns HTML string with syntax highlighting using CSS classes (`.token_*`)
|
|
105
105
|
*
|
|
106
106
|
* @example
|
|
107
|
+
* ```ts
|
|
107
108
|
* // Standard usage - uses registered grammar
|
|
108
109
|
* stylize('var foo = true;', 'ts');
|
|
110
|
+
* ```
|
|
109
111
|
*
|
|
110
112
|
* @example
|
|
113
|
+
* ```ts
|
|
111
114
|
* // Custom grammar - overrides registered grammar
|
|
112
115
|
* const customGrammar = { keyword: [...], string: [...] };
|
|
113
116
|
* stylize('var foo = false;', 'ts', customGrammar);
|
|
117
|
+
* ```
|
|
114
118
|
*
|
|
115
119
|
* @example
|
|
120
|
+
* ```ts
|
|
116
121
|
* // Extended grammar - builds on existing grammar
|
|
117
122
|
* const extended = this.extend_grammar('ts', { customToken: [...] });
|
|
118
123
|
* stylize('var foo = 42;', 'ts-extended', extended);
|
|
124
|
+
* ```
|
|
119
125
|
*/
|
|
120
126
|
stylize(
|
|
121
127
|
text: string,
|
|
@@ -6,8 +6,19 @@ 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
|
|
|
12
|
+
/**
|
|
13
|
+
* Pre-configured `SyntaxStyler` instance with all built-in grammars registered.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import {syntax_styler_global} from '@fuzdev/fuz_code/syntax_styler_global.js';
|
|
18
|
+
*
|
|
19
|
+
* const html = syntax_styler_global.stylize('const x = 1;', 'ts');
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
11
22
|
export const syntax_styler_global = new SyntaxStyler();
|
|
12
23
|
|
|
13
24
|
add_grammar_markup(syntax_styler_global);
|
|
@@ -17,4 +28,5 @@ add_grammar_js(syntax_styler_global);
|
|
|
17
28
|
add_grammar_ts(syntax_styler_global);
|
|
18
29
|
add_grammar_svelte(syntax_styler_global);
|
|
19
30
|
add_grammar_json(syntax_styler_global);
|
|
31
|
+
add_grammar_bash(syntax_styler_global); // before markdown — markdown references bash for fenced code blocks
|
|
20
32
|
add_grammar_markdown(syntax_styler_global);
|
|
@@ -17,6 +17,7 @@ import {SyntaxToken, type SyntaxTokenStream} from './syntax_token.js';
|
|
|
17
17
|
* @returns an array of strings and tokens, a token stream
|
|
18
18
|
*
|
|
19
19
|
* @example
|
|
20
|
+
* ```ts
|
|
20
21
|
* var code = `var foo = 0;`;
|
|
21
22
|
* var tokens = tokenize_syntax(code, SyntaxStyler.langs.js);
|
|
22
23
|
* for (var token of tokens) {
|
|
@@ -24,6 +25,7 @@ import {SyntaxToken, type SyntaxTokenStream} from './syntax_token.js';
|
|
|
24
25
|
* console.log(`Found numeric literal: ${token.content}`);
|
|
25
26
|
* }
|
|
26
27
|
* }
|
|
28
|
+
* ```
|
|
27
29
|
*/
|
|
28
30
|
export const tokenize_syntax = (text: string, grammar: SyntaxGrammar): SyntaxTokenStream => {
|
|
29
31
|
// Grammar is already normalized (rest merged, patterns in arrays, etc.)
|