tailwind-canonical 0.1.2 → 0.1.3

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/cli/index.js CHANGED
@@ -1,14 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import { analyzeFile } from '../core/analyzer.js';
3
+ import { dedupeFile } from '../core/deduplicator.js';
3
4
  import { fixFile } from '../core/fixer.js';
4
5
  import { mergeFile } from '../core/merger.js';
5
6
  import { scanFiles } from '../core/scanner.js';
6
7
  const args = process.argv.slice(2);
7
8
  const fix = args.includes('--fix');
8
9
  const merge = args.includes('--merge');
10
+ const dedup = args.includes('--dedup');
9
11
  const targets = args.filter((a) => !a.startsWith('--'));
10
12
  if (targets.length === 0) {
11
- console.error('Usage: tailwind-canonical [--fix] [--merge] <dir|file> [dir|file...]');
13
+ console.error('Usage: tailwind-canonical [--fix] [--merge] [--dedup] <dir|file> [dir|file...]');
12
14
  process.exit(1);
13
15
  }
14
16
  if (merge) {
@@ -30,6 +32,7 @@ const files = targets.flatMap((t) => scanFiles(t));
30
32
  let totalFindings = 0;
31
33
  let totalFixed = 0;
32
34
  let totalMerged = 0;
35
+ let totalDeduped = 0;
33
36
  for (const file of files) {
34
37
  if (fix) {
35
38
  const count = fixFile(file, config);
@@ -38,6 +41,13 @@ for (const file of files) {
38
41
  totalFixed += count;
39
42
  }
40
43
  }
44
+ if (dedup) {
45
+ const count = dedupeFile(file);
46
+ if (count > 0) {
47
+ console.log(` deduped ${file} (${count} class string${count > 1 ? 's' : ''})`);
48
+ totalDeduped += count;
49
+ }
50
+ }
41
51
  if (merge) {
42
52
  const count = await mergeFile(file);
43
53
  if (count > 0) {
@@ -45,7 +55,7 @@ for (const file of files) {
45
55
  totalMerged += count;
46
56
  }
47
57
  }
48
- if (!fix && !merge) {
58
+ if (!fix && !dedup && !merge) {
49
59
  const findings = analyzeFile(file, config);
50
60
  for (const f of findings) {
51
61
  const tag = f.suggestion.isCustomToken ? ' [custom token]' : '';
@@ -54,10 +64,12 @@ for (const file of files) {
54
64
  totalFindings += findings.length;
55
65
  }
56
66
  }
57
- if (fix || merge) {
67
+ if (fix || dedup || merge) {
58
68
  const parts = [];
59
69
  if (fix)
60
70
  parts.push(`${totalFixed} replacement${totalFixed !== 1 ? 's' : ''}`);
71
+ if (dedup)
72
+ parts.push(`${totalDeduped} dedup${totalDeduped !== 1 ? 's' : ''}`);
61
73
  if (merge)
62
74
  parts.push(`${totalMerged} conflict${totalMerged !== 1 ? 's' : ''} merged`);
63
75
  console.log(`\n✓ Fixed ${parts.join(', ')} across ${files.length} file${files.length !== 1 ? 's' : ''}`);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function deduplicateClasses(classStr: string): string;
2
+ export declare function dedupeFile(filePath: string): number;
3
+ //# sourceMappingURL=deduplicator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deduplicator.d.ts","sourceRoot":"","sources":["../../src/core/deduplicator.ts"],"names":[],"mappings":"AA+FA,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoD3D;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiBnD"}
@@ -0,0 +1,167 @@
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ const DISPLAY_GROUP = new Set([
3
+ 'block',
4
+ 'inline-block',
5
+ 'inline',
6
+ 'flex',
7
+ 'inline-flex',
8
+ 'table',
9
+ 'inline-table',
10
+ 'table-caption',
11
+ 'table-cell',
12
+ 'table-column',
13
+ 'table-column-group',
14
+ 'table-footer-group',
15
+ 'table-header-group',
16
+ 'table-row-group',
17
+ 'table-row',
18
+ 'flow-root',
19
+ 'grid',
20
+ 'inline-grid',
21
+ 'contents',
22
+ 'list-item',
23
+ 'hidden',
24
+ ]);
25
+ const POSITION_GROUP = new Set([
26
+ 'static',
27
+ 'fixed',
28
+ 'absolute',
29
+ 'relative',
30
+ 'sticky',
31
+ ]);
32
+ function expandSpacing(prefix, suffix) {
33
+ if (prefix === 'p' || prefix === 'm')
34
+ return { t: suffix, b: suffix, l: suffix, r: suffix };
35
+ if (prefix === 'px' || prefix === 'mx')
36
+ return { l: suffix, r: suffix };
37
+ if (prefix === 'py' || prefix === 'my')
38
+ return { t: suffix, b: suffix };
39
+ if (prefix === 'pt' || prefix === 'mt')
40
+ return { t: suffix };
41
+ if (prefix === 'pb' || prefix === 'mb')
42
+ return { b: suffix };
43
+ if (prefix === 'pl' || prefix === 'ml')
44
+ return { l: suffix };
45
+ if (prefix === 'pr' || prefix === 'mr')
46
+ return { r: suffix };
47
+ return null;
48
+ }
49
+ function collapseBox(box, kind) {
50
+ const { t, b, l, r } = box;
51
+ if (t && b && l && r) {
52
+ if (t === b && b === l && l === r)
53
+ return `${kind}-${t}`;
54
+ if (t === b && l === r)
55
+ return `${kind}y-${t} ${kind}x-${l}`;
56
+ if (l === r)
57
+ return `${kind}x-${l} ${kind}t-${t} ${kind}b-${b}`;
58
+ if (t === b)
59
+ return `${kind}y-${t} ${kind}l-${l} ${kind}r-${r}`;
60
+ return `${kind}t-${t} ${kind}b-${b} ${kind}l-${l} ${kind}r-${r}`;
61
+ }
62
+ const parts = [];
63
+ if (l && r) {
64
+ parts.push(l === r ? `${kind}x-${l}` : `${kind}l-${l} ${kind}r-${r}`);
65
+ }
66
+ else {
67
+ if (l)
68
+ parts.push(`${kind}l-${l}`);
69
+ if (r)
70
+ parts.push(`${kind}r-${r}`);
71
+ }
72
+ if (t && b) {
73
+ parts.push(t === b ? `${kind}y-${t}` : `${kind}t-${t} ${kind}b-${b}`);
74
+ }
75
+ else {
76
+ if (t)
77
+ parts.push(`${kind}t-${t}`);
78
+ if (b)
79
+ parts.push(`${kind}b-${b}`);
80
+ }
81
+ return parts.join(' ');
82
+ }
83
+ function parseSpacing(cls) {
84
+ const m = cls.match(/^(p|px|py|pt|pb|pl|pr|m|mx|my|mt|mb|ml|mr)-(.+)$/);
85
+ if (!m)
86
+ return null;
87
+ const kind = m[1].startsWith('p') ? 'p' : 'm';
88
+ return { kind, prefix: m[1], suffix: m[2] };
89
+ }
90
+ function processSpacingGroup(classes, box, kind) {
91
+ if (classes.length === 0)
92
+ return [];
93
+ const collapsed = collapseBox(box, kind);
94
+ const original = classes.filter((c, i) => classes.indexOf(c) === i).join(' ');
95
+ return collapsed === original ? original.split(' ') : collapsed.split(' ');
96
+ }
97
+ export function deduplicateClasses(classStr) {
98
+ const classes = classStr.split(/\s+/).filter(Boolean);
99
+ if (classes.length <= 1)
100
+ return classStr;
101
+ const result = [];
102
+ let displayWinner = null;
103
+ let positionWinner = null;
104
+ const seen = new Set();
105
+ const pBox = { t: '', b: '', l: '', r: '' };
106
+ const mBox = { t: '', b: '', l: '', r: '' };
107
+ const pClasses = [];
108
+ const mClasses = [];
109
+ const others = [];
110
+ for (const cls of classes) {
111
+ if (DISPLAY_GROUP.has(cls)) {
112
+ displayWinner = cls;
113
+ continue;
114
+ }
115
+ if (POSITION_GROUP.has(cls)) {
116
+ positionWinner = cls;
117
+ continue;
118
+ }
119
+ const sp = parseSpacing(cls);
120
+ if (sp) {
121
+ const expansion = expandSpacing(sp.prefix, sp.suffix);
122
+ if (expansion) {
123
+ const box = sp.kind === 'p' ? pBox : mBox;
124
+ (sp.kind === 'p' ? pClasses : mClasses).push(cls);
125
+ if (expansion.t !== undefined)
126
+ box.t = expansion.t;
127
+ if (expansion.b !== undefined)
128
+ box.b = expansion.b;
129
+ if (expansion.l !== undefined)
130
+ box.l = expansion.l;
131
+ if (expansion.r !== undefined)
132
+ box.r = expansion.r;
133
+ continue;
134
+ }
135
+ }
136
+ if (!seen.has(cls)) {
137
+ seen.add(cls);
138
+ others.push(cls);
139
+ }
140
+ }
141
+ if (displayWinner)
142
+ result.push(displayWinner);
143
+ if (positionWinner)
144
+ result.push(positionWinner);
145
+ result.push(...processSpacingGroup(pClasses, pBox, 'p'));
146
+ result.push(...processSpacingGroup(mClasses, mBox, 'm'));
147
+ result.push(...others);
148
+ return result.join(' ');
149
+ }
150
+ export function dedupeFile(filePath) {
151
+ let content = readFileSync(filePath, 'utf8');
152
+ let count = 0;
153
+ const CLASS_ATTR_REGEX = /className\s*=\s*(?:"([^"]+)"|'([^']+)'|`([^`]+)`)/g;
154
+ content = content.replace(CLASS_ATTR_REGEX, (full, dq, sq, bt) => {
155
+ const raw = dq ?? sq ?? bt ?? '';
156
+ const quote = dq !== undefined ? '"' : sq !== undefined ? "'" : '`';
157
+ const deduped = deduplicateClasses(raw);
158
+ if (deduped === raw)
159
+ return full;
160
+ count++;
161
+ return `className=${quote}${deduped}${quote}`;
162
+ });
163
+ if (count > 0)
164
+ writeFileSync(filePath, content, 'utf8');
165
+ return count;
166
+ }
167
+ //# sourceMappingURL=deduplicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deduplicator.js","sourceRoot":"","sources":["../../src/core/deduplicator.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export type { Finding } from './core/analyzer.js';
2
2
  export { analyzeFile } from './core/analyzer.js';
3
+ export { dedupeFile, deduplicateClasses } from './core/deduplicator.js';
3
4
  export { fixFile } from './core/fixer.js';
4
5
  export { mergeFile } from './core/merger.js';
5
6
  export type { Config, Suggestion } from './core/rules.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { analyzeFile } from './core/analyzer.js';
2
+ export { dedupeFile, deduplicateClasses } from './core/deduplicator.js';
2
3
  export { fixFile } from './core/fixer.js';
3
4
  export { mergeFile } from './core/merger.js';
4
5
  export { suggestCanonical } from './core/rules.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwind-canonical",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Lint and auto-fix Tailwind CSS arbitrary values that have canonical equivalents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",