@styleframe/scanner 2.0.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/index.cjs +665 -0
- package/dist/index.d.ts +419 -0
- package/dist/index.js +663 -0
- package/package.json +59 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { ModifierFactory } from '@styleframe/core';
|
|
2
|
+
import { Root } from '@styleframe/core';
|
|
3
|
+
import { Utility } from '@styleframe/core';
|
|
4
|
+
import { UtilityFactory } from '@styleframe/core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Pattern to extract the value from an arbitrary value bracket notation.
|
|
8
|
+
* Matches: [16px], [#1E3A8A], [10px_20px], etc.
|
|
9
|
+
*/
|
|
10
|
+
export declare const ARBITRARY_VALUE_PATTERN: RegExp;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Cache entry for a scanned file
|
|
14
|
+
*/
|
|
15
|
+
export declare interface CacheEntry {
|
|
16
|
+
/** Content hash for change detection */
|
|
17
|
+
hash: string;
|
|
18
|
+
/** Cached scan result */
|
|
19
|
+
result: FileScanResult;
|
|
20
|
+
/** Cache timestamp */
|
|
21
|
+
timestamp: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Generate the raw utility class name from options (without CSS escaping).
|
|
26
|
+
*/
|
|
27
|
+
export declare function classNameFromUtilityOptions(options: UtilitySelectorOptions): string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create a scanner cache instance.
|
|
31
|
+
*
|
|
32
|
+
* The cache stores scan results keyed by file path and validates
|
|
33
|
+
* entries using content hashing.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createCache(): ScannerCache;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create a file change handler with debouncing.
|
|
39
|
+
*
|
|
40
|
+
* This is a utility for integrating with external file watchers.
|
|
41
|
+
* The actual file watching should be done at the plugin level
|
|
42
|
+
* using Vite's HMR or chokidar.
|
|
43
|
+
*
|
|
44
|
+
* @param callback Function to call when files change
|
|
45
|
+
* @param options Watcher options
|
|
46
|
+
* @returns A debounced change handler
|
|
47
|
+
*/
|
|
48
|
+
export declare function createChangeHandler(callback: (changedFiles: string[]) => void, options?: WatcherOptions): {
|
|
49
|
+
onChange: (filePath: string) => void;
|
|
50
|
+
flush: () => void;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create a scanner that only scans specific content.
|
|
55
|
+
*
|
|
56
|
+
* Useful for testing or one-off scans.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createContentScanner(customExtractors?: Extractor[]): (content: string, filePath?: string) => ParsedUtility[];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Create a scanner instance for detecting utility classes in content files.
|
|
62
|
+
*
|
|
63
|
+
* @param config Scanner configuration
|
|
64
|
+
* @returns Scanner instance
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* const scanner = createScanner({
|
|
69
|
+
* content: ['./src/components/*.tsx', './src/pages/*.vue'],
|
|
70
|
+
* });
|
|
71
|
+
*
|
|
72
|
+
* const result = await scanner.scan();
|
|
73
|
+
* const matches = scanner.match(result.allParsed, root);
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function createScanner(config: ScannerConfig): Scanner;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Create a filter function that checks if a utility is in the used set.
|
|
80
|
+
*
|
|
81
|
+
* @param usedClasses Set of used utility class names
|
|
82
|
+
* @returns Filter function for utilities
|
|
83
|
+
*/
|
|
84
|
+
export declare function createUtilityFilter(usedClasses: Set<string>): (utility: Utility) => boolean;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Simple debounce utility
|
|
88
|
+
*/
|
|
89
|
+
export declare function debounce<T extends (...args: unknown[]) => void>(fn: T, delay: number): (...args: Parameters<T>) => void;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Default file extensions to scan for utility classes
|
|
93
|
+
*/
|
|
94
|
+
export declare const DEFAULT_EXTENSIONS: string[];
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Glob patterns to ignore when scanning
|
|
98
|
+
*/
|
|
99
|
+
export declare const DEFAULT_IGNORE_PATTERNS: string[];
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Extract utility classes from file content.
|
|
103
|
+
*
|
|
104
|
+
* @param content The file content
|
|
105
|
+
* @param filePath The file path (used to determine extractor)
|
|
106
|
+
* @param customExtractors Optional custom extractors to use in addition to defaults
|
|
107
|
+
* @returns Array of unique utility class names found
|
|
108
|
+
*/
|
|
109
|
+
export declare function extractClasses(content: string, filePath: string, customExtractors?: Extractor[]): string[];
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Extract utility classes from Astro content.
|
|
113
|
+
* Handles both HTML-like and JSX-like patterns.
|
|
114
|
+
*/
|
|
115
|
+
export declare function extractFromAstro(content: string): string[];
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Extract utility classes from HTML-like content.
|
|
119
|
+
* Handles class="..." attributes.
|
|
120
|
+
*/
|
|
121
|
+
export declare function extractFromHTML(content: string): string[];
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Extract utility classes from JSX/TSX content.
|
|
125
|
+
* Handles className="..." and className={...} patterns.
|
|
126
|
+
*/
|
|
127
|
+
export declare function extractFromJSX(content: string): string[];
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Extract utility classes from MDX content.
|
|
131
|
+
* Handles both Markdown and JSX patterns.
|
|
132
|
+
*/
|
|
133
|
+
export declare function extractFromMDX(content: string): string[];
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Extract utility classes from string literals in JavaScript/TypeScript code.
|
|
137
|
+
* Handles single quotes, double quotes, and template literals.
|
|
138
|
+
*
|
|
139
|
+
* Note: Template literals with interpolations (e.g., `_margin:${size}`) will only
|
|
140
|
+
* extract the static portions. Dynamic class names cannot be statically analyzed.
|
|
141
|
+
* For full coverage, use explicit string arrays or safelist patterns.
|
|
142
|
+
*/
|
|
143
|
+
export declare function extractFromStringLiterals(content: string): string[];
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Extract utility classes from Svelte content.
|
|
147
|
+
* Handles class="...", class:directive={condition}, and class={...} patterns.
|
|
148
|
+
*/
|
|
149
|
+
export declare function extractFromSvelte(content: string): string[];
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Extract utility classes from Vue SFC content.
|
|
153
|
+
* Handles class="...", :class="...", and :class="{...}" patterns.
|
|
154
|
+
*/
|
|
155
|
+
export declare function extractFromVue(content: string): string[];
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Custom extractor function type
|
|
159
|
+
*/
|
|
160
|
+
export declare type Extractor = (content: string, filePath: string) => string[];
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Extract all utility class names from a content string.
|
|
164
|
+
*
|
|
165
|
+
* @param content The content to search
|
|
166
|
+
* @returns Array of unique utility class names found
|
|
167
|
+
*/
|
|
168
|
+
export declare function extractUtilityClasses(content: string): string[];
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Scan result for a single file
|
|
172
|
+
*/
|
|
173
|
+
export declare interface FileScanResult {
|
|
174
|
+
/** Absolute file path */
|
|
175
|
+
path: string;
|
|
176
|
+
/** Set of raw class names found */
|
|
177
|
+
classes: Set<string>;
|
|
178
|
+
/** Parsed utility classes */
|
|
179
|
+
parsed: ParsedUtility[];
|
|
180
|
+
/** Timestamp of last scan */
|
|
181
|
+
lastScanned: number;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Filter root children to only include used utilities.
|
|
186
|
+
*
|
|
187
|
+
* @param root The Styleframe root instance
|
|
188
|
+
* @param usedClasses Set of used utility class names
|
|
189
|
+
* @returns Array of used children (utilities are filtered, other types pass through)
|
|
190
|
+
*/
|
|
191
|
+
export declare function filterUtilities(root: Root, usedClasses: Set<string>): Root["children"];
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Generate a utility selector string from components.
|
|
195
|
+
* This is the inverse of parseUtilityClass.
|
|
196
|
+
*
|
|
197
|
+
* @param name Utility name
|
|
198
|
+
* @param value Utility value
|
|
199
|
+
* @param modifiers Array of modifier names
|
|
200
|
+
* @returns The utility class name (without CSS escaping)
|
|
201
|
+
*/
|
|
202
|
+
export declare function generateUtilityClassName(name: string, value: string, modifiers?: string[]): string;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Generate the CSS selector for a utility instance.
|
|
206
|
+
*
|
|
207
|
+
* This mirrors the logic from @styleframe/transpiler/defaults.ts
|
|
208
|
+
*/
|
|
209
|
+
export declare function generateUtilitySelector(options: UtilitySelectorOptions): string;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Get matches for arbitrary values.
|
|
213
|
+
*/
|
|
214
|
+
export declare function getArbitraryMatches(matches: UtilityMatch[]): UtilityMatch[];
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get matches that exist in the registered values.
|
|
218
|
+
*/
|
|
219
|
+
export declare function getExistingMatches(matches: UtilityMatch[]): UtilityMatch[];
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get all unique utility class names from matches.
|
|
223
|
+
*/
|
|
224
|
+
export declare function getUsedClassNames(matches: UtilityMatch[]): Set<string>;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get matches that have a corresponding utility factory.
|
|
228
|
+
*/
|
|
229
|
+
export declare function getValidMatches(matches: UtilityMatch[]): UtilityMatch[];
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Create a simple hash from content for change detection.
|
|
233
|
+
* Uses a hash * 31 algorithm (similar to Java's String.hashCode),
|
|
234
|
+
* combined with content length to reduce collision probability.
|
|
235
|
+
*/
|
|
236
|
+
export declare function hashContent(content: string): string;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Check if a file path matches any of the given glob patterns.
|
|
240
|
+
*
|
|
241
|
+
* This is a simple check that looks for common pattern matches.
|
|
242
|
+
* For full glob support, use a library like micromatch.
|
|
243
|
+
*/
|
|
244
|
+
export declare function matchesPatterns(filePath: string, patterns: string[]): boolean;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Match parsed utility classes against registered utilities in the root.
|
|
248
|
+
*
|
|
249
|
+
* @param parsed Array of parsed utility classes
|
|
250
|
+
* @param root The Styleframe root instance
|
|
251
|
+
* @returns Array of match results
|
|
252
|
+
*/
|
|
253
|
+
export declare function matchUtilities(parsed: ParsedUtility[], root: Root): UtilityMatch[];
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Parsed utility class structure
|
|
257
|
+
*/
|
|
258
|
+
export declare interface ParsedUtility {
|
|
259
|
+
/** Original class name as found in content (e.g., "_margin:sm") */
|
|
260
|
+
raw: string;
|
|
261
|
+
/** Utility name (e.g., "margin", "background") */
|
|
262
|
+
name: string;
|
|
263
|
+
/** Value key (e.g., "sm", "primary", "[16px]") */
|
|
264
|
+
value: string;
|
|
265
|
+
/** Applied modifiers in order (e.g., ["hover", "dark"]) */
|
|
266
|
+
modifiers: string[];
|
|
267
|
+
/** Whether this uses arbitrary value syntax [value] */
|
|
268
|
+
isArbitrary: boolean;
|
|
269
|
+
/** The arbitrary value if isArbitrary is true (e.g., "16px") */
|
|
270
|
+
arbitraryValue?: string;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Parse a utility class name into its components.
|
|
275
|
+
*
|
|
276
|
+
* The utility class format is: _[modifiers:]name[:value]
|
|
277
|
+
*
|
|
278
|
+
* Examples:
|
|
279
|
+
* - "_margin:sm" → { name: "margin", value: "sm", modifiers: [] }
|
|
280
|
+
* - "_hover:margin:sm" → { name: "margin", value: "sm", modifiers: ["hover"] }
|
|
281
|
+
* - "_dark:hover:bg:primary" → { name: "bg", value: "primary", modifiers: ["dark", "hover"] }
|
|
282
|
+
* - "_margin:[16px]" → { name: "margin", value: "[16px]", isArbitrary: true, arbitraryValue: "16px" }
|
|
283
|
+
* - "_hidden" → { name: "hidden", value: "default", modifiers: [] }
|
|
284
|
+
*
|
|
285
|
+
* @param className The utility class name to parse
|
|
286
|
+
* @returns Parsed utility object or null if invalid
|
|
287
|
+
*/
|
|
288
|
+
export declare function parseUtilityClass(className: string): ParsedUtility | null;
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Quick utility to scan content and get parsed utilities.
|
|
292
|
+
*
|
|
293
|
+
* @param content Content string to scan
|
|
294
|
+
* @param filePath Optional file path hint for extractor selection
|
|
295
|
+
* @returns Array of parsed utilities
|
|
296
|
+
*/
|
|
297
|
+
export declare function quickScan(content: string, filePath?: string): ParsedUtility[];
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Scanner instance interface
|
|
301
|
+
*/
|
|
302
|
+
export declare interface Scanner {
|
|
303
|
+
/** Scan all content files */
|
|
304
|
+
scan(): Promise<ScanResult>;
|
|
305
|
+
/** Scan a single file */
|
|
306
|
+
scanFile(filePath: string): Promise<FileScanResult>;
|
|
307
|
+
/** Scan content string directly */
|
|
308
|
+
scanContent(content: string, filePath?: string): ParsedUtility[];
|
|
309
|
+
/** Match parsed utilities against a root instance */
|
|
310
|
+
match(parsed: ParsedUtility[], root: Root): UtilityMatch[];
|
|
311
|
+
/** Start watching content files for changes */
|
|
312
|
+
watch(callback: (result: ScanResult) => void): () => void;
|
|
313
|
+
/** Invalidate cache for a file or all files */
|
|
314
|
+
invalidate(filePath?: string): void;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Scanner cache interface
|
|
319
|
+
*/
|
|
320
|
+
export declare interface ScannerCache {
|
|
321
|
+
/** Get cached result for a file */
|
|
322
|
+
get(filePath: string): FileScanResult | null;
|
|
323
|
+
/** Cache a scan result */
|
|
324
|
+
set(filePath: string, result: FileScanResult, contentHash: string): void;
|
|
325
|
+
/** Check if a file has valid cache */
|
|
326
|
+
isValid(filePath: string, contentHash: string): boolean;
|
|
327
|
+
/** Get cached result if valid, null otherwise (single lookup) */
|
|
328
|
+
getIfValid(filePath: string, contentHash: string): FileScanResult | null;
|
|
329
|
+
/** Invalidate cache for a file */
|
|
330
|
+
invalidate(filePath: string): void;
|
|
331
|
+
/** Clear all cache entries */
|
|
332
|
+
clear(): void;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Configuration for the content scanner
|
|
337
|
+
*/
|
|
338
|
+
export declare interface ScannerConfig {
|
|
339
|
+
/** Glob patterns for files to scan */
|
|
340
|
+
content: string[];
|
|
341
|
+
/** Custom extraction functions */
|
|
342
|
+
extractors?: Extractor[];
|
|
343
|
+
/** Base directory for glob resolution (defaults to process.cwd()) */
|
|
344
|
+
cwd?: string;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Complete scan result across all files
|
|
349
|
+
*/
|
|
350
|
+
export declare interface ScanResult {
|
|
351
|
+
/** Map of file path to scan result */
|
|
352
|
+
files: Map<string, FileScanResult>;
|
|
353
|
+
/** All unique class names found */
|
|
354
|
+
allClasses: Set<string>;
|
|
355
|
+
/** All parsed utilities */
|
|
356
|
+
allParsed: ParsedUtility[];
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Regex pattern to match Styleframe utility class names.
|
|
361
|
+
*
|
|
362
|
+
* Matches patterns like:
|
|
363
|
+
* - _margin:sm (base utility)
|
|
364
|
+
* - _hover:margin:sm (with modifier)
|
|
365
|
+
* - _dark:hover:background:primary (multiple modifiers)
|
|
366
|
+
* - _margin:[16px] (arbitrary value)
|
|
367
|
+
* - _background:[#1E3A8A] (arbitrary color)
|
|
368
|
+
* - _hidden (default value, no suffix)
|
|
369
|
+
* - _background:color.primary (dotted reference)
|
|
370
|
+
*
|
|
371
|
+
* Pattern breakdown:
|
|
372
|
+
* - `_` - Required prefix
|
|
373
|
+
* - `[a-zA-Z][a-zA-Z0-9-]*` - First segment (modifier or name)
|
|
374
|
+
* - `(?::[a-zA-Z0-9._-]+|\:\[[^\]]+\])*` - Additional segments with `:` separator
|
|
375
|
+
*/
|
|
376
|
+
export declare const UTILITY_CLASS_PATTERN: RegExp;
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Filter function for utilities
|
|
380
|
+
*/
|
|
381
|
+
export declare type UtilityFilterFn = (utility: Utility) => boolean;
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Match result between a parsed class and a utility factory
|
|
385
|
+
*/
|
|
386
|
+
export declare interface UtilityMatch {
|
|
387
|
+
/** The parsed utility class */
|
|
388
|
+
parsed: ParsedUtility;
|
|
389
|
+
/** The matched utility factory, or null if not found */
|
|
390
|
+
factory: UtilityFactory | null;
|
|
391
|
+
/** Matched modifier factories */
|
|
392
|
+
modifierFactories: ModifierFactory[];
|
|
393
|
+
/** Whether the utility value exists in the factory */
|
|
394
|
+
exists: boolean;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Utility selector generation options
|
|
399
|
+
*/
|
|
400
|
+
export declare interface UtilitySelectorOptions {
|
|
401
|
+
name: string;
|
|
402
|
+
value: string;
|
|
403
|
+
modifiers: string[];
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Callback type for file change events
|
|
408
|
+
*/
|
|
409
|
+
export declare type WatchCallback = (result: ScanResult) => void;
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Options for creating a watcher
|
|
413
|
+
*/
|
|
414
|
+
export declare interface WatcherOptions {
|
|
415
|
+
/** Debounce time in milliseconds (default: 100) */
|
|
416
|
+
debounce?: number;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
export { }
|