Skip to content

Commit 216da52

Browse files
authored
improve generated style sorting (#82)
1 parent 0e85a2e commit 216da52

20 files changed

Lines changed: 844 additions & 637 deletions

.changeset/yellow-paths-add.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@fuzdev/fuz_css': patch
3+
---
4+
5+
improve generated style sorting

src/lib/class_variable_index.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export interface CssClassVariableIndex {
2323
* Builds an index of CSS variables used by each class definition.
2424
*
2525
* @param definitions - CSS class definitions to index
26-
* @returns CssClassVariableIndex with variable lookups
26+
* @returns `CssClassVariableIndex` with variable lookups
2727
*/
2828
export const build_class_variable_index = (
2929
definitions: Record<string, CssClassDefinition | undefined>,
@@ -74,9 +74,9 @@ const extract_variables_from_definition = (definition: CssClassDefinition): Set<
7474
/**
7575
* Gets variables used by a specific class.
7676
*
77-
* @param index - The class variable index
78-
* @param class_name - Name of the class to lookup
79-
* @returns Set of variable names (without -- prefix), or null if class not found
77+
* @param index - the class variable index
78+
* @param class_name - name of the class to lookup
79+
* @returns set of variable names (without -- prefix), or null if class not found
8080
*/
8181
export const get_class_variables = (
8282
index: CssClassVariableIndex,
@@ -86,9 +86,9 @@ export const get_class_variables = (
8686
/**
8787
* Collects all variables used by a set of classes.
8888
*
89-
* @param index - The class variable index
90-
* @param class_names - Class names to collect variables from
91-
* @returns Set of all variable names used by the classes
89+
* @param index - the class variable index
90+
* @param class_names - class names to collect variables from
91+
* @returns set of all variable names used by the classes
9292
*/
9393
export const collect_class_variables = (
9494
index: CssClassVariableIndex,
@@ -111,9 +111,9 @@ export const collect_class_variables = (
111111
/**
112112
* Gets all class names that use a specific variable.
113113
*
114-
* @param index - The class variable index
115-
* @param variable_name - Variable name to search for (without -- prefix)
116-
* @returns Array of class names that use this variable
114+
* @param index - the class variable index
115+
* @param variable_name - variable name to search for (without -- prefix)
116+
* @returns array of class names that use this variable
117117
*/
118118
export const get_classes_using_variable = (
119119
index: CssClassVariableIndex,

src/lib/css_bundled_resolution.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,36 +50,39 @@ const TYPO_SIMILARITY_THRESHOLD = 0.6;
5050
*
5151
* See variable_graph.ts for the Levenshtein-based approach used for variables.
5252
*/
53-
const string_similarity = (a: string, b: string): number => {
54-
if (a === b) return 1;
55-
if (a.length < 2 || b.length < 2) return 0;
56-
57-
const bigrams_a: Set<string> = new Set();
58-
for (let i = 0; i < a.length - 1; i++) {
59-
bigrams_a.add(a.slice(i, i + 2));
53+
const build_bigrams = (str: string): Set<string> => {
54+
const bigrams: Set<string> = new Set();
55+
for (let i = 0; i < str.length - 1; i++) {
56+
bigrams.add(str.slice(i, i + 2));
6057
}
58+
return bigrams;
59+
};
6160

61+
const string_similarity = (bigrams_a: Set<string>, len_a: number, b: string): number => {
62+
if (len_a < 2 || b.length < 2) return 0;
6263
let matches = 0;
6364
for (let i = 0; i < b.length - 1; i++) {
6465
if (bigrams_a.has(b.slice(i, i + 2))) matches++;
6566
}
66-
67-
return (2 * matches) / (a.length - 1 + b.length - 1);
67+
return (2 * matches) / (len_a - 1 + b.length - 1);
6868
};
6969

7070
/**
7171
* Finds the most similar name from a set of known names.
7272
*
73-
* @param name - The name to find similar matches for
74-
* @param known_names - Set of known valid names
75-
* @returns The most similar name, or null if none are similar enough
73+
* @param name - the name to find similar matches for
74+
* @param known_names - set of known valid names
75+
* @returns the most similar name, or null if none are similar enough
7676
*/
7777
const find_similar_name = (name: string, known_names: Set<string>): string | null => {
78+
if (name === '') return null;
79+
const bigrams_a = build_bigrams(name);
7880
let best_match: string | null = null;
7981
let best_similarity = TYPO_SIMILARITY_THRESHOLD;
8082

8183
for (const known of known_names) {
82-
const similarity = string_similarity(name, known);
84+
if (name === known) return known; // exact match fast path
85+
const similarity = string_similarity(bigrams_a, name.length, known);
8386
if (similarity > best_similarity) {
8487
best_similarity = similarity;
8588
best_match = known;
@@ -182,8 +185,8 @@ export interface CssResolutionOptions {
182185
* 3. Resolve transitive variable dependencies
183186
* 4. Generate output: theme_css (light+dark), base_css (source order)
184187
*
185-
* @param options - Resolution options including indexes, detected usage, and config
186-
* @returns Resolution result with theme CSS, base CSS, and diagnostics
188+
* @param options - resolution options including indexes, detected usage, and config
189+
* @returns resolution result with theme CSS, base CSS, and diagnostics
187190
*/
188191
export const resolve_css = (options: CssResolutionOptions): CssResolutionResult => {
189192
const {
@@ -430,10 +433,10 @@ export interface GenerateBundledCssOptions {
430433
/**
431434
* Generates combined CSS output from resolution result.
432435
*
433-
* @param result - Resolution result from resolve_css
434-
* @param utility_css - Generated utility CSS (from generate_classes_css)
435-
* @param options - Output options
436-
* @returns Combined CSS string
436+
* @param result - resolution result from `resolve_css`
437+
* @param utility_css - generated utility CSS (from `generate_classes_css`)
438+
* @param options - output options
439+
* @returns combined CSS string
437440
*/
438441
export const generate_bundled_css = (
439442
result: CssResolutionResult,

src/lib/css_cache.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ export interface CachedExtraction {
6161
* Computes the cache file path for a source file.
6262
* Cache structure mirrors source tree: `src/lib/Foo.svelte` → `.fuz/cache/css/src/lib/Foo.svelte.json`
6363
*
64-
* @param source_path - Absolute path to the source file
65-
* @param cache_dir - Absolute path to the cache directory
66-
* @param project_root - Normalized project root (must end with `/`)
64+
* @param source_path - absolute path to the source file
65+
* @param cache_dir - absolute path to the cache directory
66+
* @param project_root - normalized project root (must end with `/`)
6767
*/
6868
export const get_cache_path = (
6969
source_path: string,
@@ -82,9 +82,9 @@ export const get_cache_path = (
8282
* Internal files use relative paths mirroring source tree.
8383
* External files (outside project root) use hashed absolute paths in `_external/`.
8484
*
85-
* @param file_id - Absolute path to the source file
86-
* @param cache_dir - Absolute path to the cache directory
87-
* @param project_root - Normalized project root (must end with `/`)
85+
* @param file_id - absolute path to the source file
86+
* @param cache_dir - absolute path to the cache directory
87+
* @param project_root - normalized project root (must end with `/`)
8888
*/
8989
export const get_file_cache_path = (
9090
file_id: string,
@@ -102,8 +102,8 @@ export const get_file_cache_path = (
102102
* Returns `null` if the cache is missing, corrupted, or has a version mismatch.
103103
* This makes the cache self-healing: any error triggers re-extraction.
104104
*
105-
* @param ops - Filesystem operations for dependency injection
106-
* @param cache_path - Absolute path to the cache file
105+
* @param ops - filesystem operations for dependency injection
106+
* @param cache_path - absolute path to the cache file
107107
*/
108108
export const load_cached_extraction = async (
109109
ops: CacheOperations,
@@ -133,10 +133,10 @@ export const load_cached_extraction = async (
133133
* Uses atomic write (temp file + rename) for crash safety.
134134
* Normalizes empty collections to null to avoid allocation overhead on load.
135135
*
136-
* @param ops - Filesystem operations for dependency injection
137-
* @param cache_path - Absolute path to the cache file
136+
* @param ops - filesystem operations for dependency injection
137+
* @param cache_path - absolute path to the cache file
138138
* @param content_hash - SHA-256 hash of the source file contents
139-
* @param extraction - Extraction data to cache
139+
* @param extraction - extraction data to cache
140140
*/
141141
export const save_cached_extraction = async (
142142
ops: CacheOperations,
@@ -184,8 +184,8 @@ export const save_cached_extraction = async (
184184
* Deletes a cached extraction file.
185185
* Silently succeeds if the file doesn't exist.
186186
*
187-
* @param ops - Filesystem operations for dependency injection
188-
* @param cache_path - Absolute path to the cache file
187+
* @param ops - filesystem operations for dependency injection
188+
* @param cache_path - absolute path to the cache file
189189
*/
190190
export const delete_cached_extraction = async (
191191
ops: CacheOperations,
@@ -198,7 +198,7 @@ export const delete_cached_extraction = async (
198198
* Converts a cached extraction back to the runtime format.
199199
* Preserves null semantics (null = empty).
200200
*
201-
* @param cached - Cached extraction data
201+
* @param cached - cached extraction data
202202
*/
203203
export const from_cached_extraction = (cached: CachedExtraction): ExtractionData => ({
204204
classes: cached.classes ? new Map(cached.classes) : null,

src/lib/css_class_definitions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,9 @@ export const css_class_definitions: Record<string, CssClassDefinition | undefine
321321
* Merges user class definitions with the built-in defaults.
322322
* User definitions take precedence over defaults with the same name.
323323
*
324-
* @param user_definitions - User-provided class definitions to merge
325-
* @param include_defaults - Whether to include built-in definitions
326-
* @returns Merged class definitions
324+
* @param user_definitions - user-provided class definitions to merge
325+
* @param include_defaults - whether to include built-in definitions
326+
* @returns merged class definitions
327327
* @throws Error if `include_defaults` is false and no user definitions provided
328328
*/
329329
export const merge_class_definitions = (

src/lib/css_class_extractor.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ export class SourceIndex {
140140
* Converts a character offset to a source location.
141141
*
142142
* @param offset - 0-based character offset in the source
143-
* @param file - File path for the location
144-
* @returns SourceLocation with 1-based line and column
143+
* @param file - file path for the location
144+
* @returns `SourceLocation` with 1-based line and column
145145
*/
146146
get_location(offset: number, file: string): SourceLocation {
147147
// Binary search for line
@@ -159,10 +159,10 @@ export class SourceIndex {
159159
/**
160160
* Adds a class with its location to the extraction result.
161161
*
162-
* @param classes - Map of classes to locations
163-
* @param class_name - Class name to add
164-
* @param location - Source location where the class was found
165-
* @mutates classes - Adds or appends to the map entry
162+
* @param classes - map of classes to locations
163+
* @param class_name - class name to add
164+
* @param location - source location where the class was found
165+
* @mutates classes - adds or appends to the map entry
166166
*/
167167
const add_class_with_location = (
168168
classes: Map<string, Array<SourceLocation>>,
@@ -285,9 +285,9 @@ const location_from_offset = (state: WalkState, offset: number): SourceLocation
285285
/**
286286
* Extracts CSS classes from a Svelte file using AST parsing.
287287
*
288-
* @param source - The Svelte file source code
289-
* @param file - File path for location tracking
290-
* @returns Extraction result with classes, tracked variables, elements, and diagnostics
288+
* @param source - the Svelte file source code
289+
* @param file - file path for location tracking
290+
* @returns extraction result with classes, tracked variables, elements, and diagnostics
291291
*/
292292
export const extract_from_svelte = (source: string, file = '<unknown>'): ExtractionResult => {
293293
const source_index = new SourceIndex(source);
@@ -474,10 +474,10 @@ const extract_fuz_comments_from_script = (
474474
/**
475475
* Extracts CSS classes from a TypeScript/JS file using AST parsing.
476476
*
477-
* @param source - The TS/JS file source code
478-
* @param file - File path for location tracking
479-
* @param acorn_plugins - Additional acorn plugins (e.g., acorn-jsx for React)
480-
* @returns Extraction result with classes, tracked variables, elements, and diagnostics
477+
* @param source - the TS/JS file source code
478+
* @param file - file path for location tracking
479+
* @param acorn_plugins - additional acorn plugins (e.g., acorn-jsx for React)
480+
* @returns extraction result with classes, tracked variables, elements, and diagnostics
481481
*/
482482
export const extract_from_ts = (
483483
source: string,
@@ -547,9 +547,9 @@ export const extract_from_ts = (
547547
* Unified extraction function that auto-detects file type.
548548
* Returns just the class names as a Set.
549549
*
550-
* @param source - The file source code
551-
* @param options - Extraction options
552-
* @returns Set of class names, or null if none found
550+
* @param source - the file source code
551+
* @param options - extraction options
552+
* @returns set of class names, or null if none found
553553
*/
554554
export const extract_css_classes = (
555555
source: string,
@@ -563,9 +563,9 @@ export const extract_css_classes = (
563563
* Unified extraction function that auto-detects file type.
564564
* Returns full extraction result with locations and diagnostics.
565565
*
566-
* @param source - The file source code
567-
* @param options - Extraction options
568-
* @returns Full extraction result with classes, tracked variables, and diagnostics
566+
* @param source - the file source code
567+
* @param options - extraction options
568+
* @returns full extraction result with classes, tracked variables, and diagnostics
569569
*/
570570
export const extract_css_classes_with_locations = (
571571
source: string,

0 commit comments

Comments
 (0)