@styleframe/scanner 3.1.1 → 3.1.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @styleframe/scanner
2
2
 
3
+ ## 3.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#221](https://github.com/styleframe-dev/styleframe/pull/221) [`6d406c2`](https://github.com/styleframe-dev/styleframe/commit/6d406c289b39c666a3fb7468aa3ec08f5a6d316b) Thanks [@alexgrozav](https://github.com/alexgrozav)! - Add `treeshake` option to remove unused variables from CSS output.
8
+
9
+ `root._usage` now tracks both `variables` and `utilities` referenced during config execution and scanner registration. The transpiler's new `treeshake: true` option filters `root.variables` and theme variables down to only those present in `_usage.variables`. The plugin enables treeshaking by default when generating global CSS.
10
+
11
+ - Updated dependencies [[`6d406c2`](https://github.com/styleframe-dev/styleframe/commit/6d406c289b39c666a3fb7468aa3ec08f5a6d316b)]:
12
+ - @styleframe/core@3.5.0
13
+
3
14
  ## 3.1.1
4
15
 
5
16
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const J=require("node:fs/promises"),W=require("fast-glob"),O=require("@styleframe/core");function V(s){let e=0;for(let t=0;t<s.length;t++){const n=s.charCodeAt(t);e=(e<<5)-e+n,e=e&e}return`${e.toString(16)}-${s.length}`}function D(){const s=new Map;return{get(e){return s.get(e)?.result??null},set(e,t,n){s.set(e,{hash:n,result:t,timestamp:Date.now()})},isValid(e,t){const n=s.get(e);return n!==void 0&&n.hash===t},getIfValid(e,t){const n=s.get(e);return n&&n.hash===t?n.result:null},invalidate(e){s.delete(e)},clear(){s.clear()}}}const $=/_[a-zA-Z][a-zA-Z0-9-]*(?::[a-zA-Z0-9._-]+|:\[[^\]]+\])*/g,j=/^\[(.+)\]$/,ee=["html","htm","vue","svelte","jsx","tsx","js","ts","astro","mdx","php","erb","twig","blade.php"],X=["**/node_modules/**","**/.git/**","**/dist/**","**/build/**","**/.next/**","**/.nuxt/**","**/coverage/**"];function C(s){if(!s.startsWith("_"))return null;const e=s.slice(1);if(!e)return null;const t=te(e);if(t.length===0)return null;let n,r,c=[];t.length===1?(n=t[0],r="default"):(r=t[t.length-1],n=t[t.length-2],c=t.slice(0,-2));let a=!1,l;const f=r.match(j);return f&&(a=!0,l=f[1]),{raw:s,name:n,value:r,modifiers:c,isArbitrary:a,arbitraryValue:l}}function te(s){const e=[];let t="",n=0;for(const r of s)r==="["?(n++,t+=r):r==="]"?(n--,t+=r):r===":"&&n===0?(t&&e.push(t),t=""):t+=r;return n!==0?[]:(t&&e.push(t),e)}function S(s,e){const t=s.match(e??$);return t?[...new Set(t)]:[]}function se(s,e,t=[]){const n=[...t,s];return e!=="default"&&n.push(e),`_${n.join(":")}`}const _=/\bclassName\s*=\s*\{/g,U=/\bclass\s*=\s*\{/g,F=/\bclass\s*=\s*["']([^"']+)["']/gi,I=/\bclassName\s*=\s*["']([^"']+)["']/gi,M=/\bclass:([^\s={>]+)/g,b=/'([^'\\]*(?:\\.[^'\\]*)*)'/g,L=/"([^"\\]*(?:\\.[^"\\]*)*)"/g,P=/`([^`\\]*(?:\\.[^`\\]*)*)`/g;function k(s){let e=1,t=0;for(;t<s.length&&e>0;){const n=s[t];n==="{"?e++:n==="}"&&e--,t++}return e!==0?null:s.slice(0,t-1)}function ne(s){const e=[];_.lastIndex=0;let t;for(;(t=_.exec(s))!==null;){const n=t.index+t[0].length,r=s.slice(n),c=k(r);c!==null&&e.push(c)}return e}function re(s){const e=[];U.lastIndex=0;let t;for(;(t=U.exec(s))!==null;){const n=t.index+t[0].length,r=s.slice(n),c=k(r);c!==null&&e.push(c)}return e}function u(s,e){const t=[];F.lastIndex=0;let n;for(;(n=F.exec(s))!==null;)n[1]&&t.push(...S(n[1],e));return t}function y(s,e){const t=[];I.lastIndex=0;let n;for(;(n=I.exec(s))!==null;)n[1]&&t.push(...S(n[1],e));const r=ne(s);for(const c of r)t.push(...m(c,e));return[...new Set(t)]}function z(s,e){const t=[],n=s.match(/<template[^>]*>([\s\S]*?)<\/template>/i);n?.[1]&&(t.push(...u(n[1],e)),t.push(...m(n[1],e)));const r=s.match(/<script[^>]*>([\s\S]*?)<\/script>/i);return r?.[1]&&t.push(...m(r[1],e)),[...new Set(t)]}function B(s,e){const t=[];t.push(...u(s,e));const n=re(s);for(const a of n)t.push(...m(a,e));M.lastIndex=0;let r;for(;(r=M.exec(s))!==null;)r[1]&&t.push(r[1]);const c=s.match(/<script[^>]*>([\s\S]*?)<\/script>/i);return c?.[1]&&t.push(...m(c[1],e)),[...new Set(t)]}function G(s,e){const t=[];t.push(...u(s,e)),t.push(...y(s,e));const n=s.match(/^---\n([\s\S]*?)\n---/);return n?.[1]&&t.push(...m(n[1],e)),[...new Set(t)]}function m(s,e){const t=[];let n;for(b.lastIndex=0;(n=b.exec(s))!==null;)n[1]&&t.push(...S(n[1],e));for(L.lastIndex=0;(n=L.exec(s))!==null;)n[1]&&t.push(...S(n[1],e));for(P.lastIndex=0;(n=P.exec(s))!==null;)n[1]&&t.push(...S(n[1],e));return t}function q(s,e){const t=[];return t.push(...u(s,e)),t.push(...y(s,e)),[...new Set(t)]}const ce={html:u,htm:u,vue:z,svelte:B,jsx:y,tsx:y,js:m,ts:m,astro:G,mdx:q,php:u,erb:u,twig:u,"blade.php":u};function ae(s){if(s.endsWith(".blade.php"))return"blade.php";const e=s.split(".");return e[e.length-1]?.toLowerCase()??""}function N(s,e,t,n){const r=[],c=ae(e);if(t)for(const l of t)r.push(...l(s,e));const a=ce[c];return a?r.push(...a(s,n)):r.push(...m(s,n)),[...new Set(r)]}function v(s,e){if(e.length===0)return s;const t=[...e].sort().join(",");return`${s}|${t}`}function H(s,e){const t=new Map,n=new Map,r=new Map;for(const a of e.utilities){t.set(a.name,a);const l=new Set;for(const f of a.values)l.add(v(f.key,f.modifiers));r.set(a,l)}for(const a of e.modifiers)for(const l of a.key)n.set(l,a);const c=[];for(const a of s){const l=t.get(a.name)??null,f=[];for(const E of a.modifiers){const A=n.get(E);A&&f.push(A)}let T=!1;if(l){const E=v(a.value,a.modifiers);T=r.get(l)?.has(E)??!1}c.push({parsed:a,factory:l,modifierFactories:f,exists:T})}return c}function le(s,e){const t=R(s,e);return O.classNameToCssSelector(t)}function R(s,e){return(e??O.defaultUtilitySelectorFn)(s)}function Q(s,e){return t=>{const n=R({name:t.name,value:t.value,modifiers:t.modifiers},e);return s.has(n)}}function ie(s,e,t){const n=Q(e,t);return s.children.filter(r=>r.type!=="utility"?!0:n(r))}function oe(s){const e=new Set;for(const t of s)e.add(t.parsed.raw);return e}function ue(s){return s.filter(e=>e.factory!==null)}function fe(s){return s.filter(e=>e.exists)}function he(s){return s.filter(e=>e.parsed.isArbitrary)}const w=new Map;function me(s){const e=s.replace(/\\/g,"/");if(w.has(e))return w.get(e);if(!e.includes("**")&&!e.includes("*")&&!e.includes("?"))return w.set(e,null),null;try{const t=ge(e),n=new RegExp(`^${t}$`);return w.set(e,n),n}catch{return w.set(e,null),null}}function pe(s,e){let t=null;return(...n)=>{t&&clearTimeout(t),t=setTimeout(()=>{s(...n),t=null},e)}}function Y(s,e={}){const{debounce:t=100}=e,n=new Set;let r=null;const c=()=>{if(n.size>0){const l=[...n];n.clear(),s(l)}};return{onChange:l=>{n.add(l),r&&clearTimeout(r),r=setTimeout(()=>{c(),r=null},t)},flush:c}}function de(s){return s.replace(/[.+^${}()|[\]\\]/g,"\\$&")}function ge(s){return s.replace(/\*\*/g,"<<<GLOBSTAR>>>").replace(/\*/g,"<<<STAR>>>").replace(/\?/g,"<<<QUESTION>>>").split("<<<GLOBSTAR>>>").map(de).join(".*").replace(/<<<STAR>>>/g,"[^/]*").replace(/<<<QUESTION>>>/g,".")}function xe(s,e){const t=s.replace(/\\/g,"/");for(const n of e){const r=me(n);if(r!==null){if(r.test(t))return!0}else{const c=n.replace(/\\/g,"/");if(t===c)return!0}}return!1}function Se(s){const e=D(),t=s.cwd??process.cwd(),n=s.extractors,r=s.utilities?.pattern,c=s.utilities?.parse??C;async function a(){return W(s.content,{cwd:t,absolute:!0,ignore:X})}async function l(i){const h=await J.readFile(i,"utf-8"),d=V(h),p=e.getIfValid(i,d);if(p)return p;const g=N(h,i,n,r),o=g.map(c).filter(Z=>Z!==null),x={path:i,classes:new Set(g),parsed:o,lastScanned:Date.now()};return e.set(i,x,d),x}function f(i,h="inline"){return N(i,h,n,r).map(c).filter(p=>p!==null)}async function T(){const i=await a(),h=new Map,d=new Set,p=[],g=await Promise.all(i.map(async o=>{try{return await l(o)}catch(x){return console.warn(`[styleframe/scanner] Failed to scan ${o}:`,x),null}}));for(const o of g)if(o){h.set(o.path,o);for(const x of o.classes)d.add(x);p.push(...o.parsed)}return{files:h,allClasses:d,allParsed:p}}function E(i,h){return H(i,h)}function A(i){const{onChange:h,flush:d}=Y(async p=>{for(const o of p)e.invalidate(o);const g=await T();i(g)});return()=>{d()}}function K(i){i?e.invalidate(i):e.clear()}return{scan:T,scanFile:l,scanContent:f,match:E,watch:A,invalidate:K}}function Te(s,e="inline.html",t){const n=t?.parse??C;return N(s,e,void 0,t?.pattern).map(n).filter(c=>c!==null)}function Ee(s,e){const t=e?.parse??C;return(n,r="inline")=>N(n,r,s,e?.pattern).map(t).filter(a=>a!==null)}exports.ARBITRARY_VALUE_PATTERN=j;exports.DEFAULT_EXTENSIONS=ee;exports.DEFAULT_IGNORE_PATTERNS=X;exports.UTILITY_CLASS_PATTERN=$;exports.classNameFromUtilityOptions=R;exports.createCache=D;exports.createChangeHandler=Y;exports.createContentScanner=Ee;exports.createScanner=Se;exports.createUtilityFilter=Q;exports.debounce=pe;exports.extractClasses=N;exports.extractFromAstro=G;exports.extractFromHTML=u;exports.extractFromJSX=y;exports.extractFromMDX=q;exports.extractFromStringLiterals=m;exports.extractFromSvelte=B;exports.extractFromVue=z;exports.extractUtilityClasses=S;exports.filterUtilities=ie;exports.generateUtilityClassName=se;exports.generateUtilitySelector=le;exports.getArbitraryMatches=he;exports.getExistingMatches=fe;exports.getUsedClassNames=oe;exports.getValidMatches=ue;exports.hashContent=V;exports.matchUtilities=H;exports.matchesPatterns=xe;exports.parseUtilityClass=C;exports.quickScan=Te;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./watcher-C8V8DPY6.cjs"),f=require("@styleframe/core");function p(n,s="inline.html",i){const c=i?.parse??e.parseUtilityClass;return e.extractClasses(n,s,void 0,i?.pattern).map(c).filter(t=>t!==null)}function g(n,s){const i=s?.parse??e.parseUtilityClass;return(c,l="inline")=>e.extractClasses(c,l,n,s?.pattern).map(i).filter(r=>r!==null)}function U(n,s){for(const t of s)t.factory&&n._usage.utilities.add(f.defaultUtilitySelectorFn({name:t.parsed.name,value:t.parsed.value,modifiers:t.parsed.modifiers}));const i=s.filter(t=>t.factory!==null&&!t.exists);if(i.length===0)return 0;const c=new Map;for(const t of i){const r=t.factory,m=`${r.name}:${t.parsed.value}`,o=c.get(m),a=t.modifierFactories.length>1?t.modifierFactories:t.modifierFactories[0];if(!o)c.set(m,{factory:r,parsed:t.parsed,modifierGroups:a?[a]:[]});else if(a){const y=Array.isArray(a)?a.map(u=>u.key.join(",")).join("|"):a.key.join(",");o.modifierGroups.some(u=>(Array.isArray(u)?u.map(d=>d.key.join(",")).join("|"):u.key.join(","))===y)||o.modifierGroups.push(a)}}let l=0;for(const{factory:t,parsed:r,modifierGroups:m}of c.values()){const o=m.length>0?m:void 0;if(r.isArbitrary&&r.arbitraryValue!==void 0)t.create({[r.value]:r.arbitraryValue},o);else{const a=t.autogenerate(`@${r.value}`);t.create(a,o)}l++}return l}exports.ARBITRARY_VALUE_PATTERN=e.ARBITRARY_VALUE_PATTERN;exports.DEFAULT_EXTENSIONS=e.DEFAULT_EXTENSIONS;exports.DEFAULT_IGNORE_PATTERNS=e.DEFAULT_IGNORE_PATTERNS;exports.UTILITY_CLASS_PATTERN=e.UTILITY_CLASS_PATTERN;exports.classNameFromUtilityOptions=e.classNameFromUtilityOptions;exports.createCache=e.createCache;exports.createChangeHandler=e.createChangeHandler;exports.createUtilityFilter=e.createUtilityFilter;exports.debounce=e.debounce;exports.extractClasses=e.extractClasses;exports.extractFromAstro=e.extractFromAstro;exports.extractFromHTML=e.extractFromHTML;exports.extractFromJSX=e.extractFromJSX;exports.extractFromMDX=e.extractFromMDX;exports.extractFromStringLiterals=e.extractFromStringLiterals;exports.extractFromSvelte=e.extractFromSvelte;exports.extractFromVue=e.extractFromVue;exports.extractUtilityClasses=e.extractUtilityClasses;exports.filterUtilities=e.filterUtilities;exports.generateUtilityClassName=e.generateUtilityClassName;exports.generateUtilitySelector=e.generateUtilitySelector;exports.getArbitraryMatches=e.getArbitraryMatches;exports.getExistingMatches=e.getExistingMatches;exports.getUsedClassNames=e.getUsedClassNames;exports.getValidMatches=e.getValidMatches;exports.hashContent=e.hashContent;exports.matchUtilities=e.matchUtilities;exports.matchesPatterns=e.matchesPatterns;exports.parseUtilityClass=e.parseUtilityClass;exports.createContentScanner=g;exports.quickScan=p;exports.registerMatchedUtilities=U;
package/dist/index.d.ts CHANGED
@@ -59,24 +59,6 @@ export declare function createChangeHandler(callback: (changedFiles: string[]) =
59
59
  */
60
60
  export declare function createContentScanner(customExtractors?: Extractor[], utilities?: ScannerUtilitiesConfig): (content: string, filePath?: string) => ParsedUtility[];
61
61
 
62
- /**
63
- * Create a scanner instance for detecting utility classes in content files.
64
- *
65
- * @param config Scanner configuration
66
- * @returns Scanner instance
67
- *
68
- * @example
69
- * ```ts
70
- * const scanner = createScanner({
71
- * content: ['./src/components/*.tsx', './src/pages/*.vue'],
72
- * });
73
- *
74
- * const result = await scanner.scan();
75
- * const matches = scanner.match(result.allParsed, root);
76
- * ```
77
- */
78
- export declare function createScanner(config: ScannerConfig): Scanner;
79
-
80
62
  /**
81
63
  * Create a filter function that checks if a utility is in the used set.
82
64
  *
@@ -303,6 +285,23 @@ export declare function parseUtilityClass(className: string): ParsedUtility | nu
303
285
  */
304
286
  export declare function quickScan(content: string, filePath?: string, utilities?: ScannerUtilitiesConfig): ParsedUtility[];
305
287
 
288
+ /**
289
+ * Register utility values detected by the scanner that don't yet exist on the root.
290
+ *
291
+ * For non-arbitrary values, uses the factory's autogenerate function (treating the
292
+ * value key as a token reference). For arbitrary values, registers with the literal
293
+ * CSS value directly.
294
+ *
295
+ * Registration happens via `factory.create(...)` on each matched factory, which is
296
+ * already bound to the `root` that produced the matches via `matchUtilities(parsed, root)`.
297
+ * The `root` parameter is part of the signature to document the mutation target.
298
+ *
299
+ * @param root The Styleframe root that will receive the new utilities
300
+ * @param matches Scanner match results produced from this same root
301
+ * @returns Number of newly registered values
302
+ */
303
+ export declare function registerMatchedUtilities(_root: Root, matches: UtilityMatch[]): number;
304
+
306
305
  /**
307
306
  * Scanner instance interface
308
307
  */
package/dist/index.js CHANGED
@@ -1,496 +1,94 @@
1
- import { readFile as D } from "node:fs/promises";
2
- import j from "fast-glob";
3
- import { classNameToCssSelector as z, defaultUtilitySelectorFn as k } from "@styleframe/core";
4
- function B(s) {
5
- let e = 0;
6
- for (let t = 0; t < s.length; t++) {
7
- const n = s.charCodeAt(t);
8
- e = (e << 5) - e + n, e = e & e;
9
- }
10
- return `${e.toString(16)}-${s.length}`;
11
- }
12
- function G() {
13
- const s = /* @__PURE__ */ new Map();
14
- return {
15
- get(e) {
16
- return s.get(e)?.result ?? null;
17
- },
18
- set(e, t, n) {
19
- s.set(e, {
20
- hash: n,
21
- result: t,
22
- timestamp: Date.now()
1
+ import { p as f, e as u } from "./watcher-Bn_8hGt2.js";
2
+ import { A as v, D as E, z as C, U as _, l as j, v as k, x as L, n as M, w as R, h as b, b as D, c as G, i as I, j as V, f as P, d as K, a as O, o as X, g as $, k as q, t as w, s as H, q as Y, r as z, u as B, m as J, y as Q } from "./watcher-Bn_8hGt2.js";
3
+ import { defaultUtilitySelectorFn as y } from "@styleframe/core";
4
+ function U(n, r = "inline.html", s) {
5
+ const i = s?.parse ?? f;
6
+ return u(
7
+ n,
8
+ r,
9
+ void 0,
10
+ s?.pattern
11
+ ).map(i).filter((e) => e !== null);
12
+ }
13
+ function x(n, r) {
14
+ const s = r?.parse ?? f;
15
+ return (i, c = "inline") => u(
16
+ i,
17
+ c,
18
+ n,
19
+ r?.pattern
20
+ ).map(s).filter((t) => t !== null);
21
+ }
22
+ function N(n, r) {
23
+ for (const e of r)
24
+ e.factory && n._usage.utilities.add(
25
+ y({
26
+ name: e.parsed.name,
27
+ value: e.parsed.value,
28
+ modifiers: e.parsed.modifiers
29
+ })
30
+ );
31
+ const s = r.filter((e) => e.factory !== null && !e.exists);
32
+ if (s.length === 0)
33
+ return 0;
34
+ const i = /* @__PURE__ */ new Map();
35
+ for (const e of s) {
36
+ const t = e.factory, l = `${t.name}:${e.parsed.value}`, o = i.get(l), a = e.modifierFactories.length > 1 ? e.modifierFactories : e.modifierFactories[0];
37
+ if (!o)
38
+ i.set(l, {
39
+ factory: t,
40
+ parsed: e.parsed,
41
+ modifierGroups: a ? [a] : []
23
42
  });
24
- },
25
- isValid(e, t) {
26
- const n = s.get(e);
27
- return n !== void 0 && n.hash === t;
28
- },
29
- getIfValid(e, t) {
30
- const n = s.get(e);
31
- return n && n.hash === t ? n.result : null;
32
- },
33
- invalidate(e) {
34
- s.delete(e);
35
- },
36
- clear() {
37
- s.clear();
43
+ else if (a) {
44
+ const p = Array.isArray(a) ? a.map((m) => m.key.join(",")).join("|") : a.key.join(",");
45
+ o.modifierGroups.some((m) => (Array.isArray(m) ? m.map((d) => d.key.join(",")).join("|") : m.key.join(",")) === p) || o.modifierGroups.push(a);
38
46
  }
39
- };
40
- }
41
- const X = /_[a-zA-Z][a-zA-Z0-9-]*(?::[a-zA-Z0-9._-]+|:\[[^\]]+\])*/g, Q = /^\[(.+)\]$/, he = [
42
- "html",
43
- "htm",
44
- "vue",
45
- "svelte",
46
- "jsx",
47
- "tsx",
48
- "js",
49
- "ts",
50
- "astro",
51
- "mdx",
52
- "php",
53
- "erb",
54
- "twig",
55
- "blade.php"
56
- ], H = [
57
- "**/node_modules/**",
58
- "**/.git/**",
59
- "**/dist/**",
60
- "**/build/**",
61
- "**/.next/**",
62
- "**/.nuxt/**",
63
- "**/coverage/**"
64
- ];
65
- function C(s) {
66
- if (!s.startsWith("_"))
67
- return null;
68
- const e = s.slice(1);
69
- if (!e)
70
- return null;
71
- const t = K(e);
72
- if (t.length === 0)
73
- return null;
74
- let n, r, c = [];
75
- t.length === 1 ? (n = t[0], r = "default") : (r = t[t.length - 1], n = t[t.length - 2], c = t.slice(0, -2));
76
- let a = !1, l;
77
- const u = r.match(Q);
78
- return u && (a = !0, l = u[1]), {
79
- raw: s,
80
- name: n,
81
- value: r,
82
- modifiers: c,
83
- isArbitrary: a,
84
- arbitraryValue: l
85
- };
86
- }
87
- function K(s) {
88
- const e = [];
89
- let t = "", n = 0;
90
- for (const r of s)
91
- r === "[" ? (n++, t += r) : r === "]" ? (n--, t += r) : r === ":" && n === 0 ? (t && e.push(t), t = "") : t += r;
92
- return n !== 0 ? [] : (t && e.push(t), e);
93
- }
94
- function A(s, e) {
95
- const t = s.match(e ?? X);
96
- return t ? [...new Set(t)] : [];
97
- }
98
- function pe(s, e, t = []) {
99
- const n = [...t, s];
100
- return e !== "default" && n.push(e), `_${n.join(":")}`;
101
- }
102
- const R = /\bclassName\s*=\s*\{/g, _ = /\bclass\s*=\s*\{/g, I = /\bclass\s*=\s*["']([^"']+)["']/gi, b = /\bclassName\s*=\s*["']([^"']+)["']/gi, M = /\bclass:([^\s={>]+)/g, L = /'([^'\\]*(?:\\.[^'\\]*)*)'/g, F = /"([^"\\]*(?:\\.[^"\\]*)*)"/g, v = /`([^`\\]*(?:\\.[^`\\]*)*)`/g;
103
- function P(s) {
104
- let e = 1, t = 0;
105
- for (; t < s.length && e > 0; ) {
106
- const n = s[t];
107
- n === "{" ? e++ : n === "}" && e--, t++;
108
- }
109
- return e !== 0 ? null : s.slice(0, t - 1);
110
- }
111
- function Z(s) {
112
- const e = [];
113
- R.lastIndex = 0;
114
- let t;
115
- for (; (t = R.exec(s)) !== null; ) {
116
- const n = t.index + t[0].length, r = s.slice(n), c = P(r);
117
- c !== null && e.push(c);
118
- }
119
- return e;
120
- }
121
- function W(s) {
122
- const e = [];
123
- _.lastIndex = 0;
124
- let t;
125
- for (; (t = _.exec(s)) !== null; ) {
126
- const n = t.index + t[0].length, r = s.slice(n), c = P(r);
127
- c !== null && e.push(c);
128
47
  }
129
- return e;
130
- }
131
- function h(s, e) {
132
- const t = [];
133
- I.lastIndex = 0;
134
- let n;
135
- for (; (n = I.exec(s)) !== null; )
136
- n[1] && t.push(...A(n[1], e));
137
- return t;
138
- }
139
- function y(s, e) {
140
- const t = [];
141
- b.lastIndex = 0;
142
- let n;
143
- for (; (n = b.exec(s)) !== null; )
144
- n[1] && t.push(...A(n[1], e));
145
- const r = Z(s);
146
- for (const c of r)
147
- t.push(...m(c, e));
148
- return [...new Set(t)];
149
- }
150
- function Y(s, e) {
151
- const t = [], n = s.match(/<template[^>]*>([\s\S]*?)<\/template>/i);
152
- n?.[1] && (t.push(...h(n[1], e)), t.push(...m(n[1], e)));
153
- const r = s.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
154
- return r?.[1] && t.push(...m(r[1], e)), [...new Set(t)];
155
- }
156
- function q(s, e) {
157
- const t = [];
158
- t.push(...h(s, e));
159
- const n = W(s);
160
- for (const a of n)
161
- t.push(...m(a, e));
162
- M.lastIndex = 0;
163
- let r;
164
- for (; (r = M.exec(s)) !== null; )
165
- r[1] && t.push(r[1]);
166
- const c = s.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
167
- return c?.[1] && t.push(...m(c[1], e)), [...new Set(t)];
168
- }
169
- function J(s, e) {
170
- const t = [];
171
- t.push(...h(s, e)), t.push(...y(s, e));
172
- const n = s.match(/^---\n([\s\S]*?)\n---/);
173
- return n?.[1] && t.push(...m(n[1], e)), [...new Set(t)];
174
- }
175
- function m(s, e) {
176
- const t = [];
177
- let n;
178
- for (L.lastIndex = 0; (n = L.exec(s)) !== null; )
179
- n[1] && t.push(...A(n[1], e));
180
- for (F.lastIndex = 0; (n = F.exec(s)) !== null; )
181
- n[1] && t.push(...A(n[1], e));
182
- for (v.lastIndex = 0; (n = v.exec(s)) !== null; )
183
- n[1] && t.push(...A(n[1], e));
184
- return t;
185
- }
186
- function ee(s, e) {
187
- const t = [];
188
- return t.push(...h(s, e)), t.push(...y(s, e)), [...new Set(t)];
189
- }
190
- const te = {
191
- html: h,
192
- htm: h,
193
- vue: Y,
194
- svelte: q,
195
- jsx: y,
196
- tsx: y,
197
- js: m,
198
- ts: m,
199
- astro: J,
200
- mdx: ee,
201
- php: h,
202
- erb: h,
203
- twig: h,
204
- "blade.php": h
205
- };
206
- function se(s) {
207
- if (s.endsWith(".blade.php"))
208
- return "blade.php";
209
- const e = s.split(".");
210
- return e[e.length - 1]?.toLowerCase() ?? "";
211
- }
212
- function N(s, e, t, n) {
213
- const r = [], c = se(e);
214
- if (t)
215
- for (const l of t)
216
- r.push(...l(s, e));
217
- const a = te[c];
218
- return a ? r.push(...a(s, n)) : r.push(...m(s, n)), [...new Set(r)];
219
- }
220
- function U(s, e) {
221
- if (e.length === 0)
222
- return s;
223
- const t = [...e].sort().join(",");
224
- return `${s}|${t}`;
225
- }
226
- function ne(s, e) {
227
- const t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
228
- for (const a of e.utilities) {
229
- t.set(a.name, a);
230
- const l = /* @__PURE__ */ new Set();
231
- for (const u of a.values)
232
- l.add(U(u.key, u.modifiers));
233
- r.set(a, l);
234
- }
235
- for (const a of e.modifiers)
236
- for (const l of a.key)
237
- n.set(l, a);
238
- const c = [];
239
- for (const a of s) {
240
- const l = t.get(a.name) ?? null, u = [];
241
- for (const T of a.modifiers) {
242
- const w = n.get(T);
243
- w && u.push(w);
244
- }
245
- let S = !1;
246
- if (l) {
247
- const T = U(
248
- a.value,
249
- a.modifiers
250
- );
251
- S = r.get(l)?.has(T) ?? !1;
48
+ let c = 0;
49
+ for (const { factory: e, parsed: t, modifierGroups: l } of i.values()) {
50
+ const o = l.length > 0 ? l : void 0;
51
+ if (t.isArbitrary && t.arbitraryValue !== void 0)
52
+ e.create({ [t.value]: t.arbitraryValue }, o);
53
+ else {
54
+ const a = e.autogenerate(`@${t.value}`);
55
+ e.create(a, o);
252
56
  }
253
- c.push({
254
- parsed: a,
255
- factory: l,
256
- modifierFactories: u,
257
- exists: S
258
- });
57
+ c++;
259
58
  }
260
59
  return c;
261
60
  }
262
- function me(s, e) {
263
- const t = V(s, e);
264
- return z(t);
265
- }
266
- function V(s, e) {
267
- return (e ?? k)(s);
268
- }
269
- function re(s, e) {
270
- return (t) => {
271
- const n = V(
272
- {
273
- name: t.name,
274
- value: t.value,
275
- modifiers: t.modifiers
276
- },
277
- e
278
- );
279
- return s.has(n);
280
- };
281
- }
282
- function de(s, e, t) {
283
- const n = re(e, t);
284
- return s.children.filter((r) => r.type !== "utility" ? !0 : n(r));
285
- }
286
- function ge(s) {
287
- const e = /* @__PURE__ */ new Set();
288
- for (const t of s)
289
- e.add(t.parsed.raw);
290
- return e;
291
- }
292
- function xe(s) {
293
- return s.filter((e) => e.factory !== null);
294
- }
295
- function Se(s) {
296
- return s.filter((e) => e.exists);
297
- }
298
- function Te(s) {
299
- return s.filter((e) => e.parsed.isArbitrary);
300
- }
301
- const E = /* @__PURE__ */ new Map();
302
- function ce(s) {
303
- const e = s.replace(/\\/g, "/");
304
- if (E.has(e))
305
- return E.get(e);
306
- if (!e.includes("**") && !e.includes("*") && !e.includes("?"))
307
- return E.set(e, null), null;
308
- try {
309
- const t = oe(e), n = new RegExp(`^${t}$`);
310
- return E.set(e, n), n;
311
- } catch {
312
- return E.set(e, null), null;
313
- }
314
- }
315
- function we(s, e) {
316
- let t = null;
317
- return (...n) => {
318
- t && clearTimeout(t), t = setTimeout(() => {
319
- s(...n), t = null;
320
- }, e);
321
- };
322
- }
323
- function ae(s, e = {}) {
324
- const { debounce: t = 100 } = e, n = /* @__PURE__ */ new Set();
325
- let r = null;
326
- const c = () => {
327
- if (n.size > 0) {
328
- const l = [...n];
329
- n.clear(), s(l);
330
- }
331
- };
332
- return { onChange: (l) => {
333
- n.add(l), r && clearTimeout(r), r = setTimeout(() => {
334
- c(), r = null;
335
- }, t);
336
- }, flush: c };
337
- }
338
- function le(s) {
339
- return s.replace(/[.+^${}()|[\]\\]/g, "\\$&");
340
- }
341
- function oe(s) {
342
- return s.replace(/\*\*/g, "<<<GLOBSTAR>>>").replace(/\*/g, "<<<STAR>>>").replace(/\?/g, "<<<QUESTION>>>").split("<<<GLOBSTAR>>>").map(le).join(".*").replace(/<<<STAR>>>/g, "[^/]*").replace(/<<<QUESTION>>>/g, ".");
343
- }
344
- function Ee(s, e) {
345
- const t = s.replace(/\\/g, "/");
346
- for (const n of e) {
347
- const r = ce(n);
348
- if (r !== null) {
349
- if (r.test(t))
350
- return !0;
351
- } else {
352
- const c = n.replace(/\\/g, "/");
353
- if (t === c)
354
- return !0;
355
- }
356
- }
357
- return !1;
358
- }
359
- function Ae(s) {
360
- const e = G(), t = s.cwd ?? process.cwd(), n = s.extractors, r = s.utilities?.pattern, c = s.utilities?.parse ?? C;
361
- async function a() {
362
- return j(s.content, {
363
- cwd: t,
364
- absolute: !0,
365
- ignore: H
366
- });
367
- }
368
- async function l(o) {
369
- const f = await D(o, "utf-8"), d = B(f), p = e.getIfValid(o, d);
370
- if (p)
371
- return p;
372
- const g = N(
373
- f,
374
- o,
375
- n,
376
- r
377
- ), i = g.map(c).filter((O) => O !== null), x = {
378
- path: o,
379
- classes: new Set(g),
380
- parsed: i,
381
- lastScanned: Date.now()
382
- };
383
- return e.set(o, x, d), x;
384
- }
385
- function u(o, f = "inline") {
386
- return N(
387
- o,
388
- f,
389
- n,
390
- r
391
- ).map(c).filter((p) => p !== null);
392
- }
393
- async function S() {
394
- const o = await a(), f = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Set(), p = [], g = await Promise.all(
395
- o.map(async (i) => {
396
- try {
397
- return await l(i);
398
- } catch (x) {
399
- return console.warn(
400
- `[styleframe/scanner] Failed to scan ${i}:`,
401
- x
402
- ), null;
403
- }
404
- })
405
- );
406
- for (const i of g)
407
- if (i) {
408
- f.set(i.path, i);
409
- for (const x of i.classes)
410
- d.add(x);
411
- p.push(...i.parsed);
412
- }
413
- return {
414
- files: f,
415
- allClasses: d,
416
- allParsed: p
417
- };
418
- }
419
- function T(o, f) {
420
- return ne(o, f);
421
- }
422
- function w(o) {
423
- const { onChange: f, flush: d } = ae(async (p) => {
424
- for (const i of p)
425
- e.invalidate(i);
426
- const g = await S();
427
- o(g);
428
- });
429
- return () => {
430
- d();
431
- };
432
- }
433
- function $(o) {
434
- o ? e.invalidate(o) : e.clear();
435
- }
436
- return {
437
- scan: S,
438
- scanFile: l,
439
- scanContent: u,
440
- match: T,
441
- watch: w,
442
- invalidate: $
443
- };
444
- }
445
- function ye(s, e = "inline.html", t) {
446
- const n = t?.parse ?? C;
447
- return N(
448
- s,
449
- e,
450
- void 0,
451
- t?.pattern
452
- ).map(n).filter((c) => c !== null);
453
- }
454
- function Ne(s, e) {
455
- const t = e?.parse ?? C;
456
- return (n, r = "inline") => N(
457
- n,
458
- r,
459
- s,
460
- e?.pattern
461
- ).map(t).filter((a) => a !== null);
462
- }
463
61
  export {
464
- Q as ARBITRARY_VALUE_PATTERN,
465
- he as DEFAULT_EXTENSIONS,
466
- H as DEFAULT_IGNORE_PATTERNS,
467
- X as UTILITY_CLASS_PATTERN,
468
- V as classNameFromUtilityOptions,
469
- G as createCache,
470
- ae as createChangeHandler,
471
- Ne as createContentScanner,
472
- Ae as createScanner,
473
- re as createUtilityFilter,
474
- we as debounce,
475
- N as extractClasses,
476
- J as extractFromAstro,
477
- h as extractFromHTML,
478
- y as extractFromJSX,
479
- ee as extractFromMDX,
480
- m as extractFromStringLiterals,
481
- q as extractFromSvelte,
482
- Y as extractFromVue,
483
- A as extractUtilityClasses,
484
- de as filterUtilities,
485
- pe as generateUtilityClassName,
486
- me as generateUtilitySelector,
487
- Te as getArbitraryMatches,
488
- Se as getExistingMatches,
489
- ge as getUsedClassNames,
490
- xe as getValidMatches,
62
+ v as ARBITRARY_VALUE_PATTERN,
63
+ E as DEFAULT_EXTENSIONS,
64
+ C as DEFAULT_IGNORE_PATTERNS,
65
+ _ as UTILITY_CLASS_PATTERN,
66
+ j as classNameFromUtilityOptions,
67
+ k as createCache,
68
+ L as createChangeHandler,
69
+ x as createContentScanner,
70
+ M as createUtilityFilter,
71
+ R as debounce,
72
+ u as extractClasses,
73
+ b as extractFromAstro,
74
+ D as extractFromHTML,
75
+ G as extractFromJSX,
76
+ I as extractFromMDX,
77
+ V as extractFromStringLiterals,
78
+ P as extractFromSvelte,
79
+ K as extractFromVue,
80
+ O as extractUtilityClasses,
81
+ X as filterUtilities,
82
+ $ as generateUtilityClassName,
83
+ q as generateUtilitySelector,
84
+ w as getArbitraryMatches,
85
+ H as getExistingMatches,
86
+ Y as getUsedClassNames,
87
+ z as getValidMatches,
491
88
  B as hashContent,
492
- ne as matchUtilities,
493
- Ee as matchesPatterns,
494
- C as parseUtilityClass,
495
- ye as quickScan
89
+ J as matchUtilities,
90
+ Q as matchesPatterns,
91
+ f as parseUtilityClass,
92
+ U as quickScan,
93
+ N as registerMatchedUtilities
496
94
  };
package/dist/node.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("node:fs/promises"),v=require("fast-glob"),c=require("./watcher-C8V8DPY6.cjs");function x(l){const i=c.createCache(),h=l.cwd??process.cwd(),u=l.extractors,d=l.utilities?.pattern,f=l.utilities?.parse??c.parseUtilityClass;async function m(){return v(l.content,{cwd:h,absolute:!0,ignore:c.DEFAULT_IGNORE_PATTERNS})}async function p(t){const s=await g.readFile(t,"utf-8"),a=c.hashContent(s),n=i.getIfValid(t,a);if(n)return n;const r=c.extractClasses(s,t,u,d),e=r.map(f).filter(F=>F!==null),o={path:t,classes:new Set(r),parsed:e,lastScanned:Date.now()};return i.set(t,o,a),o}function y(t,s="inline"){return c.extractClasses(t,s,u,d).map(f).filter(n=>n!==null)}async function w(){const t=await m(),s=new Map,a=new Set,n=[],r=await Promise.all(t.map(async e=>{try{return await p(e)}catch(o){return console.warn(`[styleframe/scanner] Failed to scan ${e}:`,o),null}}));for(const e of r)if(e){s.set(e.path,e);for(const o of e.classes)a.add(o);n.push(...e.parsed)}return{files:s,allClasses:a,allParsed:n}}function C(t,s){return c.matchUtilities(t,s)}function S(t){const{onChange:s,flush:a}=c.createChangeHandler(async n=>{for(const e of n)i.invalidate(e);const r=await w();t(r)});return()=>{a()}}function N(t){t?i.invalidate(t):i.clear()}return{scan:w,scanFile:p,scanContent:y,match:C,watch:S,invalidate:N}}exports.createScanner=x;
package/dist/node.d.ts ADDED
@@ -0,0 +1,138 @@
1
+ import { ModifierFactory } from '@styleframe/core';
2
+ import { Root } from '@styleframe/core';
3
+ import { UtilityFactory } from '@styleframe/core';
4
+ import { UtilitySelectorFn } from '@styleframe/core';
5
+
6
+ /**
7
+ * Create a scanner instance for detecting utility classes in content files.
8
+ *
9
+ * @param config Scanner configuration
10
+ * @returns Scanner instance
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const scanner = createScanner({
15
+ * content: ['./src/components/*.tsx', './src/pages/*.vue'],
16
+ * });
17
+ *
18
+ * const result = await scanner.scan();
19
+ * const matches = scanner.match(result.allParsed, root);
20
+ * ```
21
+ */
22
+ export declare function createScanner(config: ScannerConfig): Scanner;
23
+
24
+ /**
25
+ * Custom extractor function type
26
+ */
27
+ declare type Extractor = (content: string, filePath: string) => string[];
28
+
29
+ /**
30
+ * Scan result for a single file
31
+ */
32
+ declare interface FileScanResult {
33
+ /** Absolute file path */
34
+ path: string;
35
+ /** Set of raw class names found */
36
+ classes: Set<string>;
37
+ /** Parsed utility classes */
38
+ parsed: ParsedUtility[];
39
+ /** Timestamp of last scan */
40
+ lastScanned: number;
41
+ }
42
+
43
+ /**
44
+ * Parsed utility class structure
45
+ */
46
+ declare interface ParsedUtility {
47
+ /** Original class name as found in content (e.g., "_margin:sm") */
48
+ raw: string;
49
+ /** Utility name (e.g., "margin", "background") */
50
+ name: string;
51
+ /** Value key (e.g., "sm", "primary", "[16px]") */
52
+ value: string;
53
+ /** Applied modifiers in order (e.g., ["hover", "dark"]) */
54
+ modifiers: string[];
55
+ /** Whether this uses arbitrary value syntax [value] */
56
+ isArbitrary: boolean;
57
+ /** The arbitrary value if isArbitrary is true (e.g., "16px") */
58
+ arbitraryValue?: string;
59
+ }
60
+
61
+ /**
62
+ * Scanner instance interface
63
+ */
64
+ declare interface Scanner {
65
+ /** Scan all content files */
66
+ scan(): Promise<ScanResult>;
67
+ /** Scan a single file */
68
+ scanFile(filePath: string): Promise<FileScanResult>;
69
+ /** Scan content string directly */
70
+ scanContent(content: string, filePath?: string): ParsedUtility[];
71
+ /** Match parsed utilities against a root instance */
72
+ match(parsed: ParsedUtility[], root: Root): UtilityMatch[];
73
+ /** Start watching content files for changes */
74
+ watch(callback: (result: ScanResult) => void): () => void;
75
+ /** Invalidate cache for a file or all files */
76
+ invalidate(filePath?: string): void;
77
+ }
78
+
79
+ /**
80
+ * Configuration for the content scanner
81
+ */
82
+ declare interface ScannerConfig {
83
+ /** Glob patterns for files to scan */
84
+ content: string[];
85
+ /** Custom extraction functions */
86
+ extractors?: Extractor[];
87
+ /** Base directory for glob resolution (defaults to process.cwd()) */
88
+ cwd?: string;
89
+ /** Custom utility class syntax configuration */
90
+ utilities?: ScannerUtilitiesConfig;
91
+ }
92
+
93
+ /**
94
+ * Configuration for custom utility class syntax.
95
+ * All fields are optional — defaults match the `_modifier:property:value` format.
96
+ */
97
+ declare interface ScannerUtilitiesConfig {
98
+ /** Regex pattern to extract utility class candidates from content strings. Must use the global (`g`) flag. */
99
+ pattern?: RegExp;
100
+ /** Parse a matched class name into its components (name, value, modifiers) */
101
+ parse?: UtilityClassParseFn;
102
+ /** Generate a raw class name from components (inverse of parse) */
103
+ selector?: UtilitySelectorFn;
104
+ }
105
+
106
+ /**
107
+ * Complete scan result across all files
108
+ */
109
+ declare interface ScanResult {
110
+ /** Map of file path to scan result */
111
+ files: Map<string, FileScanResult>;
112
+ /** All unique class names found */
113
+ allClasses: Set<string>;
114
+ /** All parsed utilities */
115
+ allParsed: ParsedUtility[];
116
+ }
117
+
118
+ /**
119
+ * Function that parses a class name string into its structured components.
120
+ * Returns null if the string is not a valid utility class.
121
+ */
122
+ declare type UtilityClassParseFn = (className: string) => ParsedUtility | null;
123
+
124
+ /**
125
+ * Match result between a parsed class and a utility factory
126
+ */
127
+ declare interface UtilityMatch {
128
+ /** The parsed utility class */
129
+ parsed: ParsedUtility;
130
+ /** The matched utility factory, or null if not found */
131
+ factory: UtilityFactory | null;
132
+ /** Matched modifier factories */
133
+ modifierFactories: ModifierFactory[];
134
+ /** Whether the utility value exists in the factory */
135
+ exists: boolean;
136
+ }
137
+
138
+ export { }
package/dist/node.js ADDED
@@ -0,0 +1,92 @@
1
+ import { readFile as S } from "node:fs/promises";
2
+ import v from "fast-glob";
3
+ import { p as E, v as T, x as U, m as g, e as d, u as A, z as D } from "./watcher-Bn_8hGt2.js";
4
+ function R(o) {
5
+ const l = T(), w = o.cwd ?? process.cwd(), i = o.extractors, u = o.utilities?.pattern, f = o.utilities?.parse ?? E;
6
+ async function h() {
7
+ return v(o.content, {
8
+ cwd: w,
9
+ absolute: !0,
10
+ ignore: D
11
+ });
12
+ }
13
+ async function m(t) {
14
+ const a = await S(t, "utf-8"), e = A(a), n = l.getIfValid(t, e);
15
+ if (n)
16
+ return n;
17
+ const c = d(
18
+ a,
19
+ t,
20
+ i,
21
+ u
22
+ ), s = c.map(f).filter((F) => F !== null), r = {
23
+ path: t,
24
+ classes: new Set(c),
25
+ parsed: s,
26
+ lastScanned: Date.now()
27
+ };
28
+ return l.set(t, r, e), r;
29
+ }
30
+ function y(t, a = "inline") {
31
+ return d(
32
+ t,
33
+ a,
34
+ i,
35
+ u
36
+ ).map(f).filter((n) => n !== null);
37
+ }
38
+ async function p() {
39
+ const t = await h(), a = /* @__PURE__ */ new Map(), e = /* @__PURE__ */ new Set(), n = [], c = await Promise.all(
40
+ t.map(async (s) => {
41
+ try {
42
+ return await m(s);
43
+ } catch (r) {
44
+ return console.warn(
45
+ `[styleframe/scanner] Failed to scan ${s}:`,
46
+ r
47
+ ), null;
48
+ }
49
+ })
50
+ );
51
+ for (const s of c)
52
+ if (s) {
53
+ a.set(s.path, s);
54
+ for (const r of s.classes)
55
+ e.add(r);
56
+ n.push(...s.parsed);
57
+ }
58
+ return {
59
+ files: a,
60
+ allClasses: e,
61
+ allParsed: n
62
+ };
63
+ }
64
+ function C(t, a) {
65
+ return g(t, a);
66
+ }
67
+ function N(t) {
68
+ const { onChange: a, flush: e } = U(async (n) => {
69
+ for (const s of n)
70
+ l.invalidate(s);
71
+ const c = await p();
72
+ t(c);
73
+ });
74
+ return () => {
75
+ e();
76
+ };
77
+ }
78
+ function x(t) {
79
+ t ? l.invalidate(t) : l.clear();
80
+ }
81
+ return {
82
+ scan: p,
83
+ scanFile: m,
84
+ scanContent: y,
85
+ match: C,
86
+ watch: N,
87
+ invalidate: x
88
+ };
89
+ }
90
+ export {
91
+ R as createScanner
92
+ };
@@ -0,0 +1,387 @@
1
+ import { classNameToCssSelector as b, defaultUtilitySelectorFn as I } from "@styleframe/core";
2
+ const M = /_[a-zA-Z][a-zA-Z0-9-]*(?::[a-zA-Z0-9._-]+|:\[[^\]]+\])*/g, L = /^\[(.+)\]$/, Q = [
3
+ "html",
4
+ "htm",
5
+ "vue",
6
+ "svelte",
7
+ "jsx",
8
+ "tsx",
9
+ "js",
10
+ "ts",
11
+ "astro",
12
+ "mdx",
13
+ "php",
14
+ "erb",
15
+ "twig",
16
+ "blade.php"
17
+ ], K = [
18
+ "**/node_modules/**",
19
+ "**/.git/**",
20
+ "**/dist/**",
21
+ "**/build/**",
22
+ "**/.next/**",
23
+ "**/.nuxt/**",
24
+ "**/coverage/**"
25
+ ];
26
+ function Z(s) {
27
+ if (!s.startsWith("_"))
28
+ return null;
29
+ const e = s.slice(1);
30
+ if (!e)
31
+ return null;
32
+ const t = U(e);
33
+ if (t.length === 0)
34
+ return null;
35
+ let n, r, a = [];
36
+ t.length === 1 ? (n = t[0], r = "default") : (r = t[t.length - 1], n = t[t.length - 2], a = t.slice(0, -2));
37
+ let l = !1, c;
38
+ const u = r.match(L);
39
+ return u && (l = !0, c = u[1]), {
40
+ raw: s,
41
+ name: n,
42
+ value: r,
43
+ modifiers: a,
44
+ isArbitrary: l,
45
+ arbitraryValue: c
46
+ };
47
+ }
48
+ function U(s) {
49
+ const e = [];
50
+ let t = "", n = 0;
51
+ for (const r of s)
52
+ r === "[" ? (n++, t += r) : r === "]" ? (n--, t += r) : r === ":" && n === 0 ? (t && e.push(t), t = "") : t += r;
53
+ return n !== 0 ? [] : (t && e.push(t), e);
54
+ }
55
+ function h(s, e) {
56
+ const t = s.match(e ?? M);
57
+ return t ? [...new Set(t)] : [];
58
+ }
59
+ function H(s, e, t = []) {
60
+ const n = [...t, s];
61
+ return e !== "default" && n.push(e), `_${n.join(":")}`;
62
+ }
63
+ const x = /\bclassName\s*=\s*\{/g, T = /\bclass\s*=\s*\{/g, S = /\bclass\s*=\s*["']([^"']+)["']/gi, A = /\bclassName\s*=\s*["']([^"']+)["']/gi, E = /\bclass:([^\s={>]+)/g, w = /'([^'\\]*(?:\\.[^'\\]*)*)'/g, C = /"([^"\\]*(?:\\.[^"\\]*)*)"/g, y = /`([^`\\]*(?:\\.[^`\\]*)*)`/g;
64
+ function _(s) {
65
+ let e = 1, t = 0;
66
+ for (; t < s.length && e > 0; ) {
67
+ const n = s[t];
68
+ n === "{" ? e++ : n === "}" && e--, t++;
69
+ }
70
+ return e !== 0 ? null : s.slice(0, t - 1);
71
+ }
72
+ function P(s) {
73
+ const e = [];
74
+ x.lastIndex = 0;
75
+ let t;
76
+ for (; (t = x.exec(s)) !== null; ) {
77
+ const n = t.index + t[0].length, r = s.slice(n), a = _(r);
78
+ a !== null && e.push(a);
79
+ }
80
+ return e;
81
+ }
82
+ function v(s) {
83
+ const e = [];
84
+ T.lastIndex = 0;
85
+ let t;
86
+ for (; (t = T.exec(s)) !== null; ) {
87
+ const n = t.index + t[0].length, r = s.slice(n), a = _(r);
88
+ a !== null && e.push(a);
89
+ }
90
+ return e;
91
+ }
92
+ function i(s, e) {
93
+ const t = [];
94
+ S.lastIndex = 0;
95
+ let n;
96
+ for (; (n = S.exec(s)) !== null; )
97
+ n[1] && t.push(...h(n[1], e));
98
+ return t;
99
+ }
100
+ function p(s, e) {
101
+ const t = [];
102
+ A.lastIndex = 0;
103
+ let n;
104
+ for (; (n = A.exec(s)) !== null; )
105
+ n[1] && t.push(...h(n[1], e));
106
+ const r = P(s);
107
+ for (const a of r)
108
+ t.push(...o(a, e));
109
+ return [...new Set(t)];
110
+ }
111
+ function F(s, e) {
112
+ const t = [], n = s.match(/<template[^>]*>([\s\S]*)<\/template>/i);
113
+ n?.[1] && (t.push(...i(n[1], e)), t.push(...o(n[1], e)));
114
+ const r = s.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
115
+ return r?.[1] && t.push(...o(r[1], e)), [...new Set(t)];
116
+ }
117
+ function O(s, e) {
118
+ const t = [];
119
+ t.push(...i(s, e));
120
+ const n = v(s);
121
+ for (const l of n)
122
+ t.push(...o(l, e));
123
+ E.lastIndex = 0;
124
+ let r;
125
+ for (; (r = E.exec(s)) !== null; )
126
+ r[1] && t.push(r[1]);
127
+ const a = s.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
128
+ return a?.[1] && t.push(...o(a[1], e)), [...new Set(t)];
129
+ }
130
+ function V(s, e) {
131
+ const t = [];
132
+ t.push(...i(s, e)), t.push(...p(s, e));
133
+ const n = s.match(/^---\n([\s\S]*?)\n---/);
134
+ return n?.[1] && t.push(...o(n[1], e)), [...new Set(t)];
135
+ }
136
+ function o(s, e) {
137
+ const t = [];
138
+ let n;
139
+ for (w.lastIndex = 0; (n = w.exec(s)) !== null; )
140
+ n[1] && t.push(...h(n[1], e));
141
+ for (C.lastIndex = 0; (n = C.exec(s)) !== null; )
142
+ n[1] && t.push(...h(n[1], e));
143
+ for (y.lastIndex = 0; (n = y.exec(s)) !== null; )
144
+ n[1] && t.push(...h(n[1], e));
145
+ return t;
146
+ }
147
+ function $(s, e) {
148
+ const t = [];
149
+ return t.push(...i(s, e)), t.push(...p(s, e)), [...new Set(t)];
150
+ }
151
+ const j = {
152
+ html: i,
153
+ htm: i,
154
+ vue: F,
155
+ svelte: O,
156
+ jsx: p,
157
+ tsx: p,
158
+ js: o,
159
+ ts: o,
160
+ astro: V,
161
+ mdx: $,
162
+ php: i,
163
+ erb: i,
164
+ twig: i,
165
+ "blade.php": i
166
+ };
167
+ function z(s) {
168
+ if (s.endsWith(".blade.php"))
169
+ return "blade.php";
170
+ const e = s.split(".");
171
+ return e[e.length - 1]?.toLowerCase() ?? "";
172
+ }
173
+ function W(s, e, t, n) {
174
+ const r = [], a = z(e);
175
+ if (t)
176
+ for (const c of t)
177
+ r.push(...c(s, e));
178
+ const l = j[a];
179
+ return l ? r.push(...l(s, n)) : r.push(...o(s, n)), [...new Set(r)];
180
+ }
181
+ function R(s, e) {
182
+ if (e.length === 0)
183
+ return s;
184
+ const t = [...e].sort().join(",");
185
+ return `${s}|${t}`;
186
+ }
187
+ function Y(s, e) {
188
+ const t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
189
+ for (const l of e.utilities) {
190
+ t.set(l.name, l);
191
+ const c = /* @__PURE__ */ new Set();
192
+ for (const u of l.values)
193
+ c.add(R(u.key, u.modifiers));
194
+ r.set(l, c);
195
+ }
196
+ for (const l of e.modifiers)
197
+ for (const c of l.key)
198
+ n.set(c, l);
199
+ const a = [];
200
+ for (const l of s) {
201
+ const c = t.get(l.name) ?? null, u = [];
202
+ for (const d of l.modifiers) {
203
+ const m = n.get(d);
204
+ m && u.push(m);
205
+ }
206
+ let g = !1;
207
+ if (c) {
208
+ const d = R(
209
+ l.value,
210
+ l.modifiers
211
+ );
212
+ g = r.get(c)?.has(d) ?? !1;
213
+ }
214
+ a.push({
215
+ parsed: l,
216
+ factory: c,
217
+ modifierFactories: u,
218
+ exists: g
219
+ });
220
+ }
221
+ return a;
222
+ }
223
+ function q(s, e) {
224
+ const t = N(s, e);
225
+ return b(t);
226
+ }
227
+ function N(s, e) {
228
+ return (e ?? I)(s);
229
+ }
230
+ function D(s, e) {
231
+ return (t) => {
232
+ const n = N(
233
+ {
234
+ name: t.name,
235
+ value: t.value,
236
+ modifiers: t.modifiers
237
+ },
238
+ e
239
+ );
240
+ return s.has(n);
241
+ };
242
+ }
243
+ function J(s, e, t) {
244
+ const n = D(e, t);
245
+ return s.children.filter((r) => r.type !== "utility" ? !0 : n(r));
246
+ }
247
+ function ee(s) {
248
+ const e = /* @__PURE__ */ new Set();
249
+ for (const t of s)
250
+ e.add(t.parsed.raw);
251
+ return e;
252
+ }
253
+ function te(s) {
254
+ return s.filter((e) => e.factory !== null);
255
+ }
256
+ function se(s) {
257
+ return s.filter((e) => e.exists);
258
+ }
259
+ function ne(s) {
260
+ return s.filter((e) => e.parsed.isArbitrary);
261
+ }
262
+ function re(s) {
263
+ let e = 0;
264
+ for (let t = 0; t < s.length; t++) {
265
+ const n = s.charCodeAt(t);
266
+ e = (e << 5) - e + n, e = e & e;
267
+ }
268
+ return `${e.toString(16)}-${s.length}`;
269
+ }
270
+ function ae() {
271
+ const s = /* @__PURE__ */ new Map();
272
+ return {
273
+ get(e) {
274
+ return s.get(e)?.result ?? null;
275
+ },
276
+ set(e, t, n) {
277
+ s.set(e, {
278
+ hash: n,
279
+ result: t,
280
+ timestamp: Date.now()
281
+ });
282
+ },
283
+ isValid(e, t) {
284
+ const n = s.get(e);
285
+ return n !== void 0 && n.hash === t;
286
+ },
287
+ getIfValid(e, t) {
288
+ const n = s.get(e);
289
+ return n && n.hash === t ? n.result : null;
290
+ },
291
+ invalidate(e) {
292
+ s.delete(e);
293
+ },
294
+ clear() {
295
+ s.clear();
296
+ }
297
+ };
298
+ }
299
+ const f = /* @__PURE__ */ new Map();
300
+ function k(s) {
301
+ const e = s.replace(/\\/g, "/");
302
+ if (f.has(e))
303
+ return f.get(e);
304
+ if (!e.includes("**") && !e.includes("*") && !e.includes("?"))
305
+ return f.set(e, null), null;
306
+ try {
307
+ const t = G(e), n = new RegExp(`^${t}$`);
308
+ return f.set(e, n), n;
309
+ } catch {
310
+ return f.set(e, null), null;
311
+ }
312
+ }
313
+ function le(s, e) {
314
+ let t = null;
315
+ return (...n) => {
316
+ t && clearTimeout(t), t = setTimeout(() => {
317
+ s(...n), t = null;
318
+ }, e);
319
+ };
320
+ }
321
+ function ce(s, e = {}) {
322
+ const { debounce: t = 100 } = e, n = /* @__PURE__ */ new Set();
323
+ let r = null;
324
+ const a = () => {
325
+ if (n.size > 0) {
326
+ const c = [...n];
327
+ n.clear(), s(c);
328
+ }
329
+ };
330
+ return { onChange: (c) => {
331
+ n.add(c), r && clearTimeout(r), r = setTimeout(() => {
332
+ a(), r = null;
333
+ }, t);
334
+ }, flush: a };
335
+ }
336
+ function B(s) {
337
+ return s.replace(/[.+^${}()|[\]\\]/g, "\\$&");
338
+ }
339
+ function G(s) {
340
+ return s.replace(/\*\*/g, "<<<GLOBSTAR>>>").replace(/\*/g, "<<<STAR>>>").replace(/\?/g, "<<<QUESTION>>>").split("<<<GLOBSTAR>>>").map(B).join(".*").replace(/<<<STAR>>>/g, "[^/]*").replace(/<<<QUESTION>>>/g, ".");
341
+ }
342
+ function ie(s, e) {
343
+ const t = s.replace(/\\/g, "/");
344
+ for (const n of e) {
345
+ const r = k(n);
346
+ if (r !== null) {
347
+ if (r.test(t))
348
+ return !0;
349
+ } else {
350
+ const a = n.replace(/\\/g, "/");
351
+ if (t === a)
352
+ return !0;
353
+ }
354
+ }
355
+ return !1;
356
+ }
357
+ export {
358
+ L as A,
359
+ Q as D,
360
+ M as U,
361
+ h as a,
362
+ i as b,
363
+ p as c,
364
+ F as d,
365
+ W as e,
366
+ O as f,
367
+ H as g,
368
+ V as h,
369
+ $ as i,
370
+ o as j,
371
+ q as k,
372
+ N as l,
373
+ Y as m,
374
+ D as n,
375
+ J as o,
376
+ Z as p,
377
+ ee as q,
378
+ te as r,
379
+ se as s,
380
+ ne as t,
381
+ re as u,
382
+ ae as v,
383
+ le as w,
384
+ ce as x,
385
+ ie as y,
386
+ K as z
387
+ };
@@ -0,0 +1 @@
1
+ "use strict";const w=require("@styleframe/core"),U=/_[a-zA-Z][a-zA-Z0-9-]*(?::[a-zA-Z0-9._-]+|:\[[^\]]+\])*/g,I=/^\[(.+)\]$/,O=["html","htm","vue","svelte","jsx","tsx","js","ts","astro","mdx","php","erb","twig","blade.php"],V=["**/node_modules/**","**/.git/**","**/dist/**","**/build/**","**/.next/**","**/.nuxt/**","**/coverage/**"];function D(s){if(!s.startsWith("_"))return null;const e=s.slice(1);if(!e)return null;const t=$(e);if(t.length===0)return null;let n,r,i=[];t.length===1?(n=t[0],r="default"):(r=t[t.length-1],n=t[t.length-2],i=t.slice(0,-2));let c=!1,l;const u=r.match(I);return u&&(c=!0,l=u[1]),{raw:s,name:n,value:r,modifiers:i,isArbitrary:c,arbitraryValue:l}}function $(s){const e=[];let t="",n=0;for(const r of s)r==="["?(n++,t+=r):r==="]"?(n--,t+=r):r===":"&&n===0?(t&&e.push(t),t=""):t+=r;return n!==0?[]:(t&&e.push(t),e)}function f(s,e){const t=s.match(e??U);return t?[...new Set(t)]:[]}function X(s,e,t=[]){const n=[...t,s];return e!=="default"&&n.push(e),`_${n.join(":")}`}const T=/\bclassName\s*=\s*\{/g,S=/\bclass\s*=\s*\{/g,A=/\bclass\s*=\s*["']([^"']+)["']/gi,E=/\bclassName\s*=\s*["']([^"']+)["']/gi,C=/\bclass:([^\s={>]+)/g,N=/'([^'\\]*(?:\\.[^'\\]*)*)'/g,R=/"([^"\\]*(?:\\.[^"\\]*)*)"/g,_=/`([^`\\]*(?:\\.[^`\\]*)*)`/g;function L(s){let e=1,t=0;for(;t<s.length&&e>0;){const n=s[t];n==="{"?e++:n==="}"&&e--,t++}return e!==0?null:s.slice(0,t-1)}function j(s){const e=[];T.lastIndex=0;let t;for(;(t=T.exec(s))!==null;){const n=t.index+t[0].length,r=s.slice(n),i=L(r);i!==null&&e.push(i)}return e}function z(s){const e=[];S.lastIndex=0;let t;for(;(t=S.exec(s))!==null;){const n=t.index+t[0].length,r=s.slice(n),i=L(r);i!==null&&e.push(i)}return e}function a(s,e){const t=[];A.lastIndex=0;let n;for(;(n=A.exec(s))!==null;)n[1]&&t.push(...f(n[1],e));return t}function m(s,e){const t=[];E.lastIndex=0;let n;for(;(n=E.exec(s))!==null;)n[1]&&t.push(...f(n[1],e));const r=j(s);for(const i of r)t.push(...o(i,e));return[...new Set(t)]}function M(s,e){const t=[],n=s.match(/<template[^>]*>([\s\S]*)<\/template>/i);n?.[1]&&(t.push(...a(n[1],e)),t.push(...o(n[1],e)));const r=s.match(/<script[^>]*>([\s\S]*?)<\/script>/i);return r?.[1]&&t.push(...o(r[1],e)),[...new Set(t)]}function b(s,e){const t=[];t.push(...a(s,e));const n=z(s);for(const c of n)t.push(...o(c,e));C.lastIndex=0;let r;for(;(r=C.exec(s))!==null;)r[1]&&t.push(r[1]);const i=s.match(/<script[^>]*>([\s\S]*?)<\/script>/i);return i?.[1]&&t.push(...o(i[1],e)),[...new Set(t)]}function F(s,e){const t=[];t.push(...a(s,e)),t.push(...m(s,e));const n=s.match(/^---\n([\s\S]*?)\n---/);return n?.[1]&&t.push(...o(n[1],e)),[...new Set(t)]}function o(s,e){const t=[];let n;for(N.lastIndex=0;(n=N.exec(s))!==null;)n[1]&&t.push(...f(n[1],e));for(R.lastIndex=0;(n=R.exec(s))!==null;)n[1]&&t.push(...f(n[1],e));for(_.lastIndex=0;(n=_.exec(s))!==null;)n[1]&&t.push(...f(n[1],e));return t}function P(s,e){const t=[];return t.push(...a(s,e)),t.push(...m(s,e)),[...new Set(t)]}const B={html:a,htm:a,vue:M,svelte:b,jsx:m,tsx:m,js:o,ts:o,astro:F,mdx:P,php:a,erb:a,twig:a,"blade.php":a};function G(s){if(s.endsWith(".blade.php"))return"blade.php";const e=s.split(".");return e[e.length-1]?.toLowerCase()??""}function k(s,e,t,n){const r=[],i=G(e);if(t)for(const l of t)r.push(...l(s,e));const c=B[i];return c?r.push(...c(s,n)):r.push(...o(s,n)),[...new Set(r)]}function y(s,e){if(e.length===0)return s;const t=[...e].sort().join(",");return`${s}|${t}`}function H(s,e){const t=new Map,n=new Map,r=new Map;for(const c of e.utilities){t.set(c.name,c);const l=new Set;for(const u of c.values)l.add(y(u.key,u.modifiers));r.set(c,l)}for(const c of e.modifiers)for(const l of c.key)n.set(l,c);const i=[];for(const c of s){const l=t.get(c.name)??null,u=[];for(const p of c.modifiers){const d=n.get(p);d&&u.push(d)}let x=!1;if(l){const p=y(c.value,c.modifiers);x=r.get(l)?.has(p)??!1}i.push({parsed:c,factory:l,modifierFactories:u,exists:x})}return i}function Q(s,e){const t=g(s,e);return w.classNameToCssSelector(t)}function g(s,e){return(e??w.defaultUtilitySelectorFn)(s)}function v(s,e){return t=>{const n=g({name:t.name,value:t.value,modifiers:t.modifiers},e);return s.has(n)}}function Y(s,e,t){const n=v(e,t);return s.children.filter(r=>r.type!=="utility"?!0:n(r))}function K(s){const e=new Set;for(const t of s)e.add(t.parsed.raw);return e}function Z(s){return s.filter(e=>e.factory!==null)}function J(s){return s.filter(e=>e.exists)}function W(s){return s.filter(e=>e.parsed.isArbitrary)}function q(s){let e=0;for(let t=0;t<s.length;t++){const n=s.charCodeAt(t);e=(e<<5)-e+n,e=e&e}return`${e.toString(16)}-${s.length}`}function ee(){const s=new Map;return{get(e){return s.get(e)?.result??null},set(e,t,n){s.set(e,{hash:n,result:t,timestamp:Date.now()})},isValid(e,t){const n=s.get(e);return n!==void 0&&n.hash===t},getIfValid(e,t){const n=s.get(e);return n&&n.hash===t?n.result:null},invalidate(e){s.delete(e)},clear(){s.clear()}}}const h=new Map;function te(s){const e=s.replace(/\\/g,"/");if(h.has(e))return h.get(e);if(!e.includes("**")&&!e.includes("*")&&!e.includes("?"))return h.set(e,null),null;try{const t=ie(e),n=new RegExp(`^${t}$`);return h.set(e,n),n}catch{return h.set(e,null),null}}function se(s,e){let t=null;return(...n)=>{t&&clearTimeout(t),t=setTimeout(()=>{s(...n),t=null},e)}}function ne(s,e={}){const{debounce:t=100}=e,n=new Set;let r=null;const i=()=>{if(n.size>0){const l=[...n];n.clear(),s(l)}};return{onChange:l=>{n.add(l),r&&clearTimeout(r),r=setTimeout(()=>{i(),r=null},t)},flush:i}}function re(s){return s.replace(/[.+^${}()|[\]\\]/g,"\\$&")}function ie(s){return s.replace(/\*\*/g,"<<<GLOBSTAR>>>").replace(/\*/g,"<<<STAR>>>").replace(/\?/g,"<<<QUESTION>>>").split("<<<GLOBSTAR>>>").map(re).join(".*").replace(/<<<STAR>>>/g,"[^/]*").replace(/<<<QUESTION>>>/g,".")}function ce(s,e){const t=s.replace(/\\/g,"/");for(const n of e){const r=te(n);if(r!==null){if(r.test(t))return!0}else{const i=n.replace(/\\/g,"/");if(t===i)return!0}}return!1}exports.ARBITRARY_VALUE_PATTERN=I;exports.DEFAULT_EXTENSIONS=O;exports.DEFAULT_IGNORE_PATTERNS=V;exports.UTILITY_CLASS_PATTERN=U;exports.classNameFromUtilityOptions=g;exports.createCache=ee;exports.createChangeHandler=ne;exports.createUtilityFilter=v;exports.debounce=se;exports.extractClasses=k;exports.extractFromAstro=F;exports.extractFromHTML=a;exports.extractFromJSX=m;exports.extractFromMDX=P;exports.extractFromStringLiterals=o;exports.extractFromSvelte=b;exports.extractFromVue=M;exports.extractUtilityClasses=f;exports.filterUtilities=Y;exports.generateUtilityClassName=X;exports.generateUtilitySelector=Q;exports.getArbitraryMatches=W;exports.getExistingMatches=J;exports.getUsedClassNames=K;exports.getValidMatches=Z;exports.hashContent=q;exports.matchUtilities=H;exports.matchesPatterns=ce;exports.parseUtilityClass=D;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@styleframe/scanner",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "module": "./dist/index.js",
@@ -10,6 +10,11 @@
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js",
12
12
  "require": "./dist/index.cjs"
13
+ },
14
+ "./node": {
15
+ "types": "./dist/node.d.ts",
16
+ "import": "./dist/node.js",
17
+ "require": "./dist/node.cjs"
13
18
  }
14
19
  },
15
20
  "files": [
@@ -22,13 +27,13 @@
22
27
  "fast-glob": "^3.3.2"
23
28
  },
24
29
  "peerDependencies": {
25
- "@styleframe/core": "^3.3.0",
30
+ "@styleframe/core": "^3.5.0",
26
31
  "@styleframe/license": "^2.0.2"
27
32
  },
28
33
  "devDependencies": {
29
34
  "@styleframe/config-typescript": "^3.0.0",
30
35
  "@styleframe/config-vite": "^3.0.0",
31
- "@styleframe/core": "^3.3.0",
36
+ "@styleframe/core": "^3.5.0",
32
37
  "@styleframe/license": "^2.0.2",
33
38
  "@vitest/coverage-v8": "^3.2.4",
34
39
  "typescript": "^5.8.3",