zuixs 0.0.0-stage → 0.0.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.
@@ -0,0 +1,238 @@
1
+ import { resolveTheme } from './theme.js';
2
+ import { utilityFor } from './utilities.js';
3
+ import { cssEscapeClass, resolveLimits, safeCondition, safeDeclaration } from './safety.js';
4
+ export const preflight = `*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif}body{margin:0;line-height:inherit}button,input,select,textarea{font:inherit}button{cursor:pointer}img,svg,video,canvas{display:block;max-width:100%}a{color:inherit;text-decoration:inherit}h1,h2,h3,h4,h5,h6,p{margin:0}ol,ul{list-style:none;margin:0;padding:0}`;
5
+ function splitVariants(input) { const result = []; let buf = '', depth = 0; for (const ch of input) {
6
+ if (ch === '[')
7
+ depth++;
8
+ else if (ch === ']')
9
+ depth--;
10
+ if (ch === ':' && depth === 0) {
11
+ result.push(buf);
12
+ buf = '';
13
+ }
14
+ else
15
+ buf += ch;
16
+ } result.push(buf); return result; }
17
+ function cssDeclarations(decls, important) { const entries = Object.entries(decls); if (!entries.length || entries.some(([prop, val]) => !safeDeclaration(prop, String(val))))
18
+ return; return entries.map(([prop, val]) => `${prop}:${String(val)}${important ? ' !important' : ''};`).join(''); }
19
+ const pseudo = { 'first-letter': '::first-letter', 'first-line': '::first-line', marker: '::marker', backdrop: '::backdrop', 'file': '::file-selector-button', 'open': ':is([open],:popover-open)', target: ':target', 'only': ':only-child', 'first-of-type': ':first-of-type', 'last-of-type': ':last-of-type', 'only-of-type': ':only-of-type', 'read-only': ':read-only', 'read-write': ':read-write', 'autofill': ':autofill', 'indeterminate': ':indeterminate', 'in-range': ':in-range', 'out-of-range': ':out-of-range', 'placeholder-shown': ':placeholder-shown', default: ':default', optional: ':optional', autofocus: ':focus-visible', hover: ':hover', focus: ':focus', 'focus-visible': ':focus-visible', 'focus-within': ':focus-within', active: ':active', disabled: ':disabled', enabled: ':enabled', checked: ':checked', required: ':required', invalid: ':invalid', valid: ':valid', first: ':first-child', last: ':last-child', odd: ':nth-child(odd)', even: ':nth-child(even)', visited: ':visited', empty: ':empty', before: '::before', after: '::after', placeholder: '::placeholder', selection: '::selection' };
20
+ function safeQuery(value) { return safeCondition(value); }
21
+ function safeSelector(value) { return value.length <= 120 && /^[a-zA-Z0-9.#:[\]_'"()=~+* >|-]+$/.test(value); }
22
+ export function createZuix(config = {}) {
23
+ const theme = resolveTheme(config);
24
+ const limits = resolveLimits(config.limits);
25
+ const utilities = {};
26
+ const components = {};
27
+ const base = [];
28
+ const api = {
29
+ addUtilities(items) { for (const [key, value] of Object.entries(items))
30
+ utilities[key.replace(/^\./, '')] = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, String(v)])); },
31
+ addComponents(items) { for (const [key, value] of Object.entries(items))
32
+ components[key.replace(/^\./, '')] = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, String(v)])); },
33
+ addBase(css) { base.push(css); },
34
+ theme(path, fallback = '') { const [category, ...rest] = path.split('.'); return String(theme[category]?.[rest.join('.')] ?? fallback); }
35
+ };
36
+ for (const plugin of config.plugins ?? [])
37
+ plugin(api);
38
+ function compileClass(token) {
39
+ // eslint-disable-next-line no-control-regex -- Intentionally matches control characters for validation or output sanitization.
40
+ if (typeof token !== 'string' || !token || token.length > limits.maxTokenLength || /[\u0000-\u001f\u007f{};\\]/.test(token))
41
+ return;
42
+ const chunks = splitVariants(token);
43
+ if (chunks.length > 12)
44
+ return;
45
+ let name = chunks.pop() ?? '';
46
+ const variants = chunks;
47
+ if (config.prefix) {
48
+ if (!name.startsWith(config.prefix))
49
+ return;
50
+ name = name.slice(config.prefix.length);
51
+ }
52
+ const important = name.startsWith('!') || Boolean(config.important);
53
+ if (name.startsWith('!'))
54
+ name = name.slice(1);
55
+ const decl = utilityFor(name, theme, { ...utilities, ...components });
56
+ if (!decl)
57
+ return;
58
+ const body = cssDeclarations(decl, important);
59
+ if (!body)
60
+ return;
61
+ let selector = `.${cssEscapeClass(token)}`;
62
+ let atRules = [];
63
+ let groupPeer = '';
64
+ for (const variant of variants) {
65
+ if (Object.hasOwn(theme.screens, variant)) {
66
+ const screen = String(theme.screens[variant]);
67
+ if (!/^(?:\d+(?:\.\d+)?)(?:px|rem|em)$/.test(screen))
68
+ return;
69
+ atRules.push(`@media (min-width: ${screen})`);
70
+ continue;
71
+ }
72
+ if (variant === 'dark') {
73
+ if (config.darkMode === 'media')
74
+ atRules.push('@media (prefers-color-scheme: dark)');
75
+ else
76
+ selector = `:is(.dark ${selector},[data-theme="dark"] ${selector})`;
77
+ continue;
78
+ }
79
+ if (variant === 'print') {
80
+ atRules.push('@media print');
81
+ continue;
82
+ }
83
+ if (variant === 'motion-reduce') {
84
+ atRules.push('@media (prefers-reduced-motion: reduce)');
85
+ continue;
86
+ }
87
+ if (variant === 'motion-safe') {
88
+ atRules.push('@media (prefers-reduced-motion: no-preference)');
89
+ continue;
90
+ }
91
+ if (variant === 'portrait' || variant === 'landscape') {
92
+ atRules.push(`@media (orientation: ${variant})`);
93
+ continue;
94
+ }
95
+ if (variant === 'motion' || variant === 'hoverable') {
96
+ atRules.push('@media (hover: hover) and (pointer: fine)');
97
+ continue;
98
+ }
99
+ if (variant === 'forced-colors') {
100
+ atRules.push('@media (forced-colors: active)');
101
+ continue;
102
+ }
103
+ if (variant === 'contrast-more' || variant === 'contrast-less') {
104
+ atRules.push(`@media (prefers-contrast: ${variant === 'contrast-more' ? 'more' : 'less'})`);
105
+ continue;
106
+ }
107
+ if (variant === 'rtl' || variant === 'ltr') {
108
+ selector = `:where([dir="${variant}"]) ${selector}`;
109
+ continue;
110
+ }
111
+ if (variant === 'starting') {
112
+ atRules.push('@starting-style');
113
+ continue;
114
+ }
115
+ if (variant.startsWith('supports-[') && variant.endsWith(']')) {
116
+ const query = variant.slice(10, -1).replace(/_/g, ' ');
117
+ if (!safeQuery(query))
118
+ return;
119
+ atRules.push(`@supports (${query})`);
120
+ continue;
121
+ }
122
+ if (variant.startsWith('media-[') && variant.endsWith(']')) {
123
+ const query = variant.slice(7, -1).replace(/_/g, ' ');
124
+ if (!safeQuery(query))
125
+ return;
126
+ atRules.push(`@media (${query})`);
127
+ continue;
128
+ }
129
+ if (variant.startsWith('container-[') && variant.endsWith(']')) {
130
+ const query = variant.slice(11, -1).replace(/_/g, ' ');
131
+ if (!safeQuery(query))
132
+ return;
133
+ atRules.push(`@container (${query})`);
134
+ continue;
135
+ }
136
+ if (variant.startsWith('cq-')) {
137
+ const key = variant.slice(3);
138
+ if (!Object.hasOwn(theme.screens, key))
139
+ return;
140
+ const screen = String(theme.screens[key]);
141
+ if (!/^(?:\d+(?:\.\d+)?)(?:px|rem|em)$/.test(screen))
142
+ return;
143
+ atRules.push(`@container (min-width: ${screen})`);
144
+ continue;
145
+ }
146
+ if (variant === 'group-hover' || variant === 'group-focus') {
147
+ groupPeer = `.group:${variant.slice(6)} ` + groupPeer;
148
+ continue;
149
+ }
150
+ if (variant === 'peer-checked' || variant === 'peer-focus') {
151
+ groupPeer = `.peer:${variant.slice(5)} ~ ` + groupPeer;
152
+ continue;
153
+ }
154
+ if (variant in pseudo) {
155
+ selector += pseudo[variant];
156
+ continue;
157
+ }
158
+ if (variant.startsWith('has-[') && variant.endsWith(']')) {
159
+ const nested = variant.slice(5, -1);
160
+ if (!safeSelector(nested))
161
+ return;
162
+ selector += `:has(${nested})`;
163
+ continue;
164
+ }
165
+ if (variant.startsWith('not-[') && variant.endsWith(']')) {
166
+ const nested = variant.slice(5, -1);
167
+ if (!safeSelector(nested))
168
+ return;
169
+ selector += `:not(${nested})`;
170
+ continue;
171
+ }
172
+ if (variant.startsWith('aria-')) {
173
+ const attr = variant.slice(5);
174
+ if (!/^[a-z-]+$/.test(attr))
175
+ return;
176
+ selector += `[aria-${attr}="true"]`;
177
+ continue;
178
+ }
179
+ if (variant.startsWith('data-')) {
180
+ const attr = variant.slice(5);
181
+ if (!/^[a-z-]+$/.test(attr))
182
+ return;
183
+ selector += `[data-${attr}]`;
184
+ continue;
185
+ }
186
+ return;
187
+ }
188
+ selector = groupPeer + selector;
189
+ let rule = `${selector}{${body}}`;
190
+ for (const atRule of atRules.reverse())
191
+ rule = `${atRule}{${rule}}`;
192
+ return rule;
193
+ }
194
+ function generate(tokens) {
195
+ const classSet = new Set();
196
+ const add = (token) => { if (typeof token !== 'string')
197
+ throw new Error('zuix: class tokens must be strings'); classSet.add(token); if (classSet.size > limits.maxClasses)
198
+ throw new Error('zuix: maxClasses limit exceeded'); };
199
+ for (const token of tokens)
200
+ add(token);
201
+ for (const token of config.safelist ?? [])
202
+ add(token);
203
+ const classes = [...classSet].filter(Boolean).sort();
204
+ const unmatched = [];
205
+ const rules = [];
206
+ for (const name of classes) {
207
+ const rule = compileClass(name);
208
+ if (rule)
209
+ rules.push(rule);
210
+ else
211
+ unmatched.push(name);
212
+ }
213
+ // Merge identical declaration blocks only when they occupy the same at-rule context.
214
+ // Never merge distinct declarations or reorder conflicting rules.
215
+ const merged = [];
216
+ const seen = new Set();
217
+ for (const rule of rules) {
218
+ if (!seen.has(rule)) {
219
+ seen.add(rule);
220
+ merged.push(rule);
221
+ }
222
+ }
223
+ const builtin = {
224
+ 'zuix-spin': 'to{transform:rotate(360deg)}',
225
+ 'zuix-pulse': '50%{opacity:.5}',
226
+ 'zuix-bounce': '0%,100%{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}',
227
+ 'zuix-ping': '75%,100%{transform:scale(2);opacity:0}'
228
+ };
229
+ const frames = { ...builtin, ...config.keyframes };
230
+ const usedRules = merged.join('');
231
+ const keyframes = Object.entries(frames).filter(([name]) => /^[a-zA-Z][\w-]{0,79}$/.test(name) && usedRules.includes(name) && new RegExp(`\\b${name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(usedRules)).map(([name, value]) => `@keyframes ${name}{${value}}`);
232
+ const chunks = [config.preflight === false ? '' : preflight, ...base, ...keyframes, ...merged].filter(Boolean);
233
+ return { css: chunks.join(config.minify ? '' : '\n'), classes, unmatched };
234
+ }
235
+ return { config, theme, compileClass, generate };
236
+ }
237
+ export function generateCSS(classes, config = {}) { return createZuix(config).generate(classes).css; }
238
+ //# sourceMappingURL=compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export { createZuix, generateCSS, preflight } from './compiler.js';
2
+ export { extractClasses } from './scanner.js';
3
+ export { defaultTheme, resolveTheme } from './theme.js';
4
+ export { utilityFor } from './utilities.js';
5
+ export { injectZuix, renderZuixStyle, zuixVite } from './adapters.js';
6
+ export type { ZuixConfig, ZuixTheme, ZuixPlugin, ZuixPluginAPI, GenerateResult } from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { createZuix, generateCSS, preflight } from './compiler.js';
2
+ export { extractClasses } from './scanner.js';
3
+ export { defaultTheme, resolveTheme } from './theme.js';
4
+ export { utilityFor } from './utilities.js';
5
+ export { injectZuix, renderZuixStyle, zuixVite } from './adapters.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,WAAW,EAAC,SAAS,EAAC,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAC,YAAY,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AACrD,OAAO,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAC,UAAU,EAAC,eAAe,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type { ZuixConfig, GenerateResult } from './types.js';
2
+ export declare function createProjectScanner(root: string, config?: ZuixConfig): {
3
+ scan: () => Map<string, string[]>;
4
+ clear: () => void;
5
+ };
6
+ export declare function scanProjectFiles(root: string, config?: ZuixConfig): Map<string, string[]>;
7
+ export declare function scanProject(root: string, config?: ZuixConfig): string[];
8
+ /** Output paths cannot escape the project root. */
9
+ export declare function buildZuix(root?: string, config?: ZuixConfig): GenerateResult;
10
+ /** Polling watcher with incremental class extraction. Reports recoverable errors and keeps watching. */
11
+ export declare function watchZuix(root?: string, config?: ZuixConfig, onBuild?: (result: GenerateResult) => void, onError?: (error: unknown) => void): () => void;
package/dist/node.js ADDED
@@ -0,0 +1,184 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { createZuix } from './compiler.js';
4
+ import { extractClasses } from './scanner.js';
5
+ import { resolveLimits } from './safety.js';
6
+ const supported = /\.(?:html?|jsx?|tsx?|vue|svelte|astro|mdx?)$/i;
7
+ const defaultExcluded = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.nuxt', '.zerux', '.output', 'coverage', '.cache']);
8
+ function globRegex(pattern) {
9
+ let s = '^';
10
+ const normalized = pattern.replace(/\\/g, '/').replace(/^\.\//, '');
11
+ if (normalized.length > 500)
12
+ throw new Error('zuix: glob too long');
13
+ for (let i = 0; i < normalized.length; i++) {
14
+ const ch = normalized[i];
15
+ if (ch === '*') {
16
+ if (normalized[i + 1] === '*') {
17
+ i++;
18
+ if (normalized[i + 1] === '/') {
19
+ i++;
20
+ s += '(?:.*/)?';
21
+ }
22
+ else
23
+ s += '.*';
24
+ }
25
+ else
26
+ s += '[^/]*';
27
+ }
28
+ else if (ch === '?')
29
+ s += '[^/]';
30
+ else
31
+ s += ch.replace(/[.+^${}()|[\]\\]/g, '\\$&');
32
+ }
33
+ return new RegExp(s + '$');
34
+ }
35
+ function expandBraces(pattern) {
36
+ const match = /\{([^{}]+)\}/.exec(pattern);
37
+ if (!match)
38
+ return [pattern];
39
+ const results = match[1].split(',').flatMap(part => expandBraces(pattern.slice(0, match.index) + part + pattern.slice(match.index + match[0].length)));
40
+ if (results.length > 100)
41
+ throw new Error('zuix: too many content globs');
42
+ return results;
43
+ }
44
+ export function createProjectScanner(root, config = {}) {
45
+ const absoluteRoot = path.resolve(root), limits = resolveLimits(config.limits);
46
+ const patterns = (config.content?.length ? config.content : ['**/*.{html,js,jsx,ts,tsx,vue,svelte,astro,md,mdx}']).flatMap(expandBraces).map(globRegex);
47
+ const excluded = (config.exclude ?? []).flatMap(expandBraces).map(globRegex);
48
+ const cache = new Map();
49
+ const perFileDir = config.perFile ? path.resolve(absoluteRoot, typeof config.perFile === 'object' ? (config.perFile.dir ?? 'zuix-files') : 'zuix-files') : '';
50
+ function scan() {
51
+ const files = new Map();
52
+ let totalBytes = 0, visited = 0;
53
+ const nextCache = new Map();
54
+ function visit(dir) {
55
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
56
+ if (++visited > limits.maxFiles * 20)
57
+ throw new Error('zuix: directory traversal limit exceeded');
58
+ if (entry.isSymbolicLink() || defaultExcluded.has(entry.name) || entry.name.startsWith('.env'))
59
+ continue;
60
+ const abs = path.join(dir, entry.name), rel = path.relative(absoluteRoot, abs).split(path.sep).join('/');
61
+ if (excluded.some(p => p.test(rel)))
62
+ continue;
63
+ if (entry.isDirectory()) {
64
+ if (abs === perFileDir)
65
+ continue;
66
+ visit(abs);
67
+ }
68
+ else if (entry.isFile() && supported.test(entry.name) && patterns.some(p => p.test(rel))) {
69
+ if (files.size >= limits.maxFiles)
70
+ throw new Error('zuix: maxFiles limit exceeded');
71
+ const stat = fs.statSync(abs);
72
+ if (stat.size > limits.maxFileBytes)
73
+ throw new Error(`zuix: maxFileBytes exceeded: ${rel}`);
74
+ totalBytes += stat.size;
75
+ if (totalBytes > limits.maxTotalBytes)
76
+ throw new Error('zuix: maxTotalBytes limit exceeded');
77
+ const old = cache.get(rel);
78
+ const classes = old && old.size === stat.size && old.mtimeMs === stat.mtimeMs ? old.classes : extractClasses(fs.readFileSync(abs, 'utf8'));
79
+ files.set(rel, classes);
80
+ nextCache.set(rel, { size: stat.size, mtimeMs: stat.mtimeMs, classes });
81
+ }
82
+ }
83
+ }
84
+ visit(absoluteRoot);
85
+ cache.clear();
86
+ for (const [key, value] of nextCache)
87
+ cache.set(key, value);
88
+ return files;
89
+ }
90
+ return { scan, clear: () => cache.clear() };
91
+ }
92
+ export function scanProjectFiles(root, config = {}) { return createProjectScanner(root, config).scan(); }
93
+ export function scanProject(root, config = {}) { return [...new Set([...scanProjectFiles(root, config).values()].flat())]; }
94
+ function inside(root, location) { const relative = path.relative(root, location); return relative !== '' && !relative.startsWith('..' + path.sep) && relative !== '..' && !path.isAbsolute(relative); }
95
+ function outputPath(root, target) {
96
+ const location = path.resolve(root, target);
97
+ if (!inside(path.resolve(root), location))
98
+ throw new Error('zuix: output must remain inside project root');
99
+ let current = path.resolve(root);
100
+ for (const segment of path.relative(current, location).split(path.sep)) {
101
+ current = path.join(current, segment);
102
+ try {
103
+ if (fs.lstatSync(current).isSymbolicLink())
104
+ throw new Error('zuix: symlink output path denied');
105
+ }
106
+ catch (error) {
107
+ if (error.code !== 'ENOENT')
108
+ throw error;
109
+ }
110
+ }
111
+ return location;
112
+ }
113
+ function writeIfChanged(file, content) {
114
+ fs.mkdirSync(path.dirname(file), { recursive: true });
115
+ if (fs.existsSync(file) && fs.lstatSync(file).isSymbolicLink())
116
+ throw new Error(`zuix: refusing symlink output ${file}`);
117
+ if (!fs.existsSync(file) || fs.readFileSync(file, 'utf8') !== content)
118
+ fs.writeFileSync(file, content);
119
+ }
120
+ function buildFromFiles(root, config, files) {
121
+ const result = createZuix(config).generate(new Set([...files.values()].flat()));
122
+ const settings = typeof config.perFile === 'object' ? config.perFile : {};
123
+ if (!config.perFile || settings.shared !== false) {
124
+ writeIfChanged(outputPath(root, config.output ?? 'zuix.css'), result.css + '\n');
125
+ }
126
+ if (config.perFile) {
127
+ const directory = outputPath(root, settings.dir ?? 'zuix-files');
128
+ const manifest = Object.create(null);
129
+ for (const [source, classes] of files) {
130
+ const dest = outputPath(root, path.join(directory, source + '.css'));
131
+ if (!inside(directory, dest))
132
+ throw new Error('zuix: invalid source filename');
133
+ const css = createZuix({ ...config, preflight: false, safelist: [] }).generate(classes).css;
134
+ writeIfChanged(dest, css + '\n');
135
+ manifest[source] = path.relative(root, dest).split(path.sep).join('/');
136
+ }
137
+ const manifestFile = path.join(directory, 'manifest.json');
138
+ if (fs.existsSync(manifestFile)) {
139
+ const previous = JSON.parse(fs.readFileSync(manifestFile, 'utf8'));
140
+ for (const [source, filename] of Object.entries(previous)) {
141
+ if (Object.hasOwn(manifest, source) || typeof filename !== 'string' || !filename.endsWith(source + '.css'))
142
+ continue;
143
+ const stale = outputPath(root, filename);
144
+ if (inside(directory, stale) && fs.existsSync(stale) && fs.lstatSync(stale).isFile())
145
+ fs.unlinkSync(stale);
146
+ }
147
+ }
148
+ writeIfChanged(manifestFile, JSON.stringify(manifest, null, 2) + '\n');
149
+ }
150
+ return result;
151
+ }
152
+ /** Output paths cannot escape the project root. */
153
+ export function buildZuix(root = process.cwd(), config = {}) {
154
+ const absolute = path.resolve(root);
155
+ return buildFromFiles(absolute, config, scanProjectFiles(absolute, config));
156
+ }
157
+ /** Polling watcher with incremental class extraction. Reports recoverable errors and keeps watching. */
158
+ export function watchZuix(root = process.cwd(), config = {}, onBuild, onError) {
159
+ const absolute = path.resolve(root), scanner = createProjectScanner(absolute, config);
160
+ let previous = '', active = true;
161
+ const tick = () => {
162
+ if (!active)
163
+ return;
164
+ try {
165
+ const files = scanner.scan();
166
+ const next = JSON.stringify([...files]);
167
+ if (next !== previous) {
168
+ const result = buildFromFiles(absolute, config, files);
169
+ previous = next;
170
+ onBuild?.(result);
171
+ }
172
+ }
173
+ catch (error) {
174
+ if (onError)
175
+ onError(error);
176
+ else
177
+ console.error('[zuix] watch:', error);
178
+ }
179
+ };
180
+ tick();
181
+ const timer = setInterval(tick, 500);
182
+ return () => { active = false; clearInterval(timer); scanner.clear(); };
183
+ }
184
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /** CSS from utility tokens is deliberately a restricted subset, not arbitrary authored CSS.
2
+ * Plugins and addBase() remain trusted application code. */
3
+ export declare const DEFAULT_LIMITS: Readonly<{
4
+ maxFiles: 20000;
5
+ maxFileBytes: number;
6
+ maxTotalBytes: number;
7
+ maxClasses: 50000;
8
+ maxTokenLength: 256;
9
+ }>;
10
+ export type ZuixLimits = Partial<typeof DEFAULT_LIMITS>;
11
+ export declare function resolveLimits(input?: ZuixLimits): Record<keyof typeof DEFAULT_LIMITS, number>;
12
+ export declare function safeCssValue(value: string): boolean;
13
+ export declare function safeDeclaration(property: string, value: string): boolean;
14
+ export declare function safeCondition(value: string): boolean;
15
+ export declare function cssEscapeClass(name: string): string;
package/dist/safety.js ADDED
@@ -0,0 +1,45 @@
1
+ /** CSS from utility tokens is deliberately a restricted subset, not arbitrary authored CSS.
2
+ * Plugins and addBase() remain trusted application code. */
3
+ export const DEFAULT_LIMITS = Object.freeze({ maxFiles: 20000, maxFileBytes: 1024 * 1024, maxTotalBytes: 64 * 1024 * 1024, maxClasses: 50000, maxTokenLength: 256 });
4
+ export function resolveLimits(input = {}) {
5
+ const result = { ...DEFAULT_LIMITS };
6
+ for (const key of Object.keys(result)) {
7
+ const value = input[key];
8
+ if (value !== undefined) {
9
+ if (!Number.isSafeInteger(value) || value < 1 || value > DEFAULT_LIMITS[key] * 16)
10
+ throw new Error(`zuix: invalid ${key} limit`);
11
+ result[key] = value;
12
+ }
13
+ }
14
+ return result;
15
+ }
16
+ export function safeCssValue(value) {
17
+ // eslint-disable-next-line no-control-regex -- Intentionally matches control characters for validation or output sanitization.
18
+ if (!value || value.length > 512 || /[\u0000-\u001f\u007f{};<>\\"'`]/.test(value) || /\/\*|\*\/|!\s*important|@(?:import|charset)|\b(?:url|image-set|expression|behavior)\s*\(/i.test(value))
19
+ return false;
20
+ // Parentheses must balance. Disallow closing out of the active declaration.
21
+ let depth = 0;
22
+ for (const c of value) {
23
+ if (c === '(') {
24
+ if (++depth > 8)
25
+ return false;
26
+ }
27
+ else if (c === ')' && --depth < 0)
28
+ return false;
29
+ }
30
+ return depth === 0;
31
+ }
32
+ export function safeDeclaration(property, value) {
33
+ return /^(?:--[\w-]+|-?[a-z][a-z0-9-]*)$/i.test(property) && property.length <= 100 && safeCssValue(value);
34
+ }
35
+ export function safeCondition(value) {
36
+ return value.length > 0 && value.length <= 160 && /^[a-zA-Z0-9\s:.,#%()[\]_<>=!+-]+$/.test(value) && !/(?:url|expression)\s*\(/i.test(value);
37
+ }
38
+ export function cssEscapeClass(name) {
39
+ return [...name].map((c, i) => {
40
+ if ((i === 0 && /[0-9]/.test(c)) || (i === 1 && name[0] === '-' && /[0-9]/.test(c)))
41
+ return `\\${c.codePointAt(0).toString(16)} `;
42
+ return /[a-zA-Z0-9_-]/.test(c) ? c : `\\${c.codePointAt(0).toString(16)} `;
43
+ }).join('');
44
+ }
45
+ //# sourceMappingURL=safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.js","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ /** Extract literal utility tokens from HTML, JSX, TSX, Vue, Svelte, and Zyro template sources. */
2
+ export declare function extractClasses(source: string): string[];
@@ -0,0 +1,20 @@
1
+ /** Extract literal utility tokens from HTML, JSX, TSX, Vue, Svelte, and Zyro template sources. */
2
+ export function extractClasses(source) {
3
+ const result = new Set();
4
+ const add = (value) => { for (const token of value.split(/\s+/))
5
+ if (token && !/[<>{}`$]/.test(token))
6
+ result.add(token); };
7
+ // Attribute literals, including className/class and class directives.
8
+ const attrs = /(?:\bclass(?:Name)?|\bclass)\s*=\s*(?:["']([^"']*)["']|\{\s*["'`]([^"'`]*?)["'`]\s*\})/g;
9
+ for (const match of source.matchAll(attrs))
10
+ add(match[1] ?? match[2] ?? '');
11
+ for (const match of source.matchAll(/\bclass:([\w:![\]#%./-]+)/g))
12
+ add(match[1]);
13
+ // String values in class composition helpers, including cn, clsx, cx, and classNames.
14
+ for (const match of source.matchAll(/\b(?:cn|clsx|cx|classNames)\s*\(([\s\S]*?)\)/g)) {
15
+ for (const literal of match[1].matchAll(/["'`]([^"'`]+)["'`]/g))
16
+ add(literal[1]);
17
+ }
18
+ return [...result];
19
+ }
20
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,MAAM,UAAU,cAAc,CAAC,MAAa;IAC3C,MAAM,MAAM,GAAC,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAC,CAAC,KAAY,EAAC,EAAE,GAAC,KAAI,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;QAAC,IAAG,KAAK,IAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA,CAAC,CAAC;IACvH,sEAAsE;IACtE,MAAM,KAAK,GAAC,yFAAyF,CAAC;IACtG,KAAI,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAE,KAAK,CAAC,CAAC,CAAC,IAAE,EAAE,CAAC,CAAC;IACtE,KAAI,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,4BAA4B,CAAC;QAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,sFAAsF;IACtF,KAAI,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,+CAA+C,CAAC,EAAC,CAAC;QACpF,KAAI,MAAM,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ZuixTheme, ZuixConfig } from './types.js';
2
+ export declare const defaultTheme: ZuixTheme;
3
+ export declare function resolveTheme(config?: ZuixConfig): ZuixTheme;