@fuzdev/fuz_ui 0.191.4 → 0.193.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.
- package/dist/ApiIndex.svelte +3 -3
- package/dist/ApiModule.svelte +2 -2
- package/dist/ApiModulesList.svelte +3 -3
- package/dist/ColorSchemeInput.svelte +6 -6
- package/dist/ContextmenuLinkEntry.svelte +1 -1
- package/dist/ContextmenuRoot.svelte +10 -10
- package/dist/ContextmenuRootForSafariCompatibility.svelte +19 -19
- package/dist/ContextmenuSeparator.svelte +3 -3
- package/dist/ContextmenuSubmenu.svelte +3 -3
- package/dist/CopyToClipboard.svelte +3 -3
- package/dist/DeclarationLink.svelte +1 -1
- package/dist/Dialog.svelte +16 -16
- package/dist/Docs.svelte +12 -12
- package/dist/DocsFooter.svelte +2 -2
- package/dist/DocsList.svelte +7 -7
- package/dist/DocsMenu.svelte +4 -4
- package/dist/DocsMenu.svelte.d.ts.map +1 -1
- package/dist/DocsPageLinks.svelte +4 -4
- package/dist/DocsPrimaryNav.svelte +2 -2
- package/dist/DocsSecondaryNav.svelte +4 -4
- package/dist/DocsTertiaryNav.svelte +13 -13
- package/dist/DocsTertiaryNav.svelte.d.ts +1 -1
- package/dist/GithubLink.svelte +1 -1
- package/dist/Hashlink.svelte +2 -2
- package/dist/HueInput.svelte +5 -5
- package/dist/LibraryDetail.svelte +8 -8
- package/dist/LibrarySummary.svelte +4 -4
- package/dist/MdnLink.svelte +1 -1
- package/dist/ModuleLink.svelte +1 -1
- package/dist/PasteFromClipboard.svelte +1 -1
- package/dist/PendingAnimation.svelte +2 -2
- package/dist/PendingButton.svelte +2 -2
- package/dist/ProjectLinks.svelte +4 -4
- package/dist/Teleport.svelte +2 -2
- package/dist/ThemeInput.svelte +5 -5
- package/dist/TomeContent.svelte +3 -3
- package/dist/TomeHeader.svelte +15 -14
- package/dist/TomeHeader.svelte.d.ts.map +1 -1
- package/dist/TomeLink.svelte +13 -6
- package/dist/TomeLink.svelte.d.ts +1 -1
- package/dist/TomeLink.svelte.d.ts.map +1 -1
- package/dist/TomeSection.svelte +1 -1
- package/dist/TomeSectionHeader.svelte +3 -3
- package/dist/api_search.svelte.js +2 -2
- package/dist/contextmenu_state.svelte.d.ts.map +1 -1
- package/dist/contextmenu_state.svelte.js +11 -10
- package/dist/csp.d.ts +81 -90
- package/dist/csp.d.ts.map +1 -1
- package/dist/csp.js +145 -163
- package/dist/csp_of_fuzdev.d.ts +13 -3
- package/dist/csp_of_fuzdev.d.ts.map +1 -1
- package/dist/csp_of_fuzdev.js +23 -7
- package/dist/dimensions.svelte.d.ts.map +1 -1
- package/dist/dimensions.svelte.js +2 -2
- package/dist/library.svelte.d.ts +1 -1
- package/dist/library_generate.js +1 -1
- package/dist/style_variable_helpers.svelte.d.ts.map +1 -1
- package/dist/style_variable_helpers.svelte.js +1 -1
- package/dist/theme_state.svelte.d.ts.map +1 -1
- package/dist/theme_state.svelte.js +2 -2
- package/dist/tome.d.ts +8 -3
- package/dist/tome.d.ts.map +1 -1
- package/dist/tome.js +24 -8
- package/dist/tsdoc_helpers.d.ts +9 -0
- package/dist/tsdoc_helpers.d.ts.map +1 -1
- package/dist/tsdoc_helpers.js +15 -5
- package/package.json +5 -5
- package/src/lib/api_search.svelte.ts +2 -2
- package/src/lib/contextmenu_state.svelte.ts +11 -10
- package/src/lib/csp.ts +224 -258
- package/src/lib/csp_of_fuzdev.ts +24 -8
- package/src/lib/dimensions.svelte.ts +2 -2
- package/src/lib/library_generate.ts +1 -1
- package/src/lib/style_variable_helpers.svelte.ts +1 -1
- package/src/lib/theme_state.svelte.ts +2 -2
- package/src/lib/tome.ts +25 -8
- package/src/lib/tsdoc_helpers.ts +18 -7
package/dist/csp.js
CHANGED
|
@@ -1,155 +1,175 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* and maps to the `KitConfig` `directives` option.
|
|
4
|
-
* The goal is to provide an ergonomic, modern, and safe API
|
|
5
|
-
* for Content Security Policy (CSP) creation
|
|
6
|
-
* that's simple to write and audit, and isn't error-prone.
|
|
2
|
+
* Builds a CSP directives map for use with SvelteKit's `kit.csp.directives` option.
|
|
7
3
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* Restrictive by default; opt into specific permissions via `extend` (append) or
|
|
5
|
+
* `overrides` (replace). Designed to read as an audit log: every user-added source
|
|
6
|
+
* is named at exactly one site in the source code. Library defaults are inherited
|
|
7
|
+
* unless you opt out via `replace_defaults`.
|
|
8
|
+
*
|
|
9
|
+
* Validation:
|
|
10
|
+
* - Unknown directive keys throw.
|
|
11
|
+
* - Extending a `['none']` directive throws (use `replace_defaults`/`overrides` to opt in).
|
|
12
|
+
* - `null` for `replace_defaults` (top-level or per-key) throws — omit the option for library
|
|
13
|
+
* defaults, pass `{}` to start blank, or use `overrides` to remove a specific directive.
|
|
14
|
+
* - `null` per-key in `extend` throws (use `overrides` for removal).
|
|
15
|
+
* - `undefined` per-key is treated as omitted in all three stages.
|
|
16
|
+
* - Non-object entries in `extend` (`null`, `undefined`, primitives) throw with a friendly error.
|
|
17
|
+
* - Output is validated to ensure `'none'` never appears alongside other tokens,
|
|
18
|
+
* that no directive ends up with an empty array (use `['none']` to forbid all),
|
|
19
|
+
* and that every source array contains only strings.
|
|
20
|
+
*
|
|
21
|
+
* Things like rendering to a string are out of scope and left to SvelteKit.
|
|
10
22
|
*/
|
|
11
|
-
export
|
|
12
|
-
const {
|
|
23
|
+
export const create_csp_directives = (options = {}) => {
|
|
24
|
+
const { replace_defaults = csp_directive_value_defaults, extend, overrides } = options;
|
|
25
|
+
if (replace_defaults === null) {
|
|
26
|
+
throw new Error(`Invalid value 'null' for options.replace_defaults. ` +
|
|
27
|
+
`Omit the option to use library defaults, or pass {} to start with no directives.`);
|
|
28
|
+
}
|
|
13
29
|
const directives = {};
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
// `Object.entries` widens to `[string, unknown]` and TS can't re-narrow per-key, so
|
|
31
|
+
// writes via the validated `directive` need a single trusted-bridge cast — kept inside
|
|
32
|
+
// this helper so the call sites stay free of type assertions. Clones arrays so callers
|
|
33
|
+
// don't have to worry about user-supplied arrays leaking into the output.
|
|
34
|
+
const assign = (directive, value) => {
|
|
35
|
+
directives[directive] = Array.isArray(value)
|
|
36
|
+
? [...value]
|
|
37
|
+
: value;
|
|
20
38
|
};
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
// Stage 1: starting state from `replace_defaults`.
|
|
40
|
+
// `{}` starts blank — every directive must come from `extend`/`overrides`.
|
|
41
|
+
for_each_directive(replace_defaults, 'replace_defaults', (directive, value) => {
|
|
42
|
+
if (value === null) {
|
|
43
|
+
throw new Error(`Invalid value 'null' for directive '${directive}' in options.replace_defaults. ` +
|
|
44
|
+
`Omit the key instead, or use \`overrides: { '${directive}': null }\` to remove.`);
|
|
45
|
+
}
|
|
46
|
+
if (value === undefined)
|
|
47
|
+
return;
|
|
48
|
+
assign(directive, value);
|
|
49
|
+
});
|
|
50
|
+
// Stage 2: append sources per layer in `extend`.
|
|
51
|
+
if (extend?.length) {
|
|
52
|
+
for (const layer of extend) {
|
|
53
|
+
for_each_directive(layer, 'extend', (directive, value) => {
|
|
54
|
+
// `undefined` is treated as omitted, matching `replace_defaults`/`overrides`.
|
|
55
|
+
// Lets callers write `{'connect-src': cond ? [API] : undefined}` naturally.
|
|
56
|
+
if (value === undefined)
|
|
57
|
+
return;
|
|
58
|
+
// `null` is meaningful enough to deserve its own error — users reaching for null
|
|
59
|
+
// in extend almost always want removal, which lives on `overrides`.
|
|
60
|
+
if (value === null) {
|
|
61
|
+
throw new Error(`Cannot extend directive '${directive}' with null. ` +
|
|
62
|
+
`extend can only append sources — to remove a directive from the output, ` +
|
|
63
|
+
`use \`overrides: { '${directive}': null }\`.`);
|
|
46
64
|
}
|
|
47
|
-
|
|
65
|
+
if (!Array.isArray(value)) {
|
|
66
|
+
throw new Error(`Cannot extend directive '${directive}': value must be an array of sources, got ${typeof value}.`);
|
|
67
|
+
}
|
|
68
|
+
if (!value.length)
|
|
69
|
+
return;
|
|
70
|
+
const current = directives[directive];
|
|
71
|
+
if (is_none(current)) {
|
|
72
|
+
throw new Error(`Cannot extend directive '${directive}' while its current value is ['none']. ` +
|
|
73
|
+
`The pipeline runs replace_defaults → extend → overrides, so an \`overrides\` ` +
|
|
74
|
+
`entry for '${directive}' cannot rescue this — extend sees the ['none'] starting ` +
|
|
75
|
+
`value first. Opt in via \`replace_defaults: { '${directive}': [...] }\` or move ` +
|
|
76
|
+
`the sources into \`overrides: { '${directive}': [...] }\`.`);
|
|
77
|
+
}
|
|
78
|
+
if (current === undefined) {
|
|
79
|
+
assign(directive, [...new Set(value)]);
|
|
80
|
+
}
|
|
81
|
+
else if (Array.isArray(current)) {
|
|
82
|
+
assign(directive, [...new Set([...current, ...value])]);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new Error(`Cannot extend directive '${directive}': it has a non-array value.`);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
48
88
|
}
|
|
49
89
|
}
|
|
50
|
-
//
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
throw new Error(`Invalid directive in options.directives: ${key}`);
|
|
56
|
-
}
|
|
57
|
-
// Skip if directive is ['none'] or not an array
|
|
58
|
-
if (is_none_directive(value) || !Array.isArray(value)) {
|
|
59
|
-
continue;
|
|
90
|
+
// Stage 3: final-pass `overrides` — replace value or remove key.
|
|
91
|
+
if (overrides) {
|
|
92
|
+
for_each_directive(overrides, 'overrides', (directive, value) => {
|
|
93
|
+
if (value === null) {
|
|
94
|
+
delete directives[directive]; // eslint-disable-line @typescript-eslint/no-dynamic-delete
|
|
60
95
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (required_trust == null)
|
|
64
|
-
continue;
|
|
65
|
-
// Add matching sources - separate the filtering into trust-based and directive-based inclusion
|
|
66
|
-
const sources_to_add = trusted_sources
|
|
67
|
-
.filter((spec) => {
|
|
68
|
-
// Check for explicit inclusion in directives list
|
|
69
|
-
const explicitly_included = spec.directives?.includes(directive) ?? false;
|
|
70
|
-
// Check for trust level based inclusion
|
|
71
|
-
const has_trust_level = spec.trust !== undefined;
|
|
72
|
-
const include_by_trust = has_trust_level && is_csp_trusted(required_trust, spec.trust);
|
|
73
|
-
// Include the source if either condition is met
|
|
74
|
-
return explicitly_included || include_by_trust;
|
|
75
|
-
})
|
|
76
|
-
.map((spec) => spec.source);
|
|
77
|
-
if (sources_to_add.length > 0) {
|
|
78
|
-
directives[directive] = [...value, ...sources_to_add];
|
|
96
|
+
else if (value !== undefined) {
|
|
97
|
+
assign(directive, value);
|
|
79
98
|
}
|
|
80
|
-
}
|
|
99
|
+
});
|
|
81
100
|
}
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
101
|
+
// Stage 4: output validation — empty arrays and mixed `'none'` are invalid CSP.
|
|
102
|
+
for (const [key, value] of Object.entries(directives)) {
|
|
103
|
+
if (typeof value === 'boolean')
|
|
104
|
+
continue;
|
|
105
|
+
if (!Array.isArray(value)) {
|
|
106
|
+
throw new Error(`Directive '${key}' has an invalid value: expected an array of sources or a boolean, ` +
|
|
107
|
+
`got ${value === null ? 'null' : typeof value}.`);
|
|
108
|
+
}
|
|
109
|
+
if (value.length === 0) {
|
|
110
|
+
throw new Error(`Directive '${key}' has an empty array. ` +
|
|
111
|
+
`Use ['none'] to forbid all sources, or omit the directive entirely.`);
|
|
112
|
+
}
|
|
113
|
+
// Element-level type check — the `CspSource` template-string type gates this at the
|
|
114
|
+
// type layer, but `as any` callers can slip non-strings through. A non-string source
|
|
115
|
+
// would render as `undefined` / `[object Object]` in the emitted CSP header.
|
|
116
|
+
for (let i = 0; i < value.length; i++) {
|
|
117
|
+
const v = value[i];
|
|
118
|
+
if (typeof v !== 'string') {
|
|
119
|
+
throw new Error(`Directive '${key}' has a non-string source at index ${i}: got ${v === null ? 'null' : typeof v}.`);
|
|
97
120
|
}
|
|
98
121
|
}
|
|
122
|
+
if (value.length > 1 && value.includes('none')) {
|
|
123
|
+
throw new Error(`Directive '${key}' has 'none' alongside other tokens (${value.join(', ')}). ` +
|
|
124
|
+
`'none' must appear alone in CSP.`);
|
|
125
|
+
}
|
|
99
126
|
}
|
|
100
127
|
return directives;
|
|
101
|
-
}
|
|
128
|
+
};
|
|
102
129
|
export const parse_csp_directive = (directive) => typeof directive === 'string' && csp_directive_spec_by_name.has(directive)
|
|
103
130
|
? directive
|
|
104
131
|
: null;
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Numeric values for CSP trust levels. See `csp_trust_levels`.
|
|
108
|
-
* Lower is less trusted.
|
|
109
|
-
* Includes `undefined` in the type for safety.
|
|
110
|
-
*/
|
|
111
|
-
export const csp_trust_level_value = {
|
|
112
|
-
low: 0,
|
|
113
|
-
medium: 1,
|
|
114
|
-
high: 2,
|
|
115
|
-
};
|
|
116
|
-
/**
|
|
117
|
-
* Validates and extracts a CSP trust level from an unknown value.
|
|
118
|
-
*/
|
|
119
|
-
export const parse_csp_trust_level = (trust) => csp_trust_levels.includes(trust) ? trust : null;
|
|
132
|
+
const is_none = (value) => Array.isArray(value) && value.length === 1 && value[0] === 'none';
|
|
120
133
|
/**
|
|
121
|
-
*
|
|
134
|
+
* Iterate over a per-directive options map, validating that every key is a known directive.
|
|
135
|
+
* Throws if any key fails to parse as a `CspDirective`, mentioning `source_label` so the
|
|
136
|
+
* error pinpoints which option (`replace_defaults`, `extend`, or `overrides`) was bad.
|
|
122
137
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* - 'low' sources can only be used in low trust directives (lowest privilege)
|
|
138
|
+
* Also guards against non-object `source` values (e.g. `extend: [undefined]`, `extend: ['oops']`)
|
|
139
|
+
* so callers get a friendly library error instead of a cryptic native `TypeError` from
|
|
140
|
+
* `Object.entries`.
|
|
127
141
|
*/
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
142
|
+
const for_each_directive = (source, source_label, fn) => {
|
|
143
|
+
if (source === null || typeof source !== 'object') {
|
|
144
|
+
const got = source === null ? 'null' : typeof source;
|
|
145
|
+
throw new Error(`Invalid entry in options.${source_label}: expected an object, got ${got}.`);
|
|
146
|
+
}
|
|
147
|
+
for (const [key, value] of Object.entries(source)) {
|
|
148
|
+
const directive = parse_csp_directive(key);
|
|
149
|
+
if (directive === null) {
|
|
150
|
+
throw new Error(`Invalid directive in options.${source_label}: ${key}`);
|
|
151
|
+
}
|
|
152
|
+
fn(directive, value);
|
|
133
153
|
}
|
|
134
|
-
// A source with higher trust privilege (higher value)
|
|
135
|
-
// can be used in a directive with less privilege (lower value).
|
|
136
|
-
return granted_value >= required_value;
|
|
137
154
|
};
|
|
138
|
-
/**
|
|
139
|
-
* Helper to check if a directive value is `['none']`,
|
|
140
|
-
* or more precisely for robustness with malformed values, checks for an array with `'none'`.
|
|
141
|
-
*/
|
|
142
|
-
const is_none_directive = (value) => Array.isArray(value) && value.includes('none');
|
|
143
155
|
export const COLOR_SCHEME_SCRIPT_HASH = 'sha256-QOxqn7EUzb3ydF9SALJoJGWSvywW9R0AfTDSenB83Z8=';
|
|
144
156
|
/**
|
|
145
|
-
* The
|
|
157
|
+
* The library CSP directive defaults — directives enabled out of the box.
|
|
146
158
|
* Prioritizes safety but loosens around media and styles, relying on defense-in-depth.
|
|
147
|
-
*
|
|
159
|
+
* WASM compile is allowed (`'wasm-unsafe-eval'` on `script-src` and `worker-src`); `eval` is not.
|
|
160
|
+
*
|
|
161
|
+
* Directives not listed here (`report-to`, `require-trusted-types-for`, `trusted-types`,
|
|
162
|
+
* `sandbox`) are intentionally absent by default — opt in via `replace_defaults` or `overrides`.
|
|
163
|
+
*
|
|
164
|
+
* Customizable via `CreateCspDirectivesOptions.replace_defaults`.
|
|
148
165
|
*/
|
|
149
166
|
export const csp_directive_value_defaults = {
|
|
150
167
|
'default-src': ['none'],
|
|
151
|
-
'
|
|
152
|
-
|
|
168
|
+
// `'wasm-unsafe-eval'` permits WASM compile/instantiate only — `eval` and `new Function`
|
|
169
|
+
// remain blocked. Needed for `@fuzdev/fuz_util/hash_blake3` and any other WASM in the page.
|
|
170
|
+
// Pre-2022 browsers ignore the keyword and block WASM; if you need them, override with `'unsafe-eval'`.
|
|
171
|
+
'script-src': ['self', 'wasm-unsafe-eval', COLOR_SCHEME_SCRIPT_HASH],
|
|
172
|
+
'script-src-elem': ['self', COLOR_SCHEME_SCRIPT_HASH], // Block script elements except for self and the color scheme loader (WASM compile is gated by script-src, not script-src-elem)
|
|
153
173
|
'script-src-attr': ['none'], // Block scripts in HTML attributes
|
|
154
174
|
'style-src': ['self', 'unsafe-inline'], // Main style directive (uses unsafe-inline but network connections are disallowed by other directives)
|
|
155
175
|
'style-src-elem': ['self', 'unsafe-inline'], // Style elements (standalone stylesheets)
|
|
@@ -163,55 +183,17 @@ export const csp_directive_value_defaults = {
|
|
|
163
183
|
'frame-src': ['self'], // Frames/iframes
|
|
164
184
|
'frame-ancestors': ['self'], // Control what can embed this page
|
|
165
185
|
'form-action': ['self'], // Form submission targets
|
|
166
|
-
'
|
|
186
|
+
// `'wasm-unsafe-eval'` mirrors the script-src allowance so WASM compiled inside a Web Worker also works.
|
|
187
|
+
'worker-src': ['self', 'blob:', 'wasm-unsafe-eval'], // Web workers
|
|
167
188
|
'object-src': ['none'], // Block plugins (Flash, Java, etc.)
|
|
168
189
|
'base-uri': ['none'], // Prevent base tag hijacking
|
|
169
190
|
'upgrade-insecure-requests': true, // Upgrade http to https
|
|
170
|
-
'report-to': null, // Report violations (e.g. `'/csp-violation-report'`)
|
|
171
|
-
'require-trusted-types-for': null,
|
|
172
|
-
'trusted-types': null,
|
|
173
|
-
sandbox: null,
|
|
174
|
-
};
|
|
175
|
-
/**
|
|
176
|
-
* Sources that meet this trust requirement are included for it by default.
|
|
177
|
-
* If null, no trusted sources are added to the directive automatically.
|
|
178
|
-
* Directives that don't support sources or default to `['none']` are null.
|
|
179
|
-
*
|
|
180
|
-
* Feedback is welcome, please see the issues - https://github.com/fuzdev/fuz_ui/issues
|
|
181
|
-
*/
|
|
182
|
-
export const csp_directive_required_trust_defaults = {
|
|
183
|
-
'default-src': null,
|
|
184
|
-
'script-src': 'high',
|
|
185
|
-
'script-src-elem': 'high',
|
|
186
|
-
'script-src-attr': null,
|
|
187
|
-
'style-src': 'medium',
|
|
188
|
-
'style-src-elem': 'medium',
|
|
189
|
-
'style-src-attr': 'medium',
|
|
190
|
-
'img-src': 'low',
|
|
191
|
-
'media-src': 'low',
|
|
192
|
-
'font-src': 'low',
|
|
193
|
-
'manifest-src': null,
|
|
194
|
-
'child-src': null,
|
|
195
|
-
'connect-src': 'medium',
|
|
196
|
-
'frame-src': 'medium',
|
|
197
|
-
'frame-ancestors': 'medium',
|
|
198
|
-
'form-action': 'medium',
|
|
199
|
-
'worker-src': 'medium',
|
|
200
|
-
'object-src': null,
|
|
201
|
-
'base-uri': null,
|
|
202
|
-
'upgrade-insecure-requests': null,
|
|
203
|
-
'report-to': null,
|
|
204
|
-
'require-trusted-types-for': null,
|
|
205
|
-
'trusted-types': null,
|
|
206
|
-
sandbox: null,
|
|
207
191
|
};
|
|
208
192
|
/**
|
|
209
193
|
* Static data descriptors for the CSP directives.
|
|
210
194
|
* Fuz excludes deprecated directives, so those are intentionally omitted,
|
|
211
195
|
* but any newer missing directives are bugs.
|
|
212
196
|
*
|
|
213
|
-
* Could be co-located but is currently here to keep that module smaller.
|
|
214
|
-
*
|
|
215
197
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy}
|
|
216
198
|
*/
|
|
217
199
|
export const csp_directive_specs = [
|
package/dist/csp_of_fuzdev.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CspDirectives } from './csp.ts';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Per-directive sources that allow full interop between fuzdev/sister sites
|
|
4
|
+
* (`*.fuz.dev`, `*.zzz.software`) — loading assets and APIs from each other,
|
|
5
|
+
* and iframing in both directions.
|
|
6
|
+
*
|
|
7
|
+
* Pass into `create_csp_directives({extend: [csp_directives_of_fuzdev]})`.
|
|
8
|
+
* Intended for sites within the ecosystem; external apps usually want a
|
|
9
|
+
* narrower, hand-written allow-list.
|
|
10
|
+
*
|
|
11
|
+
* Deliberately scoped — `script-src`, `style-src`, `worker-src`, etc. are not
|
|
12
|
+
* granted, even between sister sites. Add at the call site if a specific page
|
|
13
|
+
* needs them.
|
|
4
14
|
*/
|
|
5
|
-
export declare const
|
|
15
|
+
export declare const csp_directives_of_fuzdev: Partial<CspDirectives>;
|
|
6
16
|
//# sourceMappingURL=csp_of_fuzdev.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csp_of_fuzdev.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/csp_of_fuzdev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAE5C
|
|
1
|
+
{"version":3,"file":"csp_of_fuzdev.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/csp_of_fuzdev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,EAAE,OAAO,CAAC,aAAa,CAW3D,CAAC"}
|
package/dist/csp_of_fuzdev.js
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Per-directive sources that allow full interop between fuzdev/sister sites
|
|
3
|
+
* (`*.fuz.dev`, `*.zzz.software`) — loading assets and APIs from each other,
|
|
4
|
+
* and iframing in both directions.
|
|
5
|
+
*
|
|
6
|
+
* Pass into `create_csp_directives({extend: [csp_directives_of_fuzdev]})`.
|
|
7
|
+
* Intended for sites within the ecosystem; external apps usually want a
|
|
8
|
+
* narrower, hand-written allow-list.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately scoped — `script-src`, `style-src`, `worker-src`, etc. are not
|
|
11
|
+
* granted, even between sister sites. Add at the call site if a specific page
|
|
12
|
+
* needs them.
|
|
3
13
|
*/
|
|
4
|
-
export const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
]
|
|
14
|
+
export const csp_directives_of_fuzdev = {
|
|
15
|
+
'img-src': ['https://*.fuz.dev/', 'https://*.zzz.software/'],
|
|
16
|
+
'media-src': ['https://*.fuz.dev/', 'https://*.zzz.software/'],
|
|
17
|
+
'font-src': ['https://*.fuz.dev/', 'https://*.zzz.software/'],
|
|
18
|
+
'connect-src': ['https://*.fuz.dev/', 'https://*.zzz.software/'],
|
|
19
|
+
'frame-src': ['https://*.fuz.dev/', 'https://*.zzz.software/'],
|
|
20
|
+
'frame-ancestors': ['https://*.fuz.dev/', 'https://*.zzz.software/'],
|
|
21
|
+
// `child-src` is intentionally omitted — it defaults to `['none']`, and `extend` cannot
|
|
22
|
+
// append to a `'none'`-valued directive. Including it here would break the common
|
|
23
|
+
// `create_csp_directives({extend: [csp_directives_of_fuzdev]})` call. `frame-src` is its
|
|
24
|
+
// fallback target anyway, so direct opt-in via `frame-src` is the supported path.
|
|
25
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dimensions.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/dimensions.svelte.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAU;IACtB,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"dimensions.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/dimensions.svelte.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAU;IACtB,KAAK,EAAE,MAAM,CAAiB;IAC9B,MAAM,EAAE,MAAM,CAAiB;CAC/B"}
|
package/dist/library.svelte.d.ts
CHANGED
package/dist/library_generate.js
CHANGED
|
@@ -81,7 +81,7 @@ export const library_generate = (input) => {
|
|
|
81
81
|
// Phase 1: Analyze all modules and collect re-exports
|
|
82
82
|
const source_json = {
|
|
83
83
|
name: package_json.name,
|
|
84
|
-
version: package_json.version,
|
|
84
|
+
version: package_json.version || '',
|
|
85
85
|
modules,
|
|
86
86
|
};
|
|
87
87
|
// Collect re-exports for phase 2 merging
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style_variable_helpers.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/style_variable_helpers.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAK/D,qBAAa,qBAAqB;IACjC,KAAK,EAAE,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"style_variable_helpers.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/style_variable_helpers.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,6BAA6B,CAAC;AAK/D,qBAAa,qBAAqB;IACjC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAiB;gBAEhC,OAAO,GAAE,aAAa,GAAG,IAAW;CAGhD;AAED,eAAO,MAAM,yBAAyB;;;CAAwD,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { create_context } from './context_helpers.js';
|
|
2
2
|
// TODO maybe change this to a generic wrapper class for any value?
|
|
3
3
|
export class SelectedStyleVariable {
|
|
4
|
-
value = $state();
|
|
4
|
+
value = $state.raw();
|
|
5
5
|
constructor(initial = null) {
|
|
6
6
|
this.value = initial;
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/theme_state.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,KAAK,EAAC,MAAM,0BAA0B,CAAC;AAOrF,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAExD,qBAAa,UAAU;IACtB,KAAK,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"theme_state.svelte.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/theme_state.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,KAAK,EAAC,MAAM,0BAA0B,CAAC;AAOrF,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAExD,qBAAa,UAAU;IACtB,KAAK,EAAE,KAAK,CAAiB;IAC7B,YAAY,EAAE,WAAW,CAAiB;gBAE9B,OAAO,CAAC,EAAE,iBAAiB;IAUvC,MAAM,IAAI,cAAc;CAMxB;AACD,eAAO,MAAM,mBAAmB;2CAAwB,UAAU;4BAAV,UAAU;uBAAV,UAAU,WAAV,UAAU;CAAG,CAAC;AAEtE,eAAO,MAAM,iBAAiB,GAAI,cAAc,WAAW,GAAG,IAAI,KAAG,IAOpE,CAAC;AAEF,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAC3D,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C,eAAO,MAAM,iBAAiB,GAC7B,cAAc,WAAW,GAAG,IAAI,EAChC,YAA8B,KAC5B,IAEF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC7B,WAAU,WAAoB,EAC9B,YAA8B,KAC5B,WAA4E,CAAC;AAEhF,eAAO,MAAM,UAAU,GAAI,OAAO,KAAK,GAAG,IAAI,EAAE,YAAuB,KAAG,IAEzE,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,WAAU,KAA0B,EAAE,YAAuB,KAAG,KAC3C,CAAC"}
|
|
@@ -4,8 +4,8 @@ import { BROWSER } from 'esm-env';
|
|
|
4
4
|
import { create_context } from './context_helpers.js';
|
|
5
5
|
import { load_from_storage, save_to_storage } from './storage.js';
|
|
6
6
|
export class ThemeState {
|
|
7
|
-
theme = $state();
|
|
8
|
-
color_scheme = $state();
|
|
7
|
+
theme = $state.raw();
|
|
8
|
+
color_scheme = $state.raw();
|
|
9
9
|
constructor(options) {
|
|
10
10
|
const theme = options?.theme ?? default_themes[0];
|
|
11
11
|
const color_scheme = options?.color_scheme ?? 'auto';
|
package/dist/tome.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Component } from 'svelte';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
export declare const Tome: z.ZodObject<{
|
|
4
|
-
|
|
4
|
+
slug: z.ZodString;
|
|
5
|
+
title: z.ZodOptional<z.ZodString>;
|
|
5
6
|
category: z.ZodString;
|
|
6
7
|
Component: z.ZodCustom<Component<any, any, string>, Component<any, any, string>>;
|
|
7
8
|
related_tomes: z.ZodArray<z.ZodString>;
|
|
@@ -12,13 +13,17 @@ export type Tome = z.infer<typeof Tome>;
|
|
|
12
13
|
/**
|
|
13
14
|
* @param hash - URL fragment to append, with or without the `#`
|
|
14
15
|
*/
|
|
15
|
-
export declare const
|
|
16
|
+
export declare const tome_to_pathname: (item: Tome | string, docs_path?: string, hash?: string) => string;
|
|
17
|
+
/**
|
|
18
|
+
* The display label for a tome — its `title` if set, else its `slug`.
|
|
19
|
+
*/
|
|
20
|
+
export declare const tome_to_title: (tome: Tome) => string;
|
|
16
21
|
export declare const tomes_context: {
|
|
17
22
|
get: (error_message?: string) => () => Map<string, Tome>;
|
|
18
23
|
get_maybe: () => (() => Map<string, Tome>) | undefined;
|
|
19
24
|
set: (value: () => Map<string, Tome>) => () => Map<string, Tome>;
|
|
20
25
|
};
|
|
21
|
-
export declare const
|
|
26
|
+
export declare const tome_get_by_slug: (slug: string) => Tome;
|
|
22
27
|
export declare const tome_context: {
|
|
23
28
|
get: (error_message?: string) => () => Tome;
|
|
24
29
|
get_maybe: () => (() => Tome) | undefined;
|
package/dist/tome.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tome.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/tome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAMtB,eAAO,MAAM,IAAI
|
|
1
|
+
{"version":3,"file":"tome.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/tome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAMtB,eAAO,MAAM,IAAI;;;;;;;;iBAoBf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAC5B,MAAM,IAAI,GAAG,MAAM,EACnB,kBAA6B,EAC7B,OAAO,MAAM,KACX,MAIF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,IAAI,KAAG,MAAiC,CAAC;AAE7E,eAAO,MAAM,aAAa;2CAAwB,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;4BAAjB,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;uBAAjB,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,WAAjB,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC;CAAG,CAAC;AAEvE,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,IAK/C,CAAC;AAEF,eAAO,MAAM,YAAY;2CAAwB,IAAI;4BAAJ,IAAI;uBAAJ,IAAI,WAAJ,IAAI;CAAG,CAAC"}
|
package/dist/tome.js
CHANGED
|
@@ -2,9 +2,21 @@ import { resolve } from '$app/paths';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { ensure_start } from '@fuzdev/fuz_util/string.js';
|
|
4
4
|
import { create_context } from './context_helpers.js';
|
|
5
|
-
import { DOCS_PATH_DEFAULT
|
|
5
|
+
import { DOCS_PATH_DEFAULT } from './docs_helpers.svelte.js';
|
|
6
6
|
export const Tome = z.object({
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Stable identifier and URL path segment — must be a URL-safe slug
|
|
9
|
+
* (used directly as the route segment, the lookup key, and in
|
|
10
|
+
* `related_tomes` cross-references). Set `title` for the display label.
|
|
11
|
+
*/
|
|
12
|
+
slug: z.string(),
|
|
13
|
+
/**
|
|
14
|
+
* Human-readable display label shown in menus, headings, and links.
|
|
15
|
+
* Falls back to `slug` when omitted, so set `title` to give multi-word or
|
|
16
|
+
* specially cased tomes a readable label (e.g. `slug: 'vite-plugin'` →
|
|
17
|
+
* `title: 'vite plugin'`).
|
|
18
|
+
*/
|
|
19
|
+
title: z.string().optional(),
|
|
8
20
|
// TODO maybe now this makes sense with mdz? summary: z.string(),
|
|
9
21
|
category: z.string(),
|
|
10
22
|
Component: z.custom(),
|
|
@@ -15,17 +27,21 @@ export const Tome = z.object({
|
|
|
15
27
|
/**
|
|
16
28
|
* @param hash - URL fragment to append, with or without the `#`
|
|
17
29
|
*/
|
|
18
|
-
export const
|
|
19
|
-
const
|
|
20
|
-
const path = docs_path + '/' +
|
|
30
|
+
export const tome_to_pathname = (item, docs_path = DOCS_PATH_DEFAULT, hash) => {
|
|
31
|
+
const slug = typeof item === 'string' ? item : item.slug;
|
|
32
|
+
const path = docs_path + '/' + slug;
|
|
21
33
|
return resolve((hash ? path + ensure_start(hash, '#') : path));
|
|
22
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* The display label for a tome — its `title` if set, else its `slug`.
|
|
37
|
+
*/
|
|
38
|
+
export const tome_to_title = (tome) => tome.title ?? tome.slug;
|
|
23
39
|
export const tomes_context = create_context();
|
|
24
|
-
export const
|
|
40
|
+
export const tome_get_by_slug = (slug) => {
|
|
25
41
|
const get_tomes = tomes_context.get();
|
|
26
|
-
const tome = get_tomes().get(
|
|
42
|
+
const tome = get_tomes().get(slug);
|
|
27
43
|
if (!tome)
|
|
28
|
-
throw Error(`unable to find tome "${
|
|
44
|
+
throw Error(`unable to find tome "${slug}"`);
|
|
29
45
|
return tome;
|
|
30
46
|
};
|
|
31
47
|
export const tome_context = create_context();
|
package/dist/tsdoc_helpers.d.ts
CHANGED
|
@@ -98,6 +98,15 @@ export declare const tsdoc_parse: (node: ts.Node, source_file: ts.SourceFile) =>
|
|
|
98
98
|
* @mutates declaration - adds doc_comment, deprecated_message, examples, see_also, throws, since fields
|
|
99
99
|
*/
|
|
100
100
|
export declare const tsdoc_apply_to_declaration: (declaration: DeclarationJson, tsdoc: TsdocParsedComment | undefined) => void;
|
|
101
|
+
/**
|
|
102
|
+
* Concatenates a JSDoc comment (string or node array) into plain text, preserving `{@link ...}`.
|
|
103
|
+
*
|
|
104
|
+
* `JSDocLink` / `JSDocLinkCode` / `JSDocLinkPlain` nodes have empty `.text` — the identifier
|
|
105
|
+
* lives on `.name`, not `.text`. Using `.text` alone silently drops link content; we fall back
|
|
106
|
+
* to the source-text representation for link nodes so `{@link Foo}` survives intact for downstream
|
|
107
|
+
* renderers (see `tsdoc_mdz.ts`).
|
|
108
|
+
*/
|
|
109
|
+
export declare const tsdoc_comment_to_text: (comment: string | ts.NodeArray<ts.JSDocComment>, source_file: ts.SourceFile) => string;
|
|
101
110
|
/**
|
|
102
111
|
* Clean raw JSDoc comment text by removing comment markers and leading asterisks.
|
|
103
112
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tsdoc_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/tsdoc_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,iCAAiC,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,MAAM,CAAC,EAAE,KAAK,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACrD,oCAAoC;IACpC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW,GACvB,MAAM,EAAE,CAAC,IAAI,EACb,aAAa,EAAE,CAAC,UAAU,KACxB,kBAAkB,GAAG,
|
|
1
|
+
{"version":3,"file":"tsdoc_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/tsdoc_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,iCAAiC,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,MAAM,CAAC,EAAE,KAAK,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IACrD,oCAAoC;IACpC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW,GACvB,MAAM,EAAE,CAAC,IAAI,EACb,aAAa,EAAE,CAAC,UAAU,KACxB,kBAAkB,GAAG,SAoFvB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,GACtC,aAAa,eAAe,EAC5B,OAAO,kBAAkB,GAAG,SAAS,KACnC,IAmBF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GACjC,SAAS,MAAM,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,EAC/C,aAAa,EAAE,CAAC,UAAU,KACxB,MAGF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAI,cAAc,MAAM,KAAG,MAAM,GAAG,SAUnE,CAAC"}
|