@productivemark/snipcss 1.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.
Files changed (117) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/.claude-plugin/plugin.json +10 -0
  3. package/.mcp.json +8 -0
  4. package/dist/auth/config-manager.d.ts +13 -0
  5. package/dist/auth/config-manager.d.ts.map +1 -0
  6. package/dist/auth/config-manager.js +48 -0
  7. package/dist/auth/config-manager.js.map +1 -0
  8. package/dist/auth/usage-gate.d.ts +13 -0
  9. package/dist/auth/usage-gate.d.ts.map +1 -0
  10. package/dist/auth/usage-gate.js +69 -0
  11. package/dist/auth/usage-gate.js.map +1 -0
  12. package/dist/browser/browser-manager.d.ts +15 -0
  13. package/dist/browser/browser-manager.d.ts.map +1 -0
  14. package/dist/browser/browser-manager.js +61 -0
  15. package/dist/browser/browser-manager.js.map +1 -0
  16. package/dist/browser/viewport-manager.d.ts +8 -0
  17. package/dist/browser/viewport-manager.d.ts.map +1 -0
  18. package/dist/browser/viewport-manager.js +50 -0
  19. package/dist/browser/viewport-manager.js.map +1 -0
  20. package/dist/extraction/css-variable-resolver.d.ts +27 -0
  21. package/dist/extraction/css-variable-resolver.d.ts.map +1 -0
  22. package/dist/extraction/css-variable-resolver.js +105 -0
  23. package/dist/extraction/css-variable-resolver.js.map +1 -0
  24. package/dist/extraction/dom-labeler.d.ts +26 -0
  25. package/dist/extraction/dom-labeler.d.ts.map +1 -0
  26. package/dist/extraction/dom-labeler.js +124 -0
  27. package/dist/extraction/dom-labeler.js.map +1 -0
  28. package/dist/extraction/element-discovery.d.ts +59 -0
  29. package/dist/extraction/element-discovery.d.ts.map +1 -0
  30. package/dist/extraction/element-discovery.js +525 -0
  31. package/dist/extraction/element-discovery.js.map +1 -0
  32. package/dist/extraction/extraction-pipeline.d.ts +26 -0
  33. package/dist/extraction/extraction-pipeline.d.ts.map +1 -0
  34. package/dist/extraction/extraction-pipeline.js +200 -0
  35. package/dist/extraction/extraction-pipeline.js.map +1 -0
  36. package/dist/extraction/font-collector.d.ts +26 -0
  37. package/dist/extraction/font-collector.d.ts.map +1 -0
  38. package/dist/extraction/font-collector.js +160 -0
  39. package/dist/extraction/font-collector.js.map +1 -0
  40. package/dist/extraction/html-cleaner.d.ts +16 -0
  41. package/dist/extraction/html-cleaner.d.ts.map +1 -0
  42. package/dist/extraction/html-cleaner.js +149 -0
  43. package/dist/extraction/html-cleaner.js.map +1 -0
  44. package/dist/extraction/keyframe-collector.d.ts +16 -0
  45. package/dist/extraction/keyframe-collector.d.ts.map +1 -0
  46. package/dist/extraction/keyframe-collector.js +62 -0
  47. package/dist/extraction/keyframe-collector.js.map +1 -0
  48. package/dist/extraction/pseudo-state-handler.d.ts +36 -0
  49. package/dist/extraction/pseudo-state-handler.d.ts.map +1 -0
  50. package/dist/extraction/pseudo-state-handler.js +210 -0
  51. package/dist/extraction/pseudo-state-handler.js.map +1 -0
  52. package/dist/extraction/result-builder.d.ts +25 -0
  53. package/dist/extraction/result-builder.d.ts.map +1 -0
  54. package/dist/extraction/result-builder.js +136 -0
  55. package/dist/extraction/result-builder.js.map +1 -0
  56. package/dist/extraction/rule-deduplicator.d.ts +39 -0
  57. package/dist/extraction/rule-deduplicator.d.ts.map +1 -0
  58. package/dist/extraction/rule-deduplicator.js +107 -0
  59. package/dist/extraction/rule-deduplicator.js.map +1 -0
  60. package/dist/extraction/selector-fixer.d.ts +25 -0
  61. package/dist/extraction/selector-fixer.d.ts.map +1 -0
  62. package/dist/extraction/selector-fixer.js +111 -0
  63. package/dist/extraction/selector-fixer.js.map +1 -0
  64. package/dist/extraction/specificity.d.ts +17 -0
  65. package/dist/extraction/specificity.d.ts.map +1 -0
  66. package/dist/extraction/specificity.js +88 -0
  67. package/dist/extraction/specificity.js.map +1 -0
  68. package/dist/extraction/style-matcher.d.ts +33 -0
  69. package/dist/extraction/style-matcher.d.ts.map +1 -0
  70. package/dist/extraction/style-matcher.js +199 -0
  71. package/dist/extraction/style-matcher.js.map +1 -0
  72. package/dist/extraction/stylesheet-collector.d.ts +33 -0
  73. package/dist/extraction/stylesheet-collector.d.ts.map +1 -0
  74. package/dist/extraction/stylesheet-collector.js +71 -0
  75. package/dist/extraction/stylesheet-collector.js.map +1 -0
  76. package/dist/index.d.ts +3 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +235 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/mcp-server.d.ts +3 -0
  81. package/dist/mcp-server.d.ts.map +1 -0
  82. package/dist/mcp-server.js +349 -0
  83. package/dist/mcp-server.js.map +1 -0
  84. package/dist/tailwind/css-to-tailwind.d.ts +17 -0
  85. package/dist/tailwind/css-to-tailwind.d.ts.map +1 -0
  86. package/dist/tailwind/css-to-tailwind.js +1583 -0
  87. package/dist/tailwind/css-to-tailwind.js.map +1 -0
  88. package/dist/tailwind/shorthand-expander.d.ts +27 -0
  89. package/dist/tailwind/shorthand-expander.d.ts.map +1 -0
  90. package/dist/tailwind/shorthand-expander.js +812 -0
  91. package/dist/tailwind/shorthand-expander.js.map +1 -0
  92. package/dist/tailwind/tailwind-converter.d.ts +35 -0
  93. package/dist/tailwind/tailwind-converter.d.ts.map +1 -0
  94. package/dist/tailwind/tailwind-converter.js +1223 -0
  95. package/dist/tailwind/tailwind-converter.js.map +1 -0
  96. package/dist/tailwind/tailwind-helpers.d.ts +95 -0
  97. package/dist/tailwind/tailwind-helpers.d.ts.map +1 -0
  98. package/dist/tailwind/tailwind-helpers.js +593 -0
  99. package/dist/tailwind/tailwind-helpers.js.map +1 -0
  100. package/dist/tailwind/tailwind-reducer.d.ts +36 -0
  101. package/dist/tailwind/tailwind-reducer.d.ts.map +1 -0
  102. package/dist/tailwind/tailwind-reducer.js +189 -0
  103. package/dist/tailwind/tailwind-reducer.js.map +1 -0
  104. package/dist/types/index.d.ts +239 -0
  105. package/dist/types/index.d.ts.map +1 -0
  106. package/dist/types/index.js +94 -0
  107. package/dist/types/index.js.map +1 -0
  108. package/dist/utils/helpers.d.ts +34 -0
  109. package/dist/utils/helpers.d.ts.map +1 -0
  110. package/dist/utils/helpers.js +120 -0
  111. package/dist/utils/helpers.js.map +1 -0
  112. package/dist/utils/parsel.d.ts +41 -0
  113. package/dist/utils/parsel.d.ts.map +1 -0
  114. package/dist/utils/parsel.js +314 -0
  115. package/dist/utils/parsel.js.map +1 -0
  116. package/package.json +41 -0
  117. package/skills/workflow/SKILL.md +95 -0
@@ -0,0 +1,1583 @@
1
+ /**
2
+ * CSS property to Tailwind class conversion.
3
+ * Port of tailwind_properties.js (4,001 lines)
4
+ *
5
+ * Exports:
6
+ * - cssToTailwind() main property→class mapper
7
+ * - getBestTailwindClasses() optimized margin/padding classes
8
+ * - getTransformClasses() transform value → Tailwind classes
9
+ * - getFilterClasses() filter/backdrop-filter → Tailwind classes
10
+ * - getFontClasses() font shorthand → Tailwind classes
11
+ */
12
+ // ── Utility helpers ─────────────────────────────────────────────────
13
+ function escapeValue(value) {
14
+ return value
15
+ .replace(/\\/g, '\\\\')
16
+ .replace(/\]/g, '\\]')
17
+ .replace(/\[/g, '\\[')
18
+ .replace(/"/g, '\\"')
19
+ .replace(/'/g, "\\'");
20
+ }
21
+ function spacesToUnderscore(value) {
22
+ return value.replace(/\s+/g, '_');
23
+ }
24
+ function getPxValue(value) {
25
+ value = value.trim().toLowerCase();
26
+ const numValue = parseFloat(value);
27
+ if (isNaN(numValue))
28
+ return null;
29
+ if (value.endsWith('rem'))
30
+ return numValue * 16;
31
+ if (value.endsWith('px'))
32
+ return numValue;
33
+ if (value.endsWith('em'))
34
+ return numValue * 16;
35
+ if (value.endsWith('%')) {
36
+ return value === '100%' ? 9999 : null;
37
+ }
38
+ return numValue;
39
+ }
40
+ function standardizeBorderRadiusValue(value) {
41
+ value = value.trim().toLowerCase();
42
+ if (['none', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', 'full'].includes(value))
43
+ return value;
44
+ const pxValue = getPxValue(value);
45
+ if (pxValue !== null)
46
+ return `${Math.round(pxValue)}px`;
47
+ return value;
48
+ }
49
+ function standardizeSpacingValue(value) {
50
+ value = value.trim().toLowerCase();
51
+ const knownValues = ['auto', 'px', '0', '0.5', '1', '1.5', '2', '2.5', '3', '3.5', '4', '5', '6', '7', '8', '9', '10', '11', '12', '14', '16', '20', '24', '28', '32', '36', '40', '44', '48', '52', '56', '60', '64', '72', '80', '96'];
52
+ if (knownValues.includes(value))
53
+ return value;
54
+ const pxValue = getPxValue(value);
55
+ if (pxValue !== null) {
56
+ const predefinedPxValues = {
57
+ 0: '0', 1: 'px', 2: '0.5', 4: '1', 6: '1.5', 8: '2', 10: '2.5', 12: '3', 14: '3.5',
58
+ 16: '4', 20: '5', 24: '6', 28: '7', 32: '8', 36: '9', 40: '10', 44: '11', 48: '12',
59
+ 56: '14', 64: '16', 80: '20', 96: '24', 112: '28', 128: '32', 144: '36', 160: '40',
60
+ 176: '44', 192: '48', 208: '52', 224: '56', 240: '60', 256: '64', 288: '72', 320: '80', 384: '96',
61
+ };
62
+ const rounded = Math.round(pxValue);
63
+ return predefinedPxValues[rounded] ?? `${rounded}px`;
64
+ }
65
+ return value;
66
+ }
67
+ // ── Spacing scale (reused by several helpers) ───────────────────────
68
+ function makeSpacingScale(prefix) {
69
+ const vals = ['0', 'px', '0.5', '1', '1.5', '2', '2.5', '3', '3.5', '4', '5', '6', '7', '8', '9', '10', '11', '12', '14', '16', '20', '24', '28', '32', '36', '40', '44', '48', '52', '56', '60', '64', '72', '80', '96', 'auto'];
70
+ const m = {};
71
+ for (const v of vals)
72
+ m[v] = `${prefix}-${v}`;
73
+ return m;
74
+ }
75
+ // ── Handler factories ───────────────────────────────────────────────
76
+ function handleSize(dimension, sizeType) {
77
+ const prefix = sizeType === 'min' ? `min-${dimension}` : sizeType === 'max' ? `max-${dimension}` : dimension;
78
+ const predefinedSizesNone = {
79
+ '1/2': `${prefix}-1/2`, '1/3': `${prefix}-1/3`, '2/3': `${prefix}-2/3`,
80
+ '1/4': `${prefix}-1/4`, '2/4': `${prefix}-1/2`, '3/4': `${prefix}-3/4`,
81
+ '1/5': `${prefix}-1/5`, '2/5': `${prefix}-2/5`, '3/5': `${prefix}-3/5`, '4/5': `${prefix}-4/5`,
82
+ '1/6': `${prefix}-1/6`, '2/6': `${prefix}-1/3`, '3/6': `${prefix}-1/2`,
83
+ '4/6': `${prefix}-2/3`, '5/6': `${prefix}-5/6`,
84
+ '1/12': `${prefix}-1/12`, '2/12': `${prefix}-1/6`, '3/12': `${prefix}-1/4`,
85
+ '4/12': `${prefix}-1/3`, '5/12': `${prefix}-5/12`, '6/12': `${prefix}-1/2`,
86
+ '7/12': `${prefix}-7/12`, '8/12': `${prefix}-2/3`, '9/12': `${prefix}-3/4`,
87
+ '10/12': `${prefix}-5/6`, '11/12': `${prefix}-11/12`,
88
+ '50%': `${prefix}-1/2`, '33.333333%': `${prefix}-1/3`, '66.666667%': `${prefix}-2/3`,
89
+ '25%': `${prefix}-1/4`, '75%': `${prefix}-3/4`,
90
+ '20%': `${prefix}-1/5`, '40%': `${prefix}-2/5`, '60%': `${prefix}-3/5`, '80%': `${prefix}-4/5`,
91
+ '16.666667%': `${prefix}-1/6`, '83.333333%': `${prefix}-5/6`,
92
+ ...Object.fromEntries(['0', '1', '2', '3', '4', '5', '6', '8', '10', '12', '14', '16', '20', '24', '28', '32', '36', '40', '44', '48', '52', '56', '60', '64', '72', '80', '96']
93
+ .map(v => [v, `${prefix}-${v}`])),
94
+ 'auto': `${prefix}-auto`, 'px': `${prefix}-px`, 'full': `${prefix}-full`,
95
+ 'screen': `${prefix}-screen`, 'min': `${prefix}-min`, 'max': `${prefix}-max`, 'fit': `${prefix}-fit`,
96
+ };
97
+ const predefinedSizesMinMax = {
98
+ '0': `${prefix}-0`, 'full': `${prefix}-full`, 'min': `${prefix}-min`,
99
+ 'max': `${prefix}-max`, 'fit': `${prefix}-fit`,
100
+ 'screen': sizeType === 'min' ? `${prefix}-screen` : undefined,
101
+ 'none': sizeType === 'max' ? `${prefix}-none` : undefined,
102
+ ...(sizeType === 'max' && dimension === 'w' ? {
103
+ 'xs': `${prefix}-xs`, 'sm': `${prefix}-sm`, 'md': `${prefix}-md`, 'lg': `${prefix}-lg`,
104
+ 'xl': `${prefix}-xl`, '2xl': `${prefix}-2xl`, '3xl': `${prefix}-3xl`, '4xl': `${prefix}-4xl`,
105
+ '5xl': `${prefix}-5xl`, '6xl': `${prefix}-6xl`, '7xl': `${prefix}-7xl`,
106
+ 'screen-sm': `${prefix}-screen-sm`, 'screen-md': `${prefix}-screen-md`,
107
+ 'screen-lg': `${prefix}-screen-lg`, 'screen-xl': `${prefix}-screen-xl`,
108
+ 'screen-2xl': `${prefix}-screen-2xl`,
109
+ } : {}),
110
+ };
111
+ const predefined = sizeType === 'none' ? predefinedSizesNone : predefinedSizesMinMax;
112
+ return (value) => {
113
+ const v = value.trim();
114
+ const mapped = predefined[v];
115
+ if (mapped)
116
+ return mapped;
117
+ return `${prefix}-[${spacesToUnderscore(escapeValue(v))}]`;
118
+ };
119
+ }
120
+ function handleBorderRadius(property) {
121
+ const propertyMap = {
122
+ 'border-radius': 'rounded', 'border-top-left-radius': 'rounded-tl',
123
+ 'border-top-right-radius': 'rounded-tr', 'border-bottom-left-radius': 'rounded-bl',
124
+ 'border-bottom-right-radius': 'rounded-br', 'border-top-radius': 'rounded-t',
125
+ 'border-right-radius': 'rounded-r', 'border-bottom-radius': 'rounded-b',
126
+ 'border-left-radius': 'rounded-l',
127
+ };
128
+ const prefix = propertyMap[property];
129
+ if (!prefix)
130
+ return (value) => `[${property}:${escapeValue(value)}]`;
131
+ const predefined = {
132
+ '0px': `${prefix}-none`, '0': `${prefix}-none`, '2px': `${prefix}-sm`,
133
+ '4px': prefix, '6px': `${prefix}-md`, '8px': `${prefix}-lg`,
134
+ '12px': `${prefix}-xl`, '16px': `${prefix}-2xl`, '24px': `${prefix}-3xl`,
135
+ '9999px': `${prefix}-full`, '100%': `${prefix}-full`,
136
+ 'none': `${prefix}-none`, 'sm': `${prefix}-sm`, 'md': `${prefix}-md`,
137
+ 'lg': `${prefix}-lg`, 'xl': `${prefix}-xl`, '2xl': `${prefix}-2xl`,
138
+ '3xl': `${prefix}-3xl`, 'full': `${prefix}-full`,
139
+ };
140
+ return (value) => {
141
+ const trimmed = value.trim();
142
+ const values = trimmed.split(/\s+/);
143
+ if (values.length === 1) {
144
+ const std = standardizeBorderRadiusValue(values[0]);
145
+ return predefined[std] ?? `${prefix}-[${escapeValue(values[0])}]`;
146
+ }
147
+ return `[${property}:${escapeValue(values.join('_'))}]`;
148
+ };
149
+ }
150
+ function handleSpacing(property) {
151
+ const propertyMap = {
152
+ 'padding': 'p', 'padding-top': 'pt', 'padding-right': 'pr', 'padding-bottom': 'pb', 'padding-left': 'pl',
153
+ 'padding-horizontal': 'px', 'padding-vertical': 'py',
154
+ 'padding-inline': 'px', 'padding-inline-start': 'pl', 'padding-inline-end': 'pr',
155
+ 'margin': 'm', 'margin-top': 'mt', 'margin-right': 'mr', 'margin-bottom': 'mb', 'margin-left': 'ml',
156
+ 'margin-horizontal': 'mx', 'margin-vertical': 'my',
157
+ 'margin-inline': 'mx', 'margin-inline-start': 'ml', 'margin-inline-end': 'mr',
158
+ 'gap': 'gap', 'gap-x': 'gap-x', 'gap-y': 'gap-y',
159
+ };
160
+ const prefix = propertyMap[property];
161
+ if (!prefix)
162
+ return (value) => `[${property}:${escapeValue(value)}]`;
163
+ const predefined = makeSpacingScale(prefix);
164
+ const isMargin = prefix.startsWith('m');
165
+ return (value) => {
166
+ const trimmed = value.trim();
167
+ // Tokenize respecting parentheses
168
+ const values = [];
169
+ let token = '';
170
+ let parenCount = 0;
171
+ for (let i = 0; i < trimmed.length; i++) {
172
+ const ch = trimmed[i];
173
+ if (ch === '(') {
174
+ parenCount++;
175
+ token += ch;
176
+ }
177
+ else if (ch === ')') {
178
+ parenCount--;
179
+ token += ch;
180
+ }
181
+ else if (/\s/.test(ch) && parenCount === 0) {
182
+ if (token.trim()) {
183
+ values.push(token.trim());
184
+ token = '';
185
+ }
186
+ }
187
+ else {
188
+ token += ch;
189
+ }
190
+ }
191
+ if (token.trim())
192
+ values.push(token.trim());
193
+ let sidePrefix = prefix;
194
+ if (property.endsWith('-start'))
195
+ sidePrefix = isMargin ? 'ml' : 'pl';
196
+ else if (property.endsWith('-end'))
197
+ sidePrefix = isMargin ? 'mr' : 'pr';
198
+ if (values.length === 1) {
199
+ return predefined[values[0]] ?? `${sidePrefix}-[${spacesToUnderscore(escapeValue(values[0]))}]`;
200
+ }
201
+ else if (values.length === 2) {
202
+ const [v1, v2] = values;
203
+ const startPfx = isMargin ? 'ml' : 'pl';
204
+ const endPfx = isMargin ? 'mr' : 'pr';
205
+ const startClass = predefined[v1]
206
+ ? predefined[v1].replace(prefix, startPfx)
207
+ : `${startPfx}-[${spacesToUnderscore(escapeValue(v1))}]`;
208
+ const endClass = predefined[v2]
209
+ ? predefined[v2].replace(prefix, endPfx)
210
+ : `${endPfx}-[${spacesToUnderscore(escapeValue(v2))}]`;
211
+ return `${startClass} ${endClass}`;
212
+ }
213
+ return `${sidePrefix}-[${spacesToUnderscore(escapeValue(trimmed))}]`;
214
+ };
215
+ }
216
+ function handleGapSpacing(property) {
217
+ const prefixMap = {
218
+ 'row-gap': 'gap-y', 'column-gap': 'gap-x', 'grid-row-gap': 'gap-y', 'grid-column-gap': 'gap-x',
219
+ };
220
+ const prefix = prefixMap[property];
221
+ const predefined = makeSpacingScale(prefix);
222
+ return (value) => {
223
+ const v = value.trim();
224
+ return predefined[v] ?? `${prefix}-[${spacesToUnderscore(escapeValue(v))}]`;
225
+ };
226
+ }
227
+ function handleFlex() {
228
+ const predefined = { '1': 'flex-1', 'auto': 'flex-auto', 'initial': 'flex-initial', 'none': 'flex-none' };
229
+ return (value) => {
230
+ const v = value.trim();
231
+ if (predefined[v])
232
+ return predefined[v];
233
+ return `flex-[${escapeValue(v).replace(/\s+/g, '_')}]`;
234
+ };
235
+ }
236
+ function handlePosition(property) {
237
+ const prefix = property; // top, right, bottom, left
238
+ const predefined = makeSpacingScale(prefix);
239
+ return (value) => {
240
+ const std = standardizeSpacingValue(value);
241
+ return predefined[std] ?? `${prefix}-[${spacesToUnderscore(escapeValue(value.trim()))}]`;
242
+ };
243
+ }
244
+ function handleGridTemplate(property) {
245
+ return (value) => {
246
+ const v = value.trim();
247
+ if (v === 'none')
248
+ return property === 'grid-template-columns' ? 'grid-cols-none' : 'grid-rows-none';
249
+ const repeatMatch = v.match(/^repeat\((\d+),\s*1fr\)$/);
250
+ if (repeatMatch) {
251
+ return property === 'grid-template-columns' ? `grid-cols-${repeatMatch[1]}` : `grid-rows-${repeatMatch[1]}`;
252
+ }
253
+ const escaped = escapeValue(v).replace(/\s+/g, '_');
254
+ return property === 'grid-template-columns' ? `grid-cols-[${escaped}]` : `grid-rows-[${escaped}]`;
255
+ };
256
+ }
257
+ function handleGridColumnStart() {
258
+ return (value) => {
259
+ if (value === 'auto')
260
+ return 'col-start-auto';
261
+ const spanMatch = value.match(/^span\s+(\d+)$/i);
262
+ if (spanMatch)
263
+ return `col-span-${spanMatch[1]}`;
264
+ if (/^\d+$/.test(value))
265
+ return `col-start-[${value}]`;
266
+ return `[grid-column-start:${escapeValue(value)}]`;
267
+ };
268
+ }
269
+ function handleGridColumnEnd() {
270
+ return (value) => {
271
+ if (value === 'auto')
272
+ return 'col-end-auto';
273
+ const spanMatch = value.match(/^span\s+(\d+)$/i);
274
+ if (spanMatch)
275
+ return `col-span-${spanMatch[1]}`;
276
+ if (/^\d+$/.test(value))
277
+ return `col-end-[${value}]`;
278
+ return `[grid-column-end:${escapeValue(value)}]`;
279
+ };
280
+ }
281
+ function handleGridRowStart() {
282
+ return (value) => {
283
+ if (value === 'auto')
284
+ return 'row-start-auto';
285
+ const spanMatch = value.match(/^span\s+(\d+)$/i);
286
+ if (spanMatch)
287
+ return `row-span-${spanMatch[1]}`;
288
+ if (/^\d+$/.test(value))
289
+ return `row-start-[${value}]`;
290
+ return `[grid-row-start:${escapeValue(value)}]`;
291
+ };
292
+ }
293
+ function handleGridRowEnd() {
294
+ return (value) => {
295
+ if (value === 'auto')
296
+ return 'row-end-auto';
297
+ const spanMatch = value.match(/^span\s+(\d+)$/i);
298
+ if (spanMatch)
299
+ return `row-span-${spanMatch[1]}`;
300
+ if (/^\d+$/.test(value))
301
+ return `row-end-[${value}]`;
302
+ return `[grid-row-end:${escapeValue(value)}]`;
303
+ };
304
+ }
305
+ function handleBorderWidth(property) {
306
+ const side = property.match(/border-(top|right|bottom|left)-width/);
307
+ const prefix = side ? `border-${side[1][0]}` : 'border';
308
+ return (value) => {
309
+ const widthMap = {
310
+ 'thin': prefix, 'medium': `${prefix}-2`, 'thick': `${prefix}-4`,
311
+ '0': `${prefix}-0`, '1px': prefix, '2px': `${prefix}-2`, '4px': `${prefix}-4`, '8px': `${prefix}-8`,
312
+ };
313
+ return widthMap[value] ?? `${prefix}-[${spacesToUnderscore(escapeValue(value.trim()))}]`;
314
+ };
315
+ }
316
+ function handleBorderStyle(property) {
317
+ const side = property.match(/border-(top|right|bottom|left)-style/);
318
+ return (value) => {
319
+ if (side)
320
+ return `[${property}:${value}]`;
321
+ const styleMap = {
322
+ 'none': 'border-none', 'hidden': 'border-none', 'solid': 'border-solid',
323
+ 'dashed': 'border-dashed', 'dotted': 'border-dotted', 'double': 'border-double',
324
+ 'groove': '[border-style:groove]', 'ridge': '[border-style:ridge]',
325
+ 'inset': '[border-style:inset]', 'outset': '[border-style:outset]',
326
+ };
327
+ return styleMap[value] ?? `border-[${spacesToUnderscore(escapeValue(value.trim()))}]`;
328
+ };
329
+ }
330
+ function handleBorderColor(property) {
331
+ const side = property.match(/border-(top|right|bottom|left)-color/);
332
+ const prefix = side ? `border-${side[1][0]}` : 'border';
333
+ return (value) => {
334
+ const colorMap = {
335
+ 'transparent': `${prefix}-transparent`, 'current': `${prefix}-current`,
336
+ 'black': `${prefix}-black`, 'white': `${prefix}-white`,
337
+ 'inherit': `${prefix}-inherit`, 'currentColor': `${prefix}-current`,
338
+ };
339
+ if (colorMap[value])
340
+ return colorMap[value];
341
+ if (/^#([0-9a-fA-F]{3,8})$/.test(value))
342
+ return `${prefix}-[${value}]`;
343
+ if (/^rgb[a]?\([\d\s,%.]+\)$/.test(value))
344
+ return `${prefix}-[${value.replace(/\s+/g, '_')}]`;
345
+ if (/^hsl[a]?\([\d\s%,.]+\)$/.test(value))
346
+ return `${prefix}-[${value.replace(/\s+/g, '_')}]`;
347
+ if (value.startsWith('var('))
348
+ return `${prefix}-[${value}]`;
349
+ if (/^[a-z]+-\d+$/.test(value))
350
+ return `${prefix}-${value}`;
351
+ return `${prefix}-[${spacesToUnderscore(escapeValue(value.trim()))}]`;
352
+ };
353
+ }
354
+ function handleOutlineWidth() {
355
+ return (value) => {
356
+ const widthMap = {
357
+ '0': 'outline-0', '1px': 'outline-[0.0625rem]', '2px': 'outline-[0.125rem]',
358
+ '4px': 'outline-[0.25rem]', '8px': 'outline-[0.5rem]',
359
+ };
360
+ return widthMap[value] ?? `outline-[${spacesToUnderscore(escapeValue(value.trim()))}]`;
361
+ };
362
+ }
363
+ function handleOutlineStyle() {
364
+ return (value) => {
365
+ const styleMap = {
366
+ 'none': 'outline-none', 'solid': 'outline-[solid]', 'dashed': 'outline-[dashed]',
367
+ 'dotted': 'outline-[dotted]', 'double': 'outline-[double]', 'groove': 'outline-[groove]',
368
+ 'ridge': 'outline-[ridge]', 'inset': 'outline-[inset]', 'outset': 'outline-[outset]',
369
+ };
370
+ return styleMap[value] ?? `outline-[${spacesToUnderscore(escapeValue(value.trim()))}]`;
371
+ };
372
+ }
373
+ // ── Color mapping helper (shared by color / outline-color) ──────────
374
+ function makeColorMapping(prefix) {
375
+ const colors = ['slate', 'gray', 'red', 'blue', 'green', 'yellow'];
376
+ const shades = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
377
+ const m = { 'black': `${prefix}-black`, 'white': `${prefix}-white` };
378
+ for (const c of colors) {
379
+ for (const s of shades)
380
+ m[`${c}-${s}`] = `${prefix}-${c}-${s}`;
381
+ }
382
+ m['transparent'] = `${prefix}-transparent`;
383
+ m['current'] = `${prefix}-current`;
384
+ m['inherit'] = `${prefix}-inherit`;
385
+ return m;
386
+ }
387
+ export function cssToTailwind(property, value) {
388
+ try {
389
+ const mappings = {
390
+ 'position': { 'static': 'static', 'relative': 'relative', 'absolute': 'absolute', 'fixed': 'fixed', 'sticky': 'sticky' },
391
+ 'clear': { 'none': 'clear-none', 'left': 'clear-left', 'right': 'clear-right', 'both': 'clear-both' },
392
+ 'resize': { 'none': 'resize-none', 'y': 'resize-y', 'x': 'resize-x', 'both': 'resize' },
393
+ 'background': (v) => `[background:${spacesToUnderscore(escapeValue(v))}]`,
394
+ 'object-fit': { 'contain': 'object-contain', 'cover': 'object-cover', 'fill': 'object-fill', 'none': 'object-none', 'scale-down': 'object-scale-down' },
395
+ 'min-height': handleSize('h', 'min'),
396
+ 'max-height': handleSize('h', 'max'),
397
+ 'min-width': handleSize('w', 'min'),
398
+ 'max-width': handleSize('w', 'max'),
399
+ 'width': handleSize('w', 'none'),
400
+ 'height': handleSize('h', 'none'),
401
+ 'padding': () => { throw new Error('padding not expanded'); },
402
+ 'padding-top': handleSpacing('padding-top'),
403
+ 'padding-right': handleSpacing('padding-right'),
404
+ 'padding-bottom': handleSpacing('padding-bottom'),
405
+ 'padding-left': handleSpacing('padding-left'),
406
+ 'padding-horizontal': handleSpacing('padding-horizontal'),
407
+ 'padding-vertical': handleSpacing('padding-vertical'),
408
+ 'padding-inline': handleSpacing('padding-inline'),
409
+ 'padding-inline-start': handleSpacing('padding-inline-start'),
410
+ 'padding-inline-end': handleSpacing('padding-inline-end'),
411
+ 'margin': () => { throw new Error('margin not expanded'); },
412
+ 'margin-top': handleSpacing('margin-top'),
413
+ 'margin-right': handleSpacing('margin-right'),
414
+ 'margin-bottom': handleSpacing('margin-bottom'),
415
+ 'margin-left': handleSpacing('margin-left'),
416
+ 'margin-horizontal': handleSpacing('margin-horizontal'),
417
+ 'margin-vertical': handleSpacing('margin-vertical'),
418
+ 'margin-inline': handleSpacing('padding-inline'),
419
+ 'margin-inline-start': handleSpacing('padding-inline-start'),
420
+ 'margin-inline-end': handleSpacing('padding-inline-end'),
421
+ 'grid-row-gap': handleGapSpacing('row-gap'),
422
+ 'row-gap': handleGapSpacing('row-gap'),
423
+ 'grid-column-gap': handleGapSpacing('column-gap'),
424
+ 'column-gap': handleGapSpacing('column-gap'),
425
+ 'grid-template-columns': handleGridTemplate('grid-template-columns'),
426
+ 'grid-template-rows': handleGridTemplate('grid-template-rows'),
427
+ 'gap': handleSpacing('gap'),
428
+ 'gap-x': handleSpacing('gap-x'),
429
+ 'gap-y': handleSpacing('gap-y'),
430
+ 'grid-column': () => { throw new Error('grid-column not expanded'); },
431
+ 'grid-row': () => { throw new Error('grid-row not expanded'); },
432
+ 'grid-template': () => { throw new Error('grid-template not expanded'); },
433
+ 'grid-area': () => { throw new Error('grid-area not expanded'); },
434
+ 'grid-column-start': handleGridColumnStart(),
435
+ 'grid-column-end': handleGridColumnEnd(),
436
+ 'grid-row-start': handleGridRowStart(),
437
+ 'grid-row-end': handleGridRowEnd(),
438
+ 'grid-auto-flow': (v) => {
439
+ const flowMap = {
440
+ 'row': 'grid-flow-row', 'column': 'grid-flow-col',
441
+ 'row dense': 'grid-flow-row-dense', 'column dense': 'grid-flow-col-dense', 'dense': 'grid-flow-dense',
442
+ };
443
+ return flowMap[v] ?? `[grid-auto-flow:${escapeValue(v)}]`;
444
+ },
445
+ 'grid-auto-columns': (v) => {
446
+ const map = { 'auto': 'grid-auto-cols-auto', 'min-content': 'grid-auto-cols-min', 'max-content': 'grid-auto-cols-max', '1fr': 'grid-auto-cols-fr' };
447
+ return map[v] ?? `grid-auto-cols-[${spacesToUnderscore(escapeValue(v))}]`;
448
+ },
449
+ 'grid-auto-rows': (v) => {
450
+ const map = { 'auto': 'grid-auto-rows-auto', 'min-content': 'grid-auto-rows-min', 'max-content': 'grid-auto-rows-max', '1fr': 'grid-auto-rows-fr' };
451
+ return map[v] ?? `grid-auto-rows-[${spacesToUnderscore(escapeValue(v))}]`;
452
+ },
453
+ 'grid-gap': (v) => {
454
+ const trimmed = v.trim();
455
+ const predefined = makeSpacingScale('gap');
456
+ return predefined[trimmed] ?? `gap-[${spacesToUnderscore(escapeValue(trimmed))}]`;
457
+ },
458
+ 'left': handlePosition('left'),
459
+ 'top': handlePosition('top'),
460
+ 'right': handlePosition('right'),
461
+ 'bottom': handlePosition('bottom'),
462
+ 'z-index': (v) => {
463
+ const map = { '0': 'z-0', '10': 'z-10', '20': 'z-20', '30': 'z-30', '40': 'z-40', '50': 'z-50', 'auto': 'z-auto' };
464
+ return map[v] ?? `z-[${spacesToUnderscore(escapeValue(v))}]`;
465
+ },
466
+ 'color': (v) => {
467
+ const map = makeColorMapping('text');
468
+ return map[v] ?? `text-[${spacesToUnderscore(escapeValue(v))}]`;
469
+ },
470
+ 'outline-color': (v) => {
471
+ const map = makeColorMapping('outline');
472
+ return map[v] ?? `outline-[${spacesToUnderscore(escapeValue(v))}]`;
473
+ },
474
+ 'outline-width': handleOutlineWidth(),
475
+ 'outline-style': handleOutlineStyle(),
476
+ 'border-radius': handleBorderRadius('border-radius'),
477
+ 'border-top-left-radius': handleBorderRadius('border-top-left-radius'),
478
+ 'border-top-right-radius': handleBorderRadius('border-top-right-radius'),
479
+ 'border-bottom-left-radius': handleBorderRadius('border-bottom-left-radius'),
480
+ 'border-bottom-right-radius': handleBorderRadius('border-bottom-right-radius'),
481
+ 'border-top-radius': handleBorderRadius('border-top-radius'),
482
+ 'border-right-radius': handleBorderRadius('border-right-radius'),
483
+ 'border-bottom-radius': handleBorderRadius('border-bottom-radius'),
484
+ 'border-left-radius': handleBorderRadius('border-left-radius'),
485
+ 'border': () => { throw new Error('border not expanded'); },
486
+ 'border-bottom': () => { throw new Error('border-bottom not expanded'); },
487
+ 'border-left': () => { throw new Error('border-left not expanded'); },
488
+ 'border-top': () => { throw new Error('border-top not expanded'); },
489
+ 'border-right': () => { throw new Error('border-right not expanded'); },
490
+ 'border-width': handleBorderWidth('border-width'),
491
+ 'border-style': handleBorderStyle('border-style'),
492
+ 'border-color': handleBorderColor('border-color'),
493
+ 'border-top-width': handleBorderWidth('border-top-width'),
494
+ 'border-top-style': handleBorderStyle('border-top-style'),
495
+ 'border-top-color': handleBorderColor('border-top-color'),
496
+ 'border-right-width': handleBorderWidth('border-right-width'),
497
+ 'border-right-style': handleBorderStyle('border-right-style'),
498
+ 'border-right-color': handleBorderColor('border-right-color'),
499
+ 'border-bottom-width': handleBorderWidth('border-bottom-width'),
500
+ 'border-bottom-style': handleBorderStyle('border-bottom-style'),
501
+ 'border-bottom-color': handleBorderColor('border-bottom-color'),
502
+ 'border-left-width': handleBorderWidth('border-left-width'),
503
+ 'border-left-style': handleBorderStyle('border-left-style'),
504
+ 'border-left-color': handleBorderColor('border-left-color'),
505
+ 'opacity': (v) => {
506
+ const num = parseFloat(v);
507
+ if (isNaN(num))
508
+ return `opacity-[${v}]`;
509
+ const pct = Math.round(num * 100);
510
+ const map = {
511
+ 0: 'opacity-0', 5: 'opacity-5', 10: 'opacity-10', 20: 'opacity-20', 25: 'opacity-25',
512
+ 30: 'opacity-30', 40: 'opacity-40', 50: 'opacity-50', 60: 'opacity-60', 70: 'opacity-70',
513
+ 75: 'opacity-75', 80: 'opacity-80', 90: 'opacity-90', 95: 'opacity-95', 100: 'opacity-100',
514
+ };
515
+ return map[pct] ?? `[opacity:${spacesToUnderscore(escapeValue(v))}]`;
516
+ },
517
+ 'flex': handleFlex(),
518
+ 'flex-direction': { 'row': 'flex-row', 'row-reverse': 'flex-row-reverse', 'column': 'flex-col', 'column-reverse': 'flex-col-reverse' },
519
+ 'justify-content': {
520
+ 'normal': 'justify-normal', 'flex-start': 'justify-start', 'start': 'justify-start', 'left': 'justify-start',
521
+ 'flex-end': 'justify-end', 'end': 'justify-end', 'right': 'justify-end', 'center': 'justify-center',
522
+ 'space-between': 'justify-between', 'space-around': 'justify-around', 'space-evenly': 'justify-evenly',
523
+ },
524
+ 'flex-flow': () => { throw new Error('flex-flow not expanded'); },
525
+ 'place-self': () => { throw new Error('place-self not expanded'); },
526
+ 'align-self': {
527
+ 'auto': 'self-auto', 'flex-start': 'self-start', 'flex-end': 'self-end',
528
+ 'center': 'self-center', 'stretch': 'self-stretch', 'baseline': 'self-baseline',
529
+ 'initial': '[align-self:initial]', 'inherit': '[align-self:inherit]',
530
+ },
531
+ 'justify-self': {
532
+ 'auto': 'justify-self-auto', 'start': 'justify-self-start', 'end': 'justify-self-end',
533
+ 'center': 'justify-self-center', 'stretch': 'justify-self-stretch',
534
+ 'initial': '[justify-self:initial]', 'inherit': '[justify-self:inherit]',
535
+ 'baseline': 'justify-self-baseline', 'first baseline': 'justify-self-first', 'last baseline': 'justify-self-last',
536
+ },
537
+ 'overflow': { 'visible': 'overflow-visible', 'hidden': 'overflow-hidden', 'auto': 'overflow-auto', 'scroll': 'overflow-scroll', 'clip': 'overflow-clip' },
538
+ 'overflow-x': { 'visible': 'overflow-x-visible', 'hidden': 'overflow-x-hidden', 'auto': 'overflow-x-auto', 'scroll': 'overflow-x-scroll', 'clip': 'overflow-x-clip' },
539
+ 'overflow-y': { 'visible': 'overflow-y-visible', 'hidden': 'overflow-y-hidden', 'auto': 'overflow-y-auto', 'scroll': 'overflow-y-scroll', 'clip': 'overflow-y-clip' },
540
+ 'float': { 'left': 'float-left', 'right': 'float-right', 'none': 'float-none' },
541
+ 'line-break': { 'normal': 'break-normal', 'anywhere': 'break-anywhere', 'keep-all': 'break-keep' },
542
+ 'font-weight': {
543
+ '100': 'font-thin', '200': 'font-extralight', '300': 'font-light', '400': 'font-normal',
544
+ '500': 'font-medium', '600': 'font-semibold', '700': 'font-bold', '800': 'font-extrabold', '900': 'font-black',
545
+ 'thin': 'font-thin', 'extralight': 'font-extralight', 'light': 'font-light', 'normal': 'font-normal',
546
+ 'medium': 'font-medium', 'semibold': 'font-semibold', 'bold': 'font-bold', 'extrabold': 'font-extrabold', 'black': 'font-black',
547
+ },
548
+ 'font-style': (v) => {
549
+ const map = { 'normal': 'not-italic', 'italic': 'italic' };
550
+ return map[v] ?? `[font-style:${escapeValue(v)}]`;
551
+ },
552
+ 'font-feature-settings': (v) => {
553
+ const map = {
554
+ '"liga" 0': 'font-ligatures-none', '"liga" 1': 'font-ligatures-normal', 'normal': 'font-normal',
555
+ '"kern"': 'font-kerning-auto', '"kern" 0': 'font-kerning-none', '"kern" 1': 'font-kerning-normal',
556
+ '"clig" 0': 'font-common-ligatures-none', '"clig" 1': 'font-common-ligatures-normal',
557
+ };
558
+ return map[v] ?? `[font-feature-settings:${spacesToUnderscore(escapeValue(v))}]`;
559
+ },
560
+ 'font-variation-settings': (v) => v === 'normal' ? 'font-normal' : `[font-variation-settings:${spacesToUnderscore(escapeValue(v))}]`,
561
+ 'text-align': { 'left': 'text-left', 'right': 'text-right', 'center': 'text-center', 'justify': 'text-justify' },
562
+ 'text-transform': { 'none': 'normal-case', 'capitalize': 'capitalize', 'uppercase': 'uppercase', 'lowercase': 'lowercase' },
563
+ 'text-decoration-style': { 'solid': 'decoration-solid', 'double': 'decoration-double', 'dotted': 'decoration-dotted', 'dashed': 'decoration-dashed', 'wavy': 'decoration-wavy' },
564
+ 'text-decoration-thickness': (v) => {
565
+ const map = {
566
+ 'auto': 'decoration-auto', 'from-font': 'decoration-from-font',
567
+ '0': 'decoration-0', '0px': 'decoration-0', '1px': 'decoration-1', '2px': 'decoration-2', '4px': 'decoration-4', '8px': 'decoration-8',
568
+ };
569
+ return map[v] ?? `decoration-[${spacesToUnderscore(escapeValue(v))}]`;
570
+ },
571
+ 'text-wrap': {
572
+ 'balance': 'text-balance', 'pretty': 'text-pretty', 'nowrap': 'text-nowrap', 'wrap': 'text-wrap',
573
+ 'normal': '[text-wrap:normal]', 'initial': '[text-wrap:initial]', 'inherit': '[text-wrap:inherit]',
574
+ },
575
+ 'scrollbar-width': { 'none': 'hide-scrollbar', 'thin': 'scrollbar-thin', 'auto': 'scrollbar' },
576
+ 'vertical-align': (v) => {
577
+ const map = {
578
+ 'baseline': 'align-baseline', 'top': 'align-top', 'middle': 'align-middle', 'bottom': 'align-bottom',
579
+ 'text-top': 'align-text-top', 'text-bottom': 'align-text-bottom', 'sub': 'align-sub', 'super': 'align-super',
580
+ };
581
+ return map[v] ?? `align-[${escapeValue(v)}]`;
582
+ },
583
+ 'line-height': (v) => {
584
+ const map = {
585
+ '1': 'leading-none', '1.25': 'leading-tight', '1.375': 'leading-snug', '1.5': 'leading-normal',
586
+ '1.625': 'leading-relaxed', '2': 'leading-loose',
587
+ '0.75rem': 'leading-3', '1rem': 'leading-4', '1.25rem': 'leading-5', '1.5rem': 'leading-6',
588
+ '1.75rem': 'leading-7', '2rem': 'leading-8', '2.25rem': 'leading-9', '2.5rem': 'leading-10',
589
+ };
590
+ return map[v] ?? `leading-[${spacesToUnderscore(escapeValue(v))}]`;
591
+ },
592
+ 'border-collapse': {
593
+ 'collapse': 'border-collapse', 'separate': 'border-separate',
594
+ 'inherit': '[border-collapse:inherit]', 'initial': '[border-collapse:initial]',
595
+ 'revert': '[border-collapse:revert]', 'unset': '[border-collapse:unset]',
596
+ },
597
+ 'caption-side': {
598
+ 'top': 'caption-top', 'bottom': 'caption-bottom',
599
+ 'inherit': '[caption-side:inherit]', 'initial': '[caption-side:initial]',
600
+ 'revert': '[caption-side:revert]', 'unset': '[caption-side:unset]',
601
+ },
602
+ 'empty-cells': {
603
+ 'show': '[empty-cells:show]', 'hide': '[empty-cells:hide]',
604
+ 'inherit': '[empty-cells:inherit]', 'initial': '[empty-cells:initial]',
605
+ 'revert': '[empty-cells:revert]', 'unset': '[empty-cells:unset]',
606
+ },
607
+ 'text-indent': (v) => {
608
+ if (v === '0' || v === '0px')
609
+ return 'indent-0';
610
+ if (v.startsWith('-'))
611
+ return `-indent-[${spacesToUnderscore(escapeValue(v.slice(1)))}]`;
612
+ return `indent-[${spacesToUnderscore(escapeValue(v))}]`;
613
+ },
614
+ 'border-spacing': (v) => {
615
+ if (!v.includes(' ')) {
616
+ if (v === '0' || v === '0px')
617
+ return 'border-spacing-0';
618
+ return `border-spacing-[${spacesToUnderscore(escapeValue(v))}]`;
619
+ }
620
+ const [x, y] = v.split(' ').map(s => s.trim());
621
+ if (x === y) {
622
+ if (x === '0' || x === '0px')
623
+ return 'border-spacing-0';
624
+ return `border-spacing-[${spacesToUnderscore(escapeValue(x))}]`;
625
+ }
626
+ const xClass = (x === '0' || x === '0px') ? 'border-spacing-x-0' : `border-spacing-x-[${spacesToUnderscore(escapeValue(x))}]`;
627
+ const yClass = (y === '0' || y === '0px') ? 'border-spacing-y-0' : `border-spacing-y-[${spacesToUnderscore(escapeValue(y))}]`;
628
+ return `${xClass} ${yClass}`;
629
+ },
630
+ 'text-decoration': { 'underline': 'underline', 'overline': 'overline', 'line-through': 'line-through', 'none': 'no-underline' },
631
+ 'text-decoration-line': { 'underline': 'underline', 'overline': 'overline', 'line-through': 'line-through', 'none': 'no-underline' },
632
+ 'text-decoration-color': (v) => `decoration-[${spacesToUnderscore(escapeValue(v))}]`,
633
+ 'text-underline-offset': (v) => {
634
+ const map = {
635
+ 'auto': 'underline-offset-auto', '0': 'underline-offset-0', '0px': 'underline-offset-0',
636
+ '1px': 'underline-offset-1', '2px': 'underline-offset-2', '4px': 'underline-offset-4', '8px': 'underline-offset-8',
637
+ };
638
+ return map[v] ?? `underline-offset-[${spacesToUnderscore(escapeValue(v))}]`;
639
+ },
640
+ 'text-decoration-skip-ink': (v) => `[text-decoration-skip-ink:${spacesToUnderscore(escapeValue(v))}]`,
641
+ 'transform': () => { throw new Error('transform has special function'); },
642
+ 'aspect-ratio': (v) => {
643
+ const map = { 'auto': 'aspect-auto', '1/1': 'aspect-square', 'square': 'aspect-square', '16/9': 'aspect-video' };
644
+ if (map[v])
645
+ return map[v];
646
+ if (/^\d+$/.test(v))
647
+ return `aspect-[${v}/1]`;
648
+ return `aspect-[${v}]`;
649
+ },
650
+ 'transition-duration': (v) => {
651
+ const map = {
652
+ '75ms': 'duration-75', '100ms': 'duration-100', '150ms': 'duration-150', '200ms': 'duration-200',
653
+ '300ms': 'duration-300', '500ms': 'duration-500', '700ms': 'duration-700', '1000ms': 'duration-1000',
654
+ };
655
+ return map[v] ?? `duration-[${spacesToUnderscore(escapeValue(v))}]`;
656
+ },
657
+ 'transition-property': (v) => {
658
+ const map = {
659
+ 'none': 'transition-none', 'all': 'transition-all', 'colors': 'transition-colors',
660
+ 'opacity': 'transition-opacity', 'shadow': 'transition-shadow', 'transform': 'transition-transform',
661
+ 'height': 'transition-[height]', 'width': 'transition-[width]', 'spacing': 'transition-[spacing]', 'default': 'transition',
662
+ };
663
+ return map[v] ?? `transition-[${spacesToUnderscore(escapeValue(v))}]`;
664
+ },
665
+ 'transition-timing-function': (v) => {
666
+ const map = {
667
+ 'linear': 'ease-linear', 'ease': 'ease-in-out', 'ease-in': 'ease-in', 'ease-out': 'ease-out', 'ease-in-out': 'ease-in-out',
668
+ };
669
+ return map[v] ?? `ease-[${spacesToUnderscore(escapeValue(v))}]`;
670
+ },
671
+ 'transition': (v) => {
672
+ const map = {
673
+ 'none': 'transition-none', 'all': 'transition-all', 'colors': 'transition-colors',
674
+ 'opacity': 'transition-opacity', 'shadow': 'transition-shadow', 'transform': 'transition-transform',
675
+ };
676
+ return map[v] ?? `[transition:${v.replace(/\s+/g, '_')}]`;
677
+ },
678
+ 'animation': (v) => `[animation:${spacesToUnderscore(escapeValue(v.trim()))}]`,
679
+ 'animation-timing-function': (v) => `[animation-timing-function:${spacesToUnderscore(escapeValue(v))}]`,
680
+ 'animation-duration': (v) => `[animation-duration:${spacesToUnderscore(escapeValue(v))}]`,
681
+ 'animation-delay': (v) => `[animation-delay:${spacesToUnderscore(escapeValue(v))}]`,
682
+ 'animation-iteration-count': (v) => `[animation-iteration-count:${escapeValue(v)}]`,
683
+ 'animation-direction': (v) => `[animation-direction:${escapeValue(v)}]`,
684
+ 'animation-fill-mode': (v) => `[animation-fill-mode:${escapeValue(v)}]`,
685
+ 'animation-play-state': (v) => `[animation-play-state:${escapeValue(v)}]`,
686
+ 'animation-name': (v) => v === 'none' ? 'animate-none' : `[animation-name:${spacesToUnderscore(escapeValue(v))}]`,
687
+ 'animation-composition': (v) => `[animation-composition:${escapeValue(v)}]`,
688
+ 'animation-timeline': (v) => `[animation-timeline:${escapeValue(v)}]`,
689
+ 'mix-blend-mode': {
690
+ 'normal': 'mix-blend-normal', 'multiply': 'mix-blend-multiply', 'screen': 'mix-blend-screen',
691
+ 'overlay': 'mix-blend-overlay', 'darken': 'mix-blend-darken', 'lighten': 'mix-blend-lighten',
692
+ 'color-dodge': 'mix-blend-color-dodge', 'color-burn': 'mix-blend-color-burn',
693
+ 'difference': 'mix-blend-difference', 'exclusion': 'mix-blend-exclusion',
694
+ },
695
+ 'text-overflow': { 'ellipsis': 'text-ellipsis', 'clip': 'text-clip' },
696
+ 'word-break': { 'break-all': 'break-all', 'break-word': 'break-words', 'normal': 'break-normal' },
697
+ 'isolation': { 'isolate': 'isolate', 'auto': 'isolation-auto' },
698
+ 'white-space': { 'normal': 'whitespace-normal', 'nowrap': 'whitespace-nowrap', 'pre': 'whitespace-pre', 'pre-line': 'whitespace-pre-line', 'pre-wrap': 'whitespace-pre-wrap' },
699
+ 'will-change': { 'auto': '[will-change:auto]', 'scroll-position': '[will-change:scroll-position]', 'contents': '[will-change:contents]', 'transform': '[will-change:transform]' },
700
+ 'transform-style': { 'flat': '[transform-style:flat]', 'preserve-3d': '[transform-style:preserve-3d]' },
701
+ 'box-shadow': (v) => {
702
+ const map = {
703
+ '0 1px 2px 0 rgba(0, 0, 0, 0.05)': 'shadow-sm', '0 1px 3px 0 rgba(0, 0, 0, 0.1)': 'shadow',
704
+ '0 4px 6px -1px rgba(0, 0, 0, 0.1)': 'shadow-md', '0 10px 15px -3px rgba(0, 0, 0, 0.1)': 'shadow-lg',
705
+ '0 20px 25px -5px rgba(0, 0, 0, 0.1)': 'shadow-xl', '0 25px 50px -12px rgba(0, 0, 0, 0.25)': 'shadow-2xl',
706
+ 'inset 0 2px 4px 0 rgba(0,0,0,0.05)': 'shadow-inner', 'none': 'shadow-none',
707
+ };
708
+ return map[v] ?? `shadow-[${v.replace(/\s+/g, '_')}]`;
709
+ },
710
+ 'font-family': (v) => {
711
+ const builtIn = { 'sans-serif': 'font-sans', 'serif': 'font-serif', 'monospace': 'font-mono' };
712
+ const families = v.split(',').map(f => f.trim());
713
+ if (families.length === 1) {
714
+ const single = families[0].toLowerCase();
715
+ if (builtIn[single])
716
+ return builtIn[single];
717
+ const isMultiWord = /\s/.test(families[0]);
718
+ const isQuoted = (families[0].startsWith("'") && families[0].endsWith("'")) || (families[0].startsWith('"') && families[0].endsWith('"'));
719
+ const finalFamily = isMultiWord && !isQuoted ? `'${families[0]}'` : families[0];
720
+ return `font-[${finalFamily}]`;
721
+ }
722
+ const parsed = families.map(fam => {
723
+ const lower = fam.toLowerCase();
724
+ if (builtIn[lower])
725
+ return lower;
726
+ const isMultiWord = /\s/.test(fam);
727
+ const isQuoted = (fam.startsWith("'") && fam.endsWith("'")) || (fam.startsWith('"') && fam.endsWith('"'));
728
+ return isMultiWord && !isQuoted ? `'${fam}'` : fam;
729
+ });
730
+ return `font-[${parsed.join(',')}]`;
731
+ },
732
+ 'box-sizing': { 'border-box': 'box-border', 'content-box': 'box-content' },
733
+ 'flex-wrap': { 'nowrap': 'flex-nowrap', 'wrap': 'flex-wrap', 'wrap-reverse': 'flex-wrap-reverse' },
734
+ 'flex-basis': (v) => {
735
+ v = v.trim();
736
+ const map = {
737
+ 'auto': 'basis-auto', '0': 'basis-0', '1': 'basis-1', '0px': 'basis-0',
738
+ '0.5': 'basis-1/2', '0.25': 'basis-1/4', '0.33': 'basis-1/3', '0.66': 'basis-2/3', '0.75': 'basis-3/4',
739
+ '1.0': 'basis-full', '100%': 'basis-full', '50%': 'basis-1/2',
740
+ '33.333333%': 'basis-1/3', '66.666667%': 'basis-2/3', '25%': 'basis-1/4', '75%': 'basis-3/4',
741
+ };
742
+ if (map[v])
743
+ return map[v];
744
+ const numericValue = parseFloat(v.replace('%', '')) / 100;
745
+ if (map[numericValue.toString()])
746
+ return map[numericValue.toString()];
747
+ return `basis-[${spacesToUnderscore(escapeValue(v))}]`;
748
+ },
749
+ 'flex-grow': (v) => {
750
+ v = v.trim();
751
+ const map = {
752
+ '0': 'grow-0', '1': 'grow', 'auto': '[flex-grow:auto]',
753
+ 'initial': 'grow-0', 'inherit': '[flex-grow:inherit]', 'unset': '[flex-grow:unset]',
754
+ };
755
+ return map[v] ?? `grow-[${spacesToUnderscore(escapeValue(v))}]`;
756
+ },
757
+ 'column-count': (v) => {
758
+ const map = {
759
+ ...Object.fromEntries(Array.from({ length: 12 }, (_, i) => [`${i + 1}`, `columns-${i + 1}`])),
760
+ 'auto': 'columns-auto', 'initial': '[column-count:initial]', 'inherit': '[column-count:inherit]',
761
+ };
762
+ return map[v] ?? `columns-[${spacesToUnderscore(escapeValue(v))}]`;
763
+ },
764
+ 'flex-shrink': (v) => {
765
+ const map = { '0': 'shrink-0', '1': 'shrink', 'initial': 'shrink-0', 'inherit': '[flex-shrink:inherit]' };
766
+ return map[v] ?? `shrink-[${spacesToUnderscore(escapeValue(v))}]`;
767
+ },
768
+ 'align-items': {
769
+ 'stretch': 'items-stretch', 'flex-start': 'items-start', 'flex-end': 'items-end',
770
+ 'center': 'items-center', 'baseline': 'items-baseline',
771
+ 'initial': '[align-items:initial]', 'inherit': '[align-items:inherit]',
772
+ },
773
+ 'align-content': {
774
+ 'normal': 'content-normal', 'center': 'content-center', 'start': 'content-start', 'end': 'content-end',
775
+ 'flex-start': 'content-start', 'flex-end': 'content-end',
776
+ 'space-between': 'content-between', 'space-around': 'content-around', 'space-evenly': 'content-evenly',
777
+ 'baseline': 'content-baseline', 'stretch': 'content-stretch',
778
+ 'initial': '[align-content:initial]', 'inherit': '[align-content:inherit]',
779
+ },
780
+ 'cursor': {
781
+ 'auto': 'cursor-auto', 'default': 'cursor-default', 'pointer': 'cursor-pointer', 'wait': 'cursor-wait',
782
+ 'text': 'cursor-text', 'move': 'cursor-move', 'not-allowed': 'cursor-not-allowed', 'help': 'cursor-help',
783
+ 'progress': 'cursor-progress', 'cell': 'cursor-cell', 'crosshair': 'cursor-crosshair',
784
+ 'vertical-text': 'cursor-vertical-text', 'alias': 'cursor-alias', 'copy': 'cursor-copy',
785
+ 'no-drop': 'cursor-no-drop', 'grab': 'cursor-grab', 'grabbing': 'cursor-grabbing',
786
+ 'all-scroll': 'cursor-all-scroll', 'col-resize': 'cursor-col-resize', 'row-resize': 'cursor-row-resize',
787
+ 'n-resize': 'cursor-n-resize', 'e-resize': 'cursor-e-resize', 's-resize': 'cursor-s-resize', 'w-resize': 'cursor-w-resize',
788
+ 'ne-resize': 'cursor-ne-resize', 'nw-resize': 'cursor-nw-resize', 'se-resize': 'cursor-se-resize', 'sw-resize': 'cursor-sw-resize',
789
+ 'ew-resize': 'cursor-ew-resize', 'ns-resize': 'cursor-ns-resize', 'nesw-resize': 'cursor-nesw-resize', 'nwse-resize': 'cursor-nwse-resize',
790
+ 'zoom-in': 'cursor-zoom-in', 'zoom-out': 'cursor-zoom-out',
791
+ },
792
+ 'user-select': {
793
+ 'none': 'select-none', 'auto': 'select-auto', 'text': 'select-text', 'all': 'select-all',
794
+ },
795
+ '-webkit-user-select': {
796
+ 'none': 'select-none', 'auto': 'select-auto', 'text': 'select-text', 'all': 'select-all',
797
+ },
798
+ 'outline': (v) => {
799
+ const map = {
800
+ '0': 'outline-none', 'none': 'outline-none', '1px solid': 'outline', '2px solid': 'outline-2',
801
+ '4px solid': 'outline-4', '8px solid': 'outline-8', 'solid': 'outline', 'dashed': 'outline-dashed',
802
+ 'dotted': 'outline-dotted', 'double': 'outline-double', 'hidden': 'outline-none',
803
+ 'inherit': '[outline:inherit]', 'initial': '[outline:initial]', 'revert': '[outline:revert]',
804
+ 'unset': '[outline:unset]', 'auto': '[outline:auto]',
805
+ };
806
+ if (v.includes('offset'))
807
+ return `outline-offset-[${v}]`;
808
+ if (map[v])
809
+ return map[v];
810
+ const parts = v.split(' ');
811
+ if (parts.length >= 2) {
812
+ if (parts[0].endsWith('px') && parts[1] === 'solid') {
813
+ const px = parts[0].replace('px', '');
814
+ if (['1', '2', '4', '8'].includes(px))
815
+ return px === '1' ? 'outline' : `outline-${px}`;
816
+ }
817
+ if (['solid', 'dashed', 'dotted', 'double'].includes(parts[0]))
818
+ return `outline-${parts[0]}`;
819
+ }
820
+ return `outline-[${spacesToUnderscore(escapeValue(v))}]`;
821
+ },
822
+ 'outline-offset': (v) => {
823
+ const map = { '0': 'outline-offset-0', '1': 'outline-offset-1', '2': 'outline-offset-2', '4': 'outline-offset-4', '8': 'outline-offset-8' };
824
+ return map[v] ?? `outline-offset-[${spacesToUnderscore(escapeValue(v))}]`;
825
+ },
826
+ 'inset': (v) => {
827
+ const map = {
828
+ '0': 'inset-0', '0px': 'inset-0', 'auto': 'inset-auto', '50%': 'inset-1/2', '100%': 'inset-full',
829
+ ...Object.fromEntries(['1', '2', '3', '4', '5', '6', '8', '10', '12', '16', '20', '24', '32', '36', '40', '44', '48', '52', '56', '60', '64', '72', '80', '96'].map(n => [n, `inset-${n}`])),
830
+ '25%': 'inset-1/4', '33%': 'inset-1/3', '33.333333%': 'inset-1/3', '66.666667%': 'inset-2/3', '75%': 'inset-3/4',
831
+ 'initial': '[inset:initial]', 'inherit': '[inset:inherit]',
832
+ };
833
+ if (v.startsWith('-')) {
834
+ const pos = v.slice(1);
835
+ if (map[pos])
836
+ return `-${map[pos]}`;
837
+ }
838
+ if (map[v])
839
+ return map[v];
840
+ if (v.endsWith('px')) {
841
+ const n = v.replace('px', '');
842
+ if (map[n])
843
+ return map[n];
844
+ }
845
+ if (v.endsWith('rem')) {
846
+ const r = parseFloat(v) * 4;
847
+ if (map[r.toString()])
848
+ return map[r.toString()];
849
+ }
850
+ return `inset-[${spacesToUnderscore(escapeValue(v))}]`;
851
+ },
852
+ 'display': {
853
+ 'none': 'hidden', 'block': 'block', 'inline-block': 'inline-block', 'inline': 'inline',
854
+ 'flex': 'flex', 'inline-flex': 'inline-flex', 'grid': 'grid', 'inline-grid': 'inline-grid',
855
+ 'contents': 'contents', 'list-item': 'list-item', 'table': 'table', 'table-row': 'table-row', 'table-cell': 'table-cell',
856
+ },
857
+ 'visibility': (v) => {
858
+ const map = { 'visible': 'visible', 'hidden': 'invisible' };
859
+ return map[v] ?? `[visibility:${escapeValue(v)}]`;
860
+ },
861
+ 'list-style': (v) => `[list-style:${escapeValue(v)}]`,
862
+ 'list-style-type': (v) => {
863
+ const map = { 'none': 'list-none', 'disc': 'list-disc', 'decimal': 'list-decimal' };
864
+ return map[v] ?? `[list-style-type:${spacesToUnderscore(escapeValue(v))}]`;
865
+ },
866
+ 'list-style-position': (v) => {
867
+ const map = { 'inside': 'list-inside', 'outside': 'list-outside' };
868
+ return map[v] ?? `[list-style-position:${spacesToUnderscore(escapeValue(v))}]`;
869
+ },
870
+ 'list-style-image': (v) => {
871
+ const trimmed = v.trim();
872
+ if (trimmed === 'none')
873
+ return '[list-style-image:none]';
874
+ const urlMatch = trimmed.match(/^url\((['"]?)(.*?)\1\)$/);
875
+ if (urlMatch)
876
+ return `list-[url('${urlMatch[2].replace(/'/g, "\\'")}')]`;
877
+ return `[list-style-image:${escapeValue(trimmed)}]`;
878
+ },
879
+ 'font-size': (v) => {
880
+ const map = {
881
+ '0.75rem': 'text-xs', '0.875rem': 'text-sm', '1rem': 'text-base', '1.125rem': 'text-lg',
882
+ '1.25rem': 'text-xl', '1.5rem': 'text-2xl', '1.875rem': 'text-3xl', '2.25rem': 'text-4xl',
883
+ '3rem': 'text-5xl', '3.75rem': 'text-6xl', '4.5rem': 'text-7xl', '6rem': 'text-8xl', '8rem': 'text-9xl',
884
+ };
885
+ if (map[v])
886
+ return map[v];
887
+ const prefix = v.startsWith('var') ? 'length:' : '';
888
+ return `text-[${prefix}${spacesToUnderscore(escapeValue(v))}]`;
889
+ },
890
+ 'letter-spacing': (v) => {
891
+ if (v === 'normal' || v === '0')
892
+ return 'tracking-normal';
893
+ const predefined = [
894
+ { value: -0.05, class: 'tracking-tighter' }, { value: -0.025, class: 'tracking-tight' },
895
+ { value: 0, class: 'tracking-normal' }, { value: 0.025, class: 'tracking-wide' },
896
+ { value: 0.05, class: 'tracking-wider' }, { value: 0.1, class: 'tracking-widest' },
897
+ ];
898
+ let emValue = null;
899
+ if (v.endsWith('px'))
900
+ emValue = parseFloat(v) / 16;
901
+ else if (v.endsWith('em'))
902
+ emValue = parseFloat(v);
903
+ else
904
+ return `tracking-[${spacesToUnderscore(escapeValue(v))}]`;
905
+ let closest = null;
906
+ for (const p of predefined) {
907
+ const diff = p.value === 0 && emValue === 0 ? 0 :
908
+ (p.value === 0 || emValue === 0) ? Infinity :
909
+ Math.abs((emValue - p.value) / emValue) * 100;
910
+ if (!closest || diff < closest.diff)
911
+ closest = { class: p.class, diff };
912
+ }
913
+ return closest && closest.diff <= 3 ? closest.class : `tracking-[${spacesToUnderscore(escapeValue(v))}]`;
914
+ },
915
+ 'fill': (v) => {
916
+ const map = {
917
+ 'none': 'fill-none', 'currentColor': 'fill-current', 'current': 'fill-current',
918
+ 'inherit': 'fill-inherit', 'transparent': 'fill-transparent', 'black': 'fill-black', 'white': 'fill-white',
919
+ };
920
+ if (map[v])
921
+ return map[v];
922
+ return `fill-[${spacesToUnderscore(escapeValue(v))}]`;
923
+ },
924
+ 'break-inside': {
925
+ 'auto': 'break-inside-auto', 'avoid': 'break-inside-avoid',
926
+ 'avoid-page': 'break-inside-avoid-page', 'avoid-column': 'break-inside-avoid-column',
927
+ 'initial': '[break-inside:initial]', 'inherit': '[break-inside:inherit]',
928
+ },
929
+ 'background-color': (v) => {
930
+ const map = {
931
+ 'transparent': 'bg-transparent', 'currentColor': 'bg-current', 'black': 'bg-black', 'white': 'bg-white', 'none': 'bg-none',
932
+ };
933
+ const trimmed = v.trim();
934
+ if (map[trimmed])
935
+ return map[trimmed];
936
+ if (/^#([0-9a-fA-F]{3,8})$/.test(trimmed) || /^rgb/.test(trimmed) || /^hsl/.test(trimmed)) {
937
+ return `bg-[${escapeValue(trimmed).replace(/\s+/g, '_')}]`;
938
+ }
939
+ if (/^var\(--.*\)$/.test(trimmed))
940
+ return `bg-[${escapeValue(trimmed)}]`;
941
+ return `bg-[${escapeValue(trimmed).replace(/\s+/g, '_')}]`;
942
+ },
943
+ 'background-image': (v) => {
944
+ if (v === 'none')
945
+ return 'bg-none';
946
+ if (v.startsWith('url(')) {
947
+ const urlMatch = v.match(/^url\((['"]?)(.*?)\1\)$/);
948
+ if (urlMatch) {
949
+ const escapedUrl = spacesToUnderscore(urlMatch[2].replace(/\s+/g, '_').replace(/([\[\]'"`\\])/g, '\\$1'));
950
+ return `bg-[url('${escapedUrl}')]`;
951
+ }
952
+ return `bg-[${spacesToUnderscore(v.replace(/([\[\]'"`\\])/g, '\\$1'))}]`;
953
+ }
954
+ if (/^(linear-gradient|radial-gradient|repeating-linear-gradient|repeating-radial-gradient)/.test(v)) {
955
+ return `bg-[${spacesToUnderscore(v.replace(/([\[\]'"`\\])/g, '\\$1'))}]`;
956
+ }
957
+ return `[background-image:${spacesToUnderscore(v.replace(/([\[\]'"`\\])/g, '\\$1'))}]`;
958
+ },
959
+ 'mask-image': (v) => {
960
+ v = v.trim();
961
+ if (v === 'none')
962
+ return 'mask-none';
963
+ if (v.startsWith('url(')) {
964
+ const urlMatch = v.match(/^url\((['"]?)(.*?)\1\)$/);
965
+ if (urlMatch) {
966
+ const url = urlMatch[2].replace(/'/g, "\\'").replace(/\s+/g, '_');
967
+ return `mask-[url('${url}')]`;
968
+ }
969
+ return `mask-[${escapeValue(v)}]`;
970
+ }
971
+ const escaped = escapeValue(v).replace(/\s+/g, '_');
972
+ if (/^(linear-gradient|radial-gradient|repeating-linear-gradient|repeating-radial-gradient)/.test(v)) {
973
+ return `mask-[${escaped}]`;
974
+ }
975
+ return `[mask-image:${escaped}]`;
976
+ },
977
+ 'background-repeat': (v) => {
978
+ const map = {
979
+ 'repeat': 'bg-repeat', 'no-repeat': 'bg-no-repeat', 'repeat-x': 'bg-repeat-x',
980
+ 'repeat-y': 'bg-repeat-y', 'round': 'bg-repeat-round', 'space': 'bg-repeat-space',
981
+ };
982
+ return map[v] ?? `[background-repeat:${escapeValue(v)}]`;
983
+ },
984
+ 'background-position': (v) => {
985
+ const map = {
986
+ 'bottom': 'bg-bottom', 'center': 'bg-center', 'left': 'bg-left',
987
+ 'left bottom': 'bg-left-bottom', 'left top': 'bg-left-top', 'right': 'bg-right',
988
+ 'right bottom': 'bg-right-bottom', 'right top': 'bg-right-top', 'top': 'bg-top',
989
+ };
990
+ return map[v] ?? `[background-position:${escapeValue(v)}]`;
991
+ },
992
+ 'background-size': (v) => {
993
+ const map = { 'auto': 'bg-auto', 'cover': 'bg-cover', 'contain': 'bg-contain' };
994
+ return map[v] ?? `[background-size:${escapeValue(v)}]`;
995
+ },
996
+ 'background-attachment': (v) => {
997
+ const map = { 'fixed': 'bg-fixed', 'local': 'bg-local', 'scroll': 'bg-scroll' };
998
+ return map[v] ?? `[background-attachment:${escapeValue(v)}]`;
999
+ },
1000
+ 'background-origin': (v) => {
1001
+ const map = { 'border-box': 'bg-origin-border', 'padding-box': 'bg-origin-padding', 'content-box': 'bg-origin-content' };
1002
+ return map[v] ?? `[background-origin:${escapeValue(v)}]`;
1003
+ },
1004
+ 'background-clip': (v) => {
1005
+ const map = { 'border-box': 'bg-clip-border', 'padding-box': 'bg-clip-padding', 'content-box': 'bg-clip-content', 'text': 'bg-clip-text' };
1006
+ return map[v] ?? `[background-clip:${escapeValue(v)}]`;
1007
+ },
1008
+ 'clip-path': (v) => `[clip-path:${spacesToUnderscore(escapeValue(v))}]`,
1009
+ '-webkit-text-stroke-width': (v) => `[-webkit-text-stroke-width:${spacesToUnderscore(escapeValue(v.trim()))}]`,
1010
+ '-webkit-text-stroke-color': (v) => `[-webkit-text-stroke-color:${spacesToUnderscore(escapeValue(v.trim()))}]`,
1011
+ '-webkit-text-fill-color': (v) => v === 'transparent' ? 'text-transparent' : `[--webkit-text-fill-color:${escapeValue(v)}]`,
1012
+ '-webkit-background-clip': (v) => {
1013
+ const map = { 'border-box': 'bg-clip-border', 'padding-box': 'bg-clip-padding', 'content-box': 'bg-clip-content', 'text': 'bg-clip-text' };
1014
+ return map[v] ?? `[--webkit-background-clip:${escapeValue(v)}]`;
1015
+ },
1016
+ };
1017
+ // Handle !important
1018
+ let importantSetting = '';
1019
+ if (value.includes('!important')) {
1020
+ value = value.replace(/\s*!important\s*/g, '').trim();
1021
+ importantSetting = '!';
1022
+ }
1023
+ // Skip empty values — don't produce broken classes like bg-[] or text-[]
1024
+ if (!value || value.trim() === '')
1025
+ return null;
1026
+ // Handle vendor prefixes (except specific ones handled above)
1027
+ if (property !== '-webkit-text-fill-color' && property !== '-webkit-background-clip' &&
1028
+ property !== '-webkit-text-stroke-color' && property !== '-webkit-text-stroke-width') {
1029
+ const vendorPrefixes = ['-webkit-', '-moz-', '-ms-', '-o-'];
1030
+ for (const pfx of vendorPrefixes) {
1031
+ if (property.startsWith(pfx))
1032
+ return null;
1033
+ }
1034
+ }
1035
+ const mapping = mappings[property];
1036
+ if (mapping) {
1037
+ if (typeof mapping === 'function') {
1038
+ const tailwindClass = mapping(value);
1039
+ return tailwindClass ? `${importantSetting}${tailwindClass}` : null;
1040
+ }
1041
+ else if (typeof mapping === 'object') {
1042
+ const tailwindClass = mapping[value];
1043
+ if (tailwindClass)
1044
+ return `${importantSetting}${tailwindClass}`;
1045
+ return `${importantSetting}[${property}:${value}]`;
1046
+ }
1047
+ return `${importantSetting}${property}-[${value}]`;
1048
+ }
1049
+ // Unsupported property fallback
1050
+ const tailwindProperty = property.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
1051
+ return `${importantSetting}${tailwindProperty}-[${value}]`;
1052
+ }
1053
+ catch (error) {
1054
+ console.warn(`cssToTailwind error for ${property}: ${value}`, error);
1055
+ return null;
1056
+ }
1057
+ }
1058
+ // ── getBestTailwindClasses ──────────────────────────────────────────
1059
+ export function getBestTailwindClasses(property, pOverwritten) {
1060
+ const sides = ['top', 'right', 'bottom', 'left'];
1061
+ const sideValues = {};
1062
+ for (const side of sides) {
1063
+ sideValues[side] = pOverwritten[`${property}-${side}`];
1064
+ }
1065
+ const values = sides.map(s => sideValues[s]);
1066
+ const allSame = values.every(v => v === values[0]);
1067
+ const tailwindSpacingScale = {
1068
+ '0px': '0', '0.125rem': '0.5', '0.25rem': '1', '0.375rem': '1.5', '0.5rem': '2', '0.625rem': '2.5',
1069
+ '0.75rem': '3', '0.875rem': '3.5', '1rem': '4', '1.25rem': '5', '1.5rem': '6', '1.75rem': '7',
1070
+ '2rem': '8', '2.25rem': '9', '2.5rem': '10', '2.75rem': '11', '3rem': '12', '3.5rem': '14',
1071
+ '4rem': '16', '5rem': '20', '6rem': '24', '7rem': '28', '8rem': '32', '9rem': '36',
1072
+ '10rem': '40', '11rem': '44', '12rem': '48', '13rem': '52', '14rem': '56', '15rem': '60',
1073
+ '16rem': '64', '18rem': '72', '20rem': '80', '24rem': '96',
1074
+ };
1075
+ function mapValueToTailwind(val) {
1076
+ if (val === '0' || val === '0px')
1077
+ return '0';
1078
+ if (val === 'auto')
1079
+ return 'auto';
1080
+ let remValue = val;
1081
+ if (val.endsWith('px')) {
1082
+ remValue = `${parseFloat(val.replace('px', '')) / 16}rem`;
1083
+ }
1084
+ else if (!val.endsWith('rem')) {
1085
+ return `[${val}]`;
1086
+ }
1087
+ return tailwindSpacingScale[remValue] ?? `[${val}]`;
1088
+ }
1089
+ function generateTailwindClass(prefix, val) {
1090
+ const tw = mapValueToTailwind(val);
1091
+ return tw === 'auto' ? `${prefix}-auto` : `${prefix}-${tw}`;
1092
+ }
1093
+ const tailClasses = [];
1094
+ const isMargin = property === 'margin';
1095
+ const basePrefix = isMargin ? 'm' : 'p';
1096
+ if (allSame) {
1097
+ tailClasses.push(generateTailwindClass(basePrefix, values[0]));
1098
+ }
1099
+ else {
1100
+ const topBottomSame = sideValues.top === sideValues.bottom;
1101
+ const leftRightSame = sideValues.left === sideValues.right;
1102
+ if (topBottomSame && leftRightSame) {
1103
+ tailClasses.push(generateTailwindClass(`${basePrefix}y`, sideValues.top));
1104
+ tailClasses.push(generateTailwindClass(`${basePrefix}x`, sideValues.left));
1105
+ }
1106
+ else {
1107
+ if (topBottomSame) {
1108
+ tailClasses.push(generateTailwindClass(`${basePrefix}y`, sideValues.top));
1109
+ }
1110
+ else {
1111
+ tailClasses.push(generateTailwindClass(`${basePrefix}t`, sideValues.top));
1112
+ tailClasses.push(generateTailwindClass(`${basePrefix}b`, sideValues.bottom));
1113
+ }
1114
+ if (leftRightSame) {
1115
+ tailClasses.push(generateTailwindClass(`${basePrefix}x`, sideValues.left));
1116
+ }
1117
+ else {
1118
+ tailClasses.push(generateTailwindClass(`${basePrefix}r`, sideValues.right));
1119
+ tailClasses.push(generateTailwindClass(`${basePrefix}l`, sideValues.left));
1120
+ }
1121
+ }
1122
+ }
1123
+ return tailClasses;
1124
+ }
1125
+ // ── getTransformClasses ─────────────────────────────────────────────
1126
+ function hasConflictingTransforms(classes) {
1127
+ const groups = { scale: [], scaleX: [], scaleY: [] };
1128
+ for (const cls of classes) {
1129
+ if (cls.includes('scale-') && !cls.includes('scale-x-') && !cls.includes('scale-y-'))
1130
+ groups.scale.push(cls);
1131
+ else if (cls.includes('scale-x-'))
1132
+ groups.scaleX.push(cls);
1133
+ else if (cls.includes('scale-y-'))
1134
+ groups.scaleY.push(cls);
1135
+ }
1136
+ return Object.values(groups).some(g => g.length > 1);
1137
+ }
1138
+ function getMultipleTransformClasses(value) {
1139
+ const trimmed = value.trim();
1140
+ if (trimmed === 'none')
1141
+ return ['transform-none'];
1142
+ const transforms = trimmed.match(/(\w+\([^)]+\))/gi);
1143
+ if (!transforms)
1144
+ return [`[transform:${spacesToUnderscore(escapeValue(trimmed))}]`];
1145
+ const funcs = [];
1146
+ for (const transform of transforms) {
1147
+ const match = transform.match(/(\w+)\(([^)]+)\)/i);
1148
+ if (!match) {
1149
+ funcs.push(transform.trim());
1150
+ continue;
1151
+ }
1152
+ const [, func, val] = match;
1153
+ funcs.push(`${func}(${spacesToUnderscore(escapeValue(val.trim()))})`);
1154
+ }
1155
+ return [`[transform:${funcs.join('_')}]`];
1156
+ }
1157
+ export function getTransformClasses(value) {
1158
+ const trimmed = value.trim();
1159
+ if (trimmed === 'none')
1160
+ return ['transform-none'];
1161
+ const transforms = trimmed.match(/(\w+\([^)]+\))/gi);
1162
+ if (!transforms)
1163
+ return [`[transform:${escapeValue(trimmed)}]`];
1164
+ const classes = [];
1165
+ for (const transform of transforms) {
1166
+ const match = transform.match(/(\w+)\(([^)]+)\)/i);
1167
+ if (!match) {
1168
+ classes.push(`[transform:${spacesToUnderscore(escapeValue(transform.trim()))}]`);
1169
+ continue;
1170
+ }
1171
+ const [, func, val] = match;
1172
+ const numericValue = parseFloat(val);
1173
+ const funcLower = func.toLowerCase();
1174
+ switch (funcLower) {
1175
+ case 'translate': {
1176
+ const vals = val.split(',').map(v => v.trim());
1177
+ if (vals.length === 2) {
1178
+ const [xVal, yVal] = vals;
1179
+ const xNum = parseFloat(xVal);
1180
+ const yNum = parseFloat(yVal);
1181
+ if (xVal === '-50%' && yVal === '-50%') {
1182
+ classes.push('-translate-x-1/2', '-translate-y-1/2');
1183
+ break;
1184
+ }
1185
+ // Handle X
1186
+ if (xNum === 50 && xVal.includes('%'))
1187
+ classes.push('translate-x-1/2');
1188
+ else if (xNum === -50 && xVal.includes('%'))
1189
+ classes.push('-translate-x-1/2');
1190
+ else if (xNum === 100 && xVal.includes('%'))
1191
+ classes.push('translate-x-full');
1192
+ else if (xNum === -100 && xVal.includes('%'))
1193
+ classes.push('-translate-x-full');
1194
+ else if (xNum < 0)
1195
+ classes.push(`-translate-x-[${Math.abs(xNum)}${xVal.replace(xNum.toString(), '')}]`);
1196
+ else
1197
+ classes.push(`translate-x-[${xVal}]`);
1198
+ // Handle Y
1199
+ if (yNum === 50 && yVal.includes('%'))
1200
+ classes.push('translate-y-1/2');
1201
+ else if (yNum === -50 && yVal.includes('%'))
1202
+ classes.push('-translate-y-1/2');
1203
+ else if (yNum === 100 && yVal.includes('%'))
1204
+ classes.push('translate-y-full');
1205
+ else if (yNum === -100 && yVal.includes('%'))
1206
+ classes.push('-translate-y-full');
1207
+ else if (yNum < 0)
1208
+ classes.push(`-translate-y-[${Math.abs(yNum)}${yVal.replace(yNum.toString(), '')}]`);
1209
+ else
1210
+ classes.push(`translate-y-[${yVal}]`);
1211
+ }
1212
+ break;
1213
+ }
1214
+ case 'translatex': {
1215
+ if (numericValue === 0) {
1216
+ classes.push('translate-x-0');
1217
+ break;
1218
+ }
1219
+ if (val.trim() === '-50%') {
1220
+ classes.push('-translate-x-1/2');
1221
+ break;
1222
+ }
1223
+ if (val.trim() === '50%') {
1224
+ classes.push('translate-x-1/2');
1225
+ break;
1226
+ }
1227
+ if (val.trim() === '100%') {
1228
+ classes.push('translate-x-full');
1229
+ break;
1230
+ }
1231
+ if (val.trim() === '-100%') {
1232
+ classes.push('-translate-x-full');
1233
+ break;
1234
+ }
1235
+ if (numericValue < 0) {
1236
+ classes.push(`-translate-x-[${Math.abs(numericValue)}${val.replace(numericValue.toString(), '').trim()}]`);
1237
+ break;
1238
+ }
1239
+ classes.push(`translate-x-[${val.trim()}]`);
1240
+ break;
1241
+ }
1242
+ case 'translatey': {
1243
+ if (numericValue === 0) {
1244
+ classes.push('translate-y-0');
1245
+ break;
1246
+ }
1247
+ if (val.trim() === '-50%') {
1248
+ classes.push('-translate-y-1/2');
1249
+ break;
1250
+ }
1251
+ if (val.trim() === '50%') {
1252
+ classes.push('translate-y-1/2');
1253
+ break;
1254
+ }
1255
+ if (val.trim() === '100%') {
1256
+ classes.push('translate-y-full');
1257
+ break;
1258
+ }
1259
+ if (val.trim() === '-100%') {
1260
+ classes.push('-translate-y-full');
1261
+ break;
1262
+ }
1263
+ if (numericValue < 0) {
1264
+ classes.push(`-translate-y-[${Math.abs(numericValue)}${val.replace(numericValue.toString(), '').trim()}]`);
1265
+ break;
1266
+ }
1267
+ classes.push(`translate-y-[${val.trim()}]`);
1268
+ break;
1269
+ }
1270
+ case 'rotate': {
1271
+ const deg = parseFloat(val);
1272
+ const degMap = { 0: 'rotate-0', 1: 'rotate-1', 2: 'rotate-2', 3: 'rotate-3', 6: 'rotate-6', 12: 'rotate-12', 45: 'rotate-45', 90: 'rotate-90', 180: 'rotate-180' };
1273
+ if (degMap[deg]) {
1274
+ classes.push(degMap[deg]);
1275
+ break;
1276
+ }
1277
+ if (deg < 0 && degMap[Math.abs(deg)]) {
1278
+ classes.push(`-${degMap[Math.abs(deg)]}`);
1279
+ break;
1280
+ }
1281
+ classes.push(`rotate-[${val.trim()}]`);
1282
+ break;
1283
+ }
1284
+ case 'scale': {
1285
+ const scale = parseFloat(val);
1286
+ const scaleMap = { 0: 'scale-0', 0.5: 'scale-50', 0.75: 'scale-75', 1: 'scale-100', 1.25: 'scale-125', 1.5: 'scale-150' };
1287
+ if (scaleMap[scale]) {
1288
+ classes.push(scaleMap[scale]);
1289
+ break;
1290
+ }
1291
+ classes.push(`scale-[${val.trim()}]`);
1292
+ break;
1293
+ }
1294
+ case 'scalex': {
1295
+ const scale = parseFloat(val);
1296
+ const scaleMap = { 0: 'scale-x-0', 0.5: 'scale-x-50', 0.75: 'scale-x-75', 1: 'scale-x-100', 1.25: 'scale-x-125', 1.5: 'scale-x-150' };
1297
+ if (scaleMap[scale]) {
1298
+ classes.push(scaleMap[scale]);
1299
+ break;
1300
+ }
1301
+ classes.push(`scale-x-[${val.trim()}]`);
1302
+ break;
1303
+ }
1304
+ case 'scaley': {
1305
+ const scale = parseFloat(val);
1306
+ const scaleMap = { 0: 'scale-y-0', 0.5: 'scale-y-50', 0.75: 'scale-y-75', 1: 'scale-y-100', 1.25: 'scale-y-125', 1.5: 'scale-y-150' };
1307
+ if (scaleMap[scale]) {
1308
+ classes.push(scaleMap[scale]);
1309
+ break;
1310
+ }
1311
+ classes.push(`scale-y-[${val.trim()}]`);
1312
+ break;
1313
+ }
1314
+ case 'skewx': {
1315
+ const deg = parseFloat(val);
1316
+ const skewMap = { 0: 'skew-x-0', 1: 'skew-x-1', 2: 'skew-x-2', 3: 'skew-x-3', 6: 'skew-x-6', 12: 'skew-x-12' };
1317
+ if (skewMap[deg]) {
1318
+ classes.push(skewMap[deg]);
1319
+ break;
1320
+ }
1321
+ classes.push(`skew-x-[${val.trim()}]`);
1322
+ break;
1323
+ }
1324
+ case 'skewy': {
1325
+ const deg = parseFloat(val);
1326
+ const skewMap = { 0: 'skew-y-0', 1: 'skew-y-1', 2: 'skew-y-2', 3: 'skew-y-3', 6: 'skew-y-6', 12: 'skew-y-12' };
1327
+ if (skewMap[deg]) {
1328
+ classes.push(skewMap[deg]);
1329
+ break;
1330
+ }
1331
+ classes.push(`skew-y-[${val.trim()}]`);
1332
+ break;
1333
+ }
1334
+ default:
1335
+ classes.push(`transform-[${func}(${val.trim()})]`);
1336
+ break;
1337
+ }
1338
+ }
1339
+ if (classes.length > 1 && hasConflictingTransforms(classes)) {
1340
+ return getMultipleTransformClasses(value);
1341
+ }
1342
+ return classes;
1343
+ }
1344
+ // ── getFilterClasses ────────────────────────────────────────────────
1345
+ export function getFilterClasses(value, isBackdrop = false) {
1346
+ const prefix = isBackdrop ? 'backdrop-' : 'filter-';
1347
+ const trimmed = value.trim();
1348
+ if (trimmed === 'none')
1349
+ return [`${prefix}none`];
1350
+ const filters = trimmed.match(/(\w+\([^)]+\))/gi);
1351
+ if (!filters)
1352
+ return [`${prefix}[${escapeValue(trimmed)}]`];
1353
+ const classes = [];
1354
+ for (const filter of filters) {
1355
+ const match = filter.match(/(\w+)-?(\w+)?\(([^)]+)\)/i);
1356
+ if (!match) {
1357
+ classes.push(`${prefix}[${escapeValue(filter.trim())}]`);
1358
+ continue;
1359
+ }
1360
+ const [, func, subFunc, val] = match;
1361
+ const fullFunc = subFunc ? `${func}-${subFunc}` : func;
1362
+ const numericValue = parseFloat(val);
1363
+ const funcLower = fullFunc.toLowerCase();
1364
+ switch (funcLower) {
1365
+ case 'grayscale':
1366
+ if (numericValue === 100 || val === '1')
1367
+ classes.push(`${prefix}grayscale`);
1368
+ else if (numericValue === 0)
1369
+ classes.push(`${prefix}grayscale-0`);
1370
+ else
1371
+ classes.push(`${prefix}grayscale-[${val}]`);
1372
+ break;
1373
+ case 'invert':
1374
+ if (numericValue === 100 || val === '1')
1375
+ classes.push(`${prefix}invert`);
1376
+ else if (numericValue === 0)
1377
+ classes.push(`${prefix}invert-0`);
1378
+ else
1379
+ classes.push(`${prefix}invert-[${val}]`);
1380
+ break;
1381
+ case 'sepia':
1382
+ if (numericValue === 100 || val === '1')
1383
+ classes.push(`${prefix}sepia`);
1384
+ else if (numericValue === 0)
1385
+ classes.push(`${prefix}sepia-0`);
1386
+ else
1387
+ classes.push(`${prefix}sepia-[${val}]`);
1388
+ break;
1389
+ case 'blur':
1390
+ if (val === '0px' || val === '0')
1391
+ classes.push(`${prefix}blur-none`);
1392
+ else if (val === '8px')
1393
+ classes.push(`${prefix}blur`);
1394
+ else
1395
+ classes.push(`${prefix}blur-[${val}]`);
1396
+ break;
1397
+ case 'brightness': {
1398
+ const bMap = { 0: '0', 50: '50', 75: '75', 90: '90', 95: '95', 100: '100', 105: '105', 110: '110', 125: '125', 150: '150', 200: '200' };
1399
+ if (bMap[numericValue])
1400
+ classes.push(`${prefix}brightness-${bMap[numericValue]}`);
1401
+ else
1402
+ classes.push(`${prefix}brightness-[${val}]`);
1403
+ break;
1404
+ }
1405
+ case 'contrast': {
1406
+ const cMap = { 0: '0', 50: '50', 75: '75', 100: '100', 125: '125', 150: '150', 200: '200' };
1407
+ if (cMap[numericValue])
1408
+ classes.push(`${prefix}contrast-${cMap[numericValue]}`);
1409
+ else
1410
+ classes.push(`${prefix}contrast-[${val}]`);
1411
+ break;
1412
+ }
1413
+ case 'saturate': {
1414
+ const sMap = { 0: '0', 50: '50', 100: '100', 150: '150', 200: '200' };
1415
+ if (sMap[numericValue])
1416
+ classes.push(`${prefix}saturate-${sMap[numericValue]}`);
1417
+ else
1418
+ classes.push(`${prefix}saturate-[${val}]`);
1419
+ break;
1420
+ }
1421
+ case 'hue-rotate': {
1422
+ const hMap = { '0deg': '0', '15deg': '15', '30deg': '30', '60deg': '60', '90deg': '90', '180deg': '180' };
1423
+ if (hMap[val])
1424
+ classes.push(`${prefix}hue-rotate-${hMap[val]}`);
1425
+ else
1426
+ classes.push(`${prefix}hue-rotate-[${val}]`);
1427
+ break;
1428
+ }
1429
+ default:
1430
+ classes.push(`${prefix}[${func}(${val})]`);
1431
+ break;
1432
+ }
1433
+ }
1434
+ return classes;
1435
+ }
1436
+ // ── getFontClasses ──────────────────────────────────────────────────
1437
+ export function getFontClasses(value) {
1438
+ const trimmed = value.trim();
1439
+ if (trimmed === 'inherit' || trimmed === 'initial' || trimmed === 'unset') {
1440
+ return [`font-${trimmed}`];
1441
+ }
1442
+ // Tokenize font value respecting quotes
1443
+ function tokenize(val) {
1444
+ const tokens = [];
1445
+ let current = '';
1446
+ let inQuotes = false;
1447
+ let quoteChar = '';
1448
+ for (let i = 0; i < val.length; i++) {
1449
+ const c = val[i];
1450
+ if (c === '"' || c === "'") {
1451
+ if (!inQuotes) {
1452
+ inQuotes = true;
1453
+ quoteChar = c;
1454
+ current += c;
1455
+ }
1456
+ else if (c === quoteChar) {
1457
+ inQuotes = false;
1458
+ current += c;
1459
+ tokens.push(current.trim());
1460
+ current = '';
1461
+ }
1462
+ else {
1463
+ current += c;
1464
+ }
1465
+ }
1466
+ else if (c === ' ' && !inQuotes) {
1467
+ if (current.trim()) {
1468
+ tokens.push(current.trim());
1469
+ current = '';
1470
+ }
1471
+ }
1472
+ else {
1473
+ current += c;
1474
+ }
1475
+ }
1476
+ if (current.trim())
1477
+ tokens.push(current.trim());
1478
+ return tokens;
1479
+ }
1480
+ const tokens = tokenize(trimmed);
1481
+ let fontStyle = null;
1482
+ let fontVariant = null;
1483
+ let fontWeight = null;
1484
+ let fontStretch = null;
1485
+ let fontSize = null;
1486
+ let lineHeight = null;
1487
+ let fontFamily = null;
1488
+ const fontStyles = ['normal', 'italic', 'oblique'];
1489
+ const fontVariants = ['normal', 'small-caps'];
1490
+ const fontWeights = ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900'];
1491
+ const fontStretches = ['normal', 'ultra-condensed', 'extra-condensed', 'condensed', 'semi-condensed', 'semi-expanded', 'expanded', 'extra-expanded', 'ultra-expanded'];
1492
+ let reachedFontSize = false;
1493
+ for (let i = 0; i < tokens.length; i++) {
1494
+ const token = tokens[i];
1495
+ if (!reachedFontSize) {
1496
+ const lower = token.toLowerCase();
1497
+ if (fontStyles.includes(lower) && !fontStyle)
1498
+ fontStyle = lower;
1499
+ else if (fontVariants.includes(lower) && !fontVariant)
1500
+ fontVariant = lower;
1501
+ else if (fontWeights.includes(lower) && !fontWeight)
1502
+ fontWeight = lower;
1503
+ else if (fontStretches.includes(lower) && !fontStretch)
1504
+ fontStretch = lower;
1505
+ else {
1506
+ const parts = token.split('/');
1507
+ fontSize = parts[0];
1508
+ if (parts.length > 1)
1509
+ lineHeight = parts[1];
1510
+ else if (tokens[i + 1] === '/') {
1511
+ lineHeight = tokens[i + 2];
1512
+ i += 2;
1513
+ }
1514
+ reachedFontSize = true;
1515
+ }
1516
+ }
1517
+ else {
1518
+ fontFamily = tokens.slice(i).join(' ').trim();
1519
+ break;
1520
+ }
1521
+ }
1522
+ const classes = [];
1523
+ // font-style
1524
+ if (fontStyle === 'italic' || fontStyle === 'oblique')
1525
+ classes.push('italic');
1526
+ else if (fontStyle === 'normal')
1527
+ classes.push('not-italic');
1528
+ // font-variant
1529
+ if (fontVariant === 'small-caps')
1530
+ classes.push('font-variant-[small-caps]');
1531
+ // font-weight
1532
+ if (fontWeight) {
1533
+ const weightMap = {
1534
+ '100': 'font-thin', '200': 'font-extralight', '300': 'font-light', '400': 'font-normal',
1535
+ '500': 'font-medium', '600': 'font-semibold', '700': 'font-bold', '800': 'font-extrabold', '900': 'font-black',
1536
+ 'normal': 'font-normal', 'bold': 'font-bold', 'bolder': 'font-bold', 'lighter': 'font-light',
1537
+ };
1538
+ classes.push(weightMap[fontWeight.toLowerCase()] ?? `font-[${escapeValue(fontWeight)}]`);
1539
+ }
1540
+ // font-size
1541
+ if (fontSize) {
1542
+ const sizeMap = {
1543
+ 'xx-small': 'text-[xx-small]', 'x-small': 'text-xs', 'small': 'text-sm', 'medium': 'text-base',
1544
+ 'large': 'text-lg', 'x-large': 'text-xl', 'xx-large': 'text-2xl', 'xxx-large': 'text-3xl',
1545
+ 'smaller': 'text-sm', 'larger': 'text-lg',
1546
+ };
1547
+ const lower = fontSize.toLowerCase();
1548
+ classes.push(sizeMap[lower] ?? `text-[${spacesToUnderscore(escapeValue(fontSize))}]`);
1549
+ }
1550
+ // line-height
1551
+ if (lineHeight) {
1552
+ const lhMap = {
1553
+ 'normal': 'leading-normal', 'none': 'leading-none', 'tight': 'leading-tight',
1554
+ 'snug': 'leading-snug', 'relaxed': 'leading-relaxed', 'loose': 'leading-loose',
1555
+ '3': 'leading-3', '4': 'leading-4', '5': 'leading-5', '6': 'leading-6',
1556
+ '7': 'leading-7', '8': 'leading-8', '9': 'leading-9', '10': 'leading-10',
1557
+ };
1558
+ classes.push(lhMap[lineHeight.toLowerCase()] ?? `leading-[${spacesToUnderscore(escapeValue(lineHeight))}]`);
1559
+ }
1560
+ // font-family
1561
+ if (fontFamily) {
1562
+ const familyMap = { 'sans-serif': 'font-sans', 'serif': 'font-serif', 'monospace': 'font-mono', 'system-ui': 'font-sans' };
1563
+ const names = fontFamily.split(',');
1564
+ let added = false;
1565
+ for (const name of names) {
1566
+ let familyName = name.trim();
1567
+ if ((familyName.startsWith('"') && familyName.endsWith('"')) || (familyName.startsWith("'") && familyName.endsWith("'"))) {
1568
+ familyName = familyName.slice(1, -1);
1569
+ }
1570
+ if (familyMap[familyName.toLowerCase()]) {
1571
+ classes.push(familyMap[familyName.toLowerCase()]);
1572
+ added = true;
1573
+ break;
1574
+ }
1575
+ }
1576
+ if (!added) {
1577
+ const first = names[0].trim();
1578
+ classes.push(`font-[${spacesToUnderscore(escapeValue(first))}]`);
1579
+ }
1580
+ }
1581
+ return classes;
1582
+ }
1583
+ //# sourceMappingURL=css-to-tailwind.js.map