@tenphi/eslint-plugin-tasty 1.0.2 → 1.0.4
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/README.md +1 -1
- package/dist/constants.js +521 -9
- package/dist/constants.js.map +1 -1
- package/dist/context.js +40 -2
- package/dist/context.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ tracked import, so a local barrel needs listing here.
|
|
|
87
87
|
|
|
88
88
|
| Rule | Severity | Description |
|
|
89
89
|
|------|----------|-------------|
|
|
90
|
-
| `tasty/known-property` | warn | Unknown style property names |
|
|
90
|
+
| `tasty/known-property` | warn | Unknown style property names (checked against the full MDN/W3C CSS property set) |
|
|
91
91
|
| `tasty/valid-value` | error | Malformed style values (unbalanced parens, !important) |
|
|
92
92
|
| `tasty/valid-color-token` | error | Invalid color token syntax or unknown tokens |
|
|
93
93
|
| `tasty/valid-custom-unit` | error | Unknown custom units |
|
package/dist/constants.js
CHANGED
|
@@ -129,12 +129,38 @@ const RENAMED_SPECIAL_STYLE_KEYS = {
|
|
|
129
129
|
"@counterStyle": "@counter-style"
|
|
130
130
|
};
|
|
131
131
|
/**
|
|
132
|
-
* CSS property names
|
|
133
|
-
*
|
|
132
|
+
* CSS property names, camelCase, derived from `known-css-properties` — the
|
|
133
|
+
* MDN/W3C-sourced dataset stylelint uses for `property-no-unknown`.
|
|
134
|
+
*
|
|
135
|
+
* Generated. Run `pnpm generate:css-properties` after bumping the dataset rather
|
|
136
|
+
* than editing this list; `constants.css-properties.test.ts` fails on drift.
|
|
137
|
+
*
|
|
138
|
+
* Tasty renders any camelCase style key straight through to its kebab-case CSS
|
|
139
|
+
* declaration (`maskSize` -> `mask-size`), so anything absent here is a false
|
|
140
|
+
* positive from `known-property` on valid CSS — which is why the list is derived
|
|
141
|
+
* from data instead of maintained by hand.
|
|
142
|
+
*
|
|
143
|
+
* The dataset also carries at-rule descriptors (`src`, `syntax`, `symbols`, `size`),
|
|
144
|
+
* which are kept, as stylelint keeps them. They are only reachable as top-level
|
|
145
|
+
* style keys, where the cost is a declaration browsers drop rather than a report —
|
|
146
|
+
* and separating them would mean hand-maintaining the exclusion list this change
|
|
147
|
+
* exists to delete. Inside an at-rule block nothing validates them: `known-property`
|
|
148
|
+
* exempts every `@`-prefixed key and does not descend.
|
|
134
149
|
*/
|
|
135
|
-
const
|
|
150
|
+
const DATASET_CSS_PROPERTIES = [
|
|
151
|
+
"accelerator",
|
|
152
|
+
"accentColor",
|
|
153
|
+
"additiveSymbols",
|
|
154
|
+
"alignContent",
|
|
155
|
+
"alignItems",
|
|
156
|
+
"alignSelf",
|
|
157
|
+
"alignmentBaseline",
|
|
136
158
|
"all",
|
|
159
|
+
"alt",
|
|
160
|
+
"anchorName",
|
|
161
|
+
"anchorScope",
|
|
137
162
|
"animation",
|
|
163
|
+
"animationComposition",
|
|
138
164
|
"animationDelay",
|
|
139
165
|
"animationDirection",
|
|
140
166
|
"animationDuration",
|
|
@@ -142,9 +168,26 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
142
168
|
"animationIterationCount",
|
|
143
169
|
"animationName",
|
|
144
170
|
"animationPlayState",
|
|
171
|
+
"animationRange",
|
|
172
|
+
"animationRangeEnd",
|
|
173
|
+
"animationRangeStart",
|
|
174
|
+
"animationTimeline",
|
|
145
175
|
"animationTimingFunction",
|
|
176
|
+
"animationTrigger",
|
|
177
|
+
"animationTriggerBehavior",
|
|
178
|
+
"animationTriggerExitRange",
|
|
179
|
+
"animationTriggerExitRangeEnd",
|
|
180
|
+
"animationTriggerExitRangeStart",
|
|
181
|
+
"animationTriggerRange",
|
|
182
|
+
"animationTriggerRangeEnd",
|
|
183
|
+
"animationTriggerRangeStart",
|
|
184
|
+
"animationTriggerTimeline",
|
|
185
|
+
"appRegion",
|
|
146
186
|
"appearance",
|
|
187
|
+
"ascentOverride",
|
|
147
188
|
"aspectRatio",
|
|
189
|
+
"audioLevel",
|
|
190
|
+
"azimuth",
|
|
148
191
|
"backdropFilter",
|
|
149
192
|
"backfaceVisibility",
|
|
150
193
|
"background",
|
|
@@ -155,9 +198,26 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
155
198
|
"backgroundImage",
|
|
156
199
|
"backgroundOrigin",
|
|
157
200
|
"backgroundPosition",
|
|
201
|
+
"backgroundPositionX",
|
|
202
|
+
"backgroundPositionY",
|
|
158
203
|
"backgroundRepeat",
|
|
204
|
+
"backgroundRepeatX",
|
|
205
|
+
"backgroundRepeatY",
|
|
159
206
|
"backgroundSize",
|
|
207
|
+
"basePalette",
|
|
208
|
+
"baselineShift",
|
|
209
|
+
"baselineSource",
|
|
210
|
+
"behavior",
|
|
211
|
+
"blockEllipsis",
|
|
160
212
|
"blockSize",
|
|
213
|
+
"blockStep",
|
|
214
|
+
"blockStepAlign",
|
|
215
|
+
"blockStepInsert",
|
|
216
|
+
"blockStepRound",
|
|
217
|
+
"blockStepSize",
|
|
218
|
+
"bookmarkLabel",
|
|
219
|
+
"bookmarkLevel",
|
|
220
|
+
"bookmarkState",
|
|
161
221
|
"border",
|
|
162
222
|
"borderBlock",
|
|
163
223
|
"borderBlockColor",
|
|
@@ -177,13 +237,27 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
177
237
|
"borderBottomRightRadius",
|
|
178
238
|
"borderBottomStyle",
|
|
179
239
|
"borderBottomWidth",
|
|
240
|
+
"borderBoundary",
|
|
180
241
|
"borderCollapse",
|
|
181
242
|
"borderColor",
|
|
243
|
+
"borderEndEndRadius",
|
|
244
|
+
"borderEndStartRadius",
|
|
182
245
|
"borderImage",
|
|
246
|
+
"borderImageOutset",
|
|
247
|
+
"borderImageRepeat",
|
|
248
|
+
"borderImageSlice",
|
|
249
|
+
"borderImageSource",
|
|
250
|
+
"borderImageWidth",
|
|
183
251
|
"borderInline",
|
|
184
252
|
"borderInlineColor",
|
|
185
253
|
"borderInlineEnd",
|
|
254
|
+
"borderInlineEndColor",
|
|
255
|
+
"borderInlineEndStyle",
|
|
256
|
+
"borderInlineEndWidth",
|
|
186
257
|
"borderInlineStart",
|
|
258
|
+
"borderInlineStartColor",
|
|
259
|
+
"borderInlineStartStyle",
|
|
260
|
+
"borderInlineStartWidth",
|
|
187
261
|
"borderInlineStyle",
|
|
188
262
|
"borderInlineWidth",
|
|
189
263
|
"borderLeft",
|
|
@@ -196,6 +270,8 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
196
270
|
"borderRightStyle",
|
|
197
271
|
"borderRightWidth",
|
|
198
272
|
"borderSpacing",
|
|
273
|
+
"borderStartEndRadius",
|
|
274
|
+
"borderStartStartRadius",
|
|
199
275
|
"borderStyle",
|
|
200
276
|
"borderTop",
|
|
201
277
|
"borderTopColor",
|
|
@@ -208,42 +284,96 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
208
284
|
"boxDecorationBreak",
|
|
209
285
|
"boxShadow",
|
|
210
286
|
"boxSizing",
|
|
287
|
+
"boxSnap",
|
|
211
288
|
"breakAfter",
|
|
212
289
|
"breakBefore",
|
|
213
290
|
"breakInside",
|
|
291
|
+
"bufferedRendering",
|
|
214
292
|
"captionSide",
|
|
293
|
+
"caret",
|
|
294
|
+
"caretAnimation",
|
|
215
295
|
"caretColor",
|
|
296
|
+
"caretShape",
|
|
297
|
+
"chains",
|
|
216
298
|
"clear",
|
|
217
299
|
"clip",
|
|
218
300
|
"clipPath",
|
|
219
301
|
"clipRule",
|
|
220
302
|
"color",
|
|
303
|
+
"colorAdjust",
|
|
304
|
+
"colorInterpolation",
|
|
305
|
+
"colorInterpolationFilters",
|
|
306
|
+
"colorProfile",
|
|
307
|
+
"colorRendering",
|
|
221
308
|
"colorScheme",
|
|
222
309
|
"columnCount",
|
|
223
310
|
"columnFill",
|
|
224
311
|
"columnGap",
|
|
312
|
+
"columnHeight",
|
|
313
|
+
"columnProgression",
|
|
225
314
|
"columnRule",
|
|
315
|
+
"columnRuleBreak",
|
|
226
316
|
"columnRuleColor",
|
|
317
|
+
"columnRuleOutset",
|
|
227
318
|
"columnRuleStyle",
|
|
228
319
|
"columnRuleWidth",
|
|
229
320
|
"columnSpan",
|
|
230
321
|
"columnWidth",
|
|
322
|
+
"columnWrap",
|
|
231
323
|
"columns",
|
|
232
324
|
"contain",
|
|
325
|
+
"containIntrinsicBlockSize",
|
|
326
|
+
"containIntrinsicHeight",
|
|
327
|
+
"containIntrinsicInlineSize",
|
|
328
|
+
"containIntrinsicSize",
|
|
329
|
+
"containIntrinsicWidth",
|
|
330
|
+
"container",
|
|
233
331
|
"containerName",
|
|
234
332
|
"containerType",
|
|
235
333
|
"content",
|
|
236
334
|
"contentVisibility",
|
|
335
|
+
"continue",
|
|
237
336
|
"counterIncrement",
|
|
238
337
|
"counterReset",
|
|
239
338
|
"counterSet",
|
|
339
|
+
"cue",
|
|
340
|
+
"cueAfter",
|
|
341
|
+
"cueBefore",
|
|
240
342
|
"cursor",
|
|
343
|
+
"cx",
|
|
344
|
+
"cy",
|
|
345
|
+
"d",
|
|
346
|
+
"descentOverride",
|
|
241
347
|
"direction",
|
|
242
348
|
"display",
|
|
349
|
+
"displayAlign",
|
|
243
350
|
"dominantBaseline",
|
|
351
|
+
"dynamicRangeLimit",
|
|
352
|
+
"elevation",
|
|
244
353
|
"emptyCells",
|
|
354
|
+
"enableBackground",
|
|
355
|
+
"epubCaptionSide",
|
|
356
|
+
"epubHyphens",
|
|
357
|
+
"epubTextCombine",
|
|
358
|
+
"epubTextEmphasis",
|
|
359
|
+
"epubTextEmphasisColor",
|
|
360
|
+
"epubTextEmphasisStyle",
|
|
361
|
+
"epubTextOrientation",
|
|
362
|
+
"epubTextTransform",
|
|
363
|
+
"epubWordBreak",
|
|
364
|
+
"epubWritingMode",
|
|
365
|
+
"fallback",
|
|
366
|
+
"fieldSizing",
|
|
367
|
+
"fill",
|
|
368
|
+
"fillBreak",
|
|
369
|
+
"fillColor",
|
|
370
|
+
"fillImage",
|
|
245
371
|
"fillOpacity",
|
|
372
|
+
"fillOrigin",
|
|
373
|
+
"fillPosition",
|
|
374
|
+
"fillRepeat",
|
|
246
375
|
"fillRule",
|
|
376
|
+
"fillSize",
|
|
247
377
|
"filter",
|
|
248
378
|
"flex",
|
|
249
379
|
"flexBasis",
|
|
@@ -253,27 +383,48 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
253
383
|
"flexShrink",
|
|
254
384
|
"flexWrap",
|
|
255
385
|
"float",
|
|
386
|
+
"floatDefer",
|
|
387
|
+
"floatOffset",
|
|
388
|
+
"floatReference",
|
|
256
389
|
"floodColor",
|
|
257
390
|
"floodOpacity",
|
|
391
|
+
"flow",
|
|
392
|
+
"flowFrom",
|
|
393
|
+
"flowInto",
|
|
258
394
|
"font",
|
|
395
|
+
"fontDisplay",
|
|
259
396
|
"fontFamily",
|
|
260
397
|
"fontFeatureSettings",
|
|
261
398
|
"fontKerning",
|
|
399
|
+
"fontLanguageOverride",
|
|
262
400
|
"fontOpticalSizing",
|
|
401
|
+
"fontPalette",
|
|
263
402
|
"fontSize",
|
|
264
403
|
"fontSizeAdjust",
|
|
265
404
|
"fontStretch",
|
|
266
405
|
"fontStyle",
|
|
267
406
|
"fontSynthesis",
|
|
407
|
+
"fontSynthesisPosition",
|
|
408
|
+
"fontSynthesisSmallCaps",
|
|
409
|
+
"fontSynthesisStyle",
|
|
410
|
+
"fontSynthesisWeight",
|
|
268
411
|
"fontVariant",
|
|
269
412
|
"fontVariantAlternates",
|
|
270
413
|
"fontVariantCaps",
|
|
271
414
|
"fontVariantEastAsian",
|
|
415
|
+
"fontVariantEmoji",
|
|
272
416
|
"fontVariantLigatures",
|
|
273
417
|
"fontVariantNumeric",
|
|
274
418
|
"fontVariantPosition",
|
|
419
|
+
"fontVariationSettings",
|
|
275
420
|
"fontWeight",
|
|
421
|
+
"fontWidth",
|
|
422
|
+
"footnoteDisplay",
|
|
423
|
+
"footnotePolicy",
|
|
424
|
+
"forcedColorAdjust",
|
|
276
425
|
"gap",
|
|
426
|
+
"glyphOrientationHorizontal",
|
|
427
|
+
"glyphOrientationVertical",
|
|
277
428
|
"grid",
|
|
278
429
|
"gridArea",
|
|
279
430
|
"gridAutoColumns",
|
|
@@ -281,67 +432,171 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
281
432
|
"gridAutoRows",
|
|
282
433
|
"gridColumn",
|
|
283
434
|
"gridColumnEnd",
|
|
435
|
+
"gridColumnGap",
|
|
284
436
|
"gridColumnStart",
|
|
437
|
+
"gridGap",
|
|
285
438
|
"gridRow",
|
|
286
439
|
"gridRowEnd",
|
|
440
|
+
"gridRowGap",
|
|
287
441
|
"gridRowStart",
|
|
288
442
|
"gridTemplate",
|
|
289
443
|
"gridTemplateAreas",
|
|
290
444
|
"gridTemplateColumns",
|
|
291
445
|
"gridTemplateRows",
|
|
446
|
+
"hangingPunctuation",
|
|
292
447
|
"height",
|
|
448
|
+
"hyphenateCharacter",
|
|
449
|
+
"hyphenateLimitChars",
|
|
450
|
+
"hyphenateLimitLast",
|
|
451
|
+
"hyphenateLimitLines",
|
|
452
|
+
"hyphenateLimitZone",
|
|
293
453
|
"hyphens",
|
|
454
|
+
"imageOrientation",
|
|
294
455
|
"imageRendering",
|
|
456
|
+
"imageResolution",
|
|
457
|
+
"imeMode",
|
|
458
|
+
"inherits",
|
|
459
|
+
"initialLetter",
|
|
460
|
+
"initialLetterAlign",
|
|
461
|
+
"initialLetterWrap",
|
|
462
|
+
"initialValue",
|
|
295
463
|
"inlineSize",
|
|
464
|
+
"inlineSizing",
|
|
465
|
+
"inputFormat",
|
|
466
|
+
"inputSecurity",
|
|
296
467
|
"inset",
|
|
468
|
+
"insetArea",
|
|
297
469
|
"insetBlock",
|
|
298
470
|
"insetBlockEnd",
|
|
299
471
|
"insetBlockStart",
|
|
300
472
|
"insetInline",
|
|
301
473
|
"insetInlineEnd",
|
|
302
474
|
"insetInlineStart",
|
|
475
|
+
"interactivity",
|
|
476
|
+
"interpolateSize",
|
|
303
477
|
"isolation",
|
|
478
|
+
"itemCross",
|
|
479
|
+
"itemDirection",
|
|
480
|
+
"itemFlow",
|
|
481
|
+
"itemPack",
|
|
482
|
+
"itemSlack",
|
|
483
|
+
"itemTrack",
|
|
484
|
+
"itemWrap",
|
|
304
485
|
"justifyContent",
|
|
305
486
|
"justifyItems",
|
|
306
487
|
"justifySelf",
|
|
488
|
+
"kerning",
|
|
489
|
+
"layoutFlow",
|
|
490
|
+
"layoutGrid",
|
|
491
|
+
"layoutGridChar",
|
|
492
|
+
"layoutGridLine",
|
|
493
|
+
"layoutGridMode",
|
|
494
|
+
"layoutGridType",
|
|
307
495
|
"left",
|
|
308
496
|
"letterSpacing",
|
|
309
497
|
"lightingColor",
|
|
310
498
|
"lineBreak",
|
|
499
|
+
"lineClamp",
|
|
500
|
+
"lineFitEdge",
|
|
501
|
+
"lineGapOverride",
|
|
502
|
+
"lineGrid",
|
|
311
503
|
"lineHeight",
|
|
504
|
+
"lineHeightStep",
|
|
505
|
+
"lineIncrement",
|
|
506
|
+
"linePadding",
|
|
507
|
+
"lineSnap",
|
|
312
508
|
"listStyle",
|
|
313
509
|
"listStyleImage",
|
|
314
510
|
"listStylePosition",
|
|
315
511
|
"listStyleType",
|
|
316
|
-
"marker",
|
|
317
|
-
"markerEnd",
|
|
318
|
-
"markerMid",
|
|
319
|
-
"markerStart",
|
|
320
512
|
"margin",
|
|
321
513
|
"marginBlock",
|
|
322
514
|
"marginBlockEnd",
|
|
323
515
|
"marginBlockStart",
|
|
324
516
|
"marginBottom",
|
|
517
|
+
"marginBreak",
|
|
325
518
|
"marginInline",
|
|
326
519
|
"marginInlineEnd",
|
|
327
520
|
"marginInlineStart",
|
|
328
521
|
"marginLeft",
|
|
329
522
|
"marginRight",
|
|
330
523
|
"marginTop",
|
|
524
|
+
"marginTrim",
|
|
525
|
+
"marker",
|
|
526
|
+
"markerEnd",
|
|
527
|
+
"markerKnockoutLeft",
|
|
528
|
+
"markerKnockoutRight",
|
|
529
|
+
"markerMid",
|
|
530
|
+
"markerOffset",
|
|
531
|
+
"markerPattern",
|
|
532
|
+
"markerSegment",
|
|
533
|
+
"markerSide",
|
|
534
|
+
"markerStart",
|
|
535
|
+
"marks",
|
|
536
|
+
"mask",
|
|
537
|
+
"maskBorder",
|
|
538
|
+
"maskBorderMode",
|
|
539
|
+
"maskBorderOutset",
|
|
540
|
+
"maskBorderRepeat",
|
|
541
|
+
"maskBorderSlice",
|
|
542
|
+
"maskBorderSource",
|
|
543
|
+
"maskBorderWidth",
|
|
544
|
+
"maskClip",
|
|
545
|
+
"maskComposite",
|
|
331
546
|
"maskImage",
|
|
547
|
+
"maskMode",
|
|
548
|
+
"maskOrigin",
|
|
549
|
+
"maskPosition",
|
|
550
|
+
"maskPositionX",
|
|
551
|
+
"maskPositionY",
|
|
552
|
+
"maskRepeat",
|
|
553
|
+
"maskSize",
|
|
554
|
+
"maskSourceType",
|
|
555
|
+
"maskType",
|
|
556
|
+
"mathDepth",
|
|
557
|
+
"mathShift",
|
|
558
|
+
"mathStyle",
|
|
332
559
|
"maxBlockSize",
|
|
333
560
|
"maxHeight",
|
|
334
561
|
"maxInlineSize",
|
|
562
|
+
"maxLines",
|
|
335
563
|
"maxWidth",
|
|
564
|
+
"maxZoom",
|
|
336
565
|
"minBlockSize",
|
|
337
566
|
"minHeight",
|
|
338
567
|
"minInlineSize",
|
|
568
|
+
"minIntrinsicSizing",
|
|
339
569
|
"minWidth",
|
|
570
|
+
"minZoom",
|
|
340
571
|
"mixBlendMode",
|
|
572
|
+
"motion",
|
|
573
|
+
"motionOffset",
|
|
574
|
+
"motionPath",
|
|
575
|
+
"motionRotation",
|
|
576
|
+
"navDown",
|
|
577
|
+
"navIndex",
|
|
578
|
+
"navLeft",
|
|
579
|
+
"navRight",
|
|
580
|
+
"navUp",
|
|
581
|
+
"navigation",
|
|
582
|
+
"negative",
|
|
341
583
|
"objectFit",
|
|
342
584
|
"objectPosition",
|
|
585
|
+
"objectViewBox",
|
|
586
|
+
"offset",
|
|
587
|
+
"offsetAnchor",
|
|
588
|
+
"offsetBlockEnd",
|
|
589
|
+
"offsetBlockStart",
|
|
590
|
+
"offsetDistance",
|
|
591
|
+
"offsetInlineEnd",
|
|
592
|
+
"offsetInlineStart",
|
|
593
|
+
"offsetPath",
|
|
594
|
+
"offsetPosition",
|
|
595
|
+
"offsetRotate",
|
|
596
|
+
"offsetRotation",
|
|
343
597
|
"opacity",
|
|
344
598
|
"order",
|
|
599
|
+
"orientation",
|
|
345
600
|
"orphans",
|
|
346
601
|
"outline",
|
|
347
602
|
"outlineColor",
|
|
@@ -350,10 +605,30 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
350
605
|
"outlineWidth",
|
|
351
606
|
"overflow",
|
|
352
607
|
"overflowAnchor",
|
|
608
|
+
"overflowBlock",
|
|
609
|
+
"overflowClipMargin",
|
|
610
|
+
"overflowClipMarginBlock",
|
|
611
|
+
"overflowClipMarginBlockEnd",
|
|
612
|
+
"overflowClipMarginBlockStart",
|
|
613
|
+
"overflowClipMarginBottom",
|
|
614
|
+
"overflowClipMarginInline",
|
|
615
|
+
"overflowClipMarginInlineEnd",
|
|
616
|
+
"overflowClipMarginInlineStart",
|
|
617
|
+
"overflowClipMarginLeft",
|
|
618
|
+
"overflowClipMarginRight",
|
|
619
|
+
"overflowClipMarginTop",
|
|
620
|
+
"overflowInline",
|
|
353
621
|
"overflowWrap",
|
|
354
622
|
"overflowX",
|
|
355
623
|
"overflowY",
|
|
624
|
+
"overlay",
|
|
625
|
+
"overrideColors",
|
|
356
626
|
"overscrollBehavior",
|
|
627
|
+
"overscrollBehaviorBlock",
|
|
628
|
+
"overscrollBehaviorInline",
|
|
629
|
+
"overscrollBehaviorX",
|
|
630
|
+
"overscrollBehaviorY",
|
|
631
|
+
"pad",
|
|
357
632
|
"padding",
|
|
358
633
|
"paddingBlock",
|
|
359
634
|
"paddingBlockEnd",
|
|
@@ -365,20 +640,75 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
365
640
|
"paddingLeft",
|
|
366
641
|
"paddingRight",
|
|
367
642
|
"paddingTop",
|
|
643
|
+
"page",
|
|
644
|
+
"pageBreakAfter",
|
|
645
|
+
"pageBreakBefore",
|
|
646
|
+
"pageBreakInside",
|
|
647
|
+
"pageOrientation",
|
|
648
|
+
"paintOrder",
|
|
649
|
+
"pause",
|
|
650
|
+
"pauseAfter",
|
|
651
|
+
"pauseBefore",
|
|
652
|
+
"penAction",
|
|
368
653
|
"perspective",
|
|
369
654
|
"perspectiveOrigin",
|
|
655
|
+
"perspectiveOriginX",
|
|
656
|
+
"perspectiveOriginY",
|
|
657
|
+
"pitch",
|
|
658
|
+
"pitchRange",
|
|
370
659
|
"placeContent",
|
|
371
660
|
"placeItems",
|
|
372
661
|
"placeSelf",
|
|
662
|
+
"playDuring",
|
|
373
663
|
"pointerEvents",
|
|
374
664
|
"position",
|
|
665
|
+
"positionAnchor",
|
|
666
|
+
"positionArea",
|
|
667
|
+
"positionTry",
|
|
668
|
+
"positionTryFallbacks",
|
|
669
|
+
"positionTryOptions",
|
|
670
|
+
"positionTryOrder",
|
|
671
|
+
"positionVisibility",
|
|
672
|
+
"prefix",
|
|
673
|
+
"printColorAdjust",
|
|
674
|
+
"propertyName",
|
|
375
675
|
"quotes",
|
|
676
|
+
"r",
|
|
677
|
+
"range",
|
|
678
|
+
"readingFlow",
|
|
679
|
+
"readingOrder",
|
|
680
|
+
"regionFragment",
|
|
376
681
|
"resize",
|
|
682
|
+
"rest",
|
|
683
|
+
"restAfter",
|
|
684
|
+
"restBefore",
|
|
685
|
+
"richness",
|
|
377
686
|
"right",
|
|
378
687
|
"rotate",
|
|
379
688
|
"rowGap",
|
|
689
|
+
"rowRule",
|
|
690
|
+
"rowRuleBreak",
|
|
691
|
+
"rowRuleColor",
|
|
692
|
+
"rowRuleOutset",
|
|
693
|
+
"rowRuleStyle",
|
|
694
|
+
"rowRuleWidth",
|
|
695
|
+
"rubyAlign",
|
|
696
|
+
"rubyMerge",
|
|
697
|
+
"rubyOverhang",
|
|
698
|
+
"rubyPosition",
|
|
699
|
+
"rule",
|
|
700
|
+
"ruleBreak",
|
|
701
|
+
"ruleColor",
|
|
702
|
+
"ruleOutset",
|
|
703
|
+
"rulePaintOrder",
|
|
704
|
+
"ruleStyle",
|
|
705
|
+
"ruleWidth",
|
|
706
|
+
"running",
|
|
707
|
+
"rx",
|
|
708
|
+
"ry",
|
|
380
709
|
"scale",
|
|
381
710
|
"scrollBehavior",
|
|
711
|
+
"scrollInitialTarget",
|
|
382
712
|
"scrollMargin",
|
|
383
713
|
"scrollMarginBlock",
|
|
384
714
|
"scrollMarginBlockEnd",
|
|
@@ -390,6 +720,7 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
390
720
|
"scrollMarginLeft",
|
|
391
721
|
"scrollMarginRight",
|
|
392
722
|
"scrollMarginTop",
|
|
723
|
+
"scrollMarkerGroup",
|
|
393
724
|
"scrollPadding",
|
|
394
725
|
"scrollPaddingBlock",
|
|
395
726
|
"scrollPaddingBlockEnd",
|
|
@@ -402,70 +733,251 @@ const KNOWN_CSS_PROPERTIES = new Set([
|
|
|
402
733
|
"scrollPaddingRight",
|
|
403
734
|
"scrollPaddingTop",
|
|
404
735
|
"scrollSnapAlign",
|
|
736
|
+
"scrollSnapCoordinate",
|
|
737
|
+
"scrollSnapDestination",
|
|
738
|
+
"scrollSnapMargin",
|
|
739
|
+
"scrollSnapMarginBottom",
|
|
740
|
+
"scrollSnapMarginLeft",
|
|
741
|
+
"scrollSnapMarginRight",
|
|
742
|
+
"scrollSnapMarginTop",
|
|
743
|
+
"scrollSnapPointsX",
|
|
744
|
+
"scrollSnapPointsY",
|
|
405
745
|
"scrollSnapStop",
|
|
406
746
|
"scrollSnapType",
|
|
747
|
+
"scrollSnapTypeX",
|
|
748
|
+
"scrollSnapTypeY",
|
|
749
|
+
"scrollStartTarget",
|
|
750
|
+
"scrollTargetGroup",
|
|
751
|
+
"scrollTimeline",
|
|
752
|
+
"scrollTimelineAxis",
|
|
753
|
+
"scrollTimelineName",
|
|
754
|
+
"scrollbar3dLightColor",
|
|
755
|
+
"scrollbar3dlightColor",
|
|
756
|
+
"scrollbarArrowColor",
|
|
757
|
+
"scrollbarBaseColor",
|
|
407
758
|
"scrollbarColor",
|
|
759
|
+
"scrollbarDarkShadowColor",
|
|
760
|
+
"scrollbarDarkshadowColor",
|
|
761
|
+
"scrollbarFaceColor",
|
|
408
762
|
"scrollbarGutter",
|
|
763
|
+
"scrollbarHighlightColor",
|
|
764
|
+
"scrollbarShadowColor",
|
|
765
|
+
"scrollbarTrackColor",
|
|
409
766
|
"scrollbarWidth",
|
|
767
|
+
"shapeImageThreshold",
|
|
768
|
+
"shapeInside",
|
|
769
|
+
"shapeMargin",
|
|
410
770
|
"shapeOutside",
|
|
411
771
|
"shapeRendering",
|
|
772
|
+
"size",
|
|
773
|
+
"sizeAdjust",
|
|
774
|
+
"sliderOrientation",
|
|
775
|
+
"snapHeight",
|
|
776
|
+
"solidColor",
|
|
777
|
+
"solidOpacity",
|
|
778
|
+
"spatialNavigationAction",
|
|
779
|
+
"spatialNavigationContain",
|
|
780
|
+
"spatialNavigationFunction",
|
|
781
|
+
"speak",
|
|
782
|
+
"speakAs",
|
|
783
|
+
"speakHeader",
|
|
784
|
+
"speakNumeral",
|
|
785
|
+
"speakPunctuation",
|
|
786
|
+
"speechRate",
|
|
787
|
+
"src",
|
|
412
788
|
"stopColor",
|
|
413
789
|
"stopOpacity",
|
|
790
|
+
"stress",
|
|
791
|
+
"stringSet",
|
|
414
792
|
"stroke",
|
|
793
|
+
"strokeAlign",
|
|
794
|
+
"strokeAlignment",
|
|
795
|
+
"strokeBreak",
|
|
796
|
+
"strokeColor",
|
|
797
|
+
"strokeDashCorner",
|
|
798
|
+
"strokeDashJustify",
|
|
799
|
+
"strokeDashadjust",
|
|
415
800
|
"strokeDasharray",
|
|
801
|
+
"strokeDashcorner",
|
|
416
802
|
"strokeDashoffset",
|
|
803
|
+
"strokeImage",
|
|
417
804
|
"strokeLinecap",
|
|
418
805
|
"strokeLinejoin",
|
|
419
806
|
"strokeMiterlimit",
|
|
420
807
|
"strokeOpacity",
|
|
808
|
+
"strokeOrigin",
|
|
809
|
+
"strokePosition",
|
|
810
|
+
"strokeRepeat",
|
|
811
|
+
"strokeSize",
|
|
421
812
|
"strokeWidth",
|
|
813
|
+
"suffix",
|
|
814
|
+
"supportedColorSchemes",
|
|
815
|
+
"symbols",
|
|
816
|
+
"syntax",
|
|
817
|
+
"system",
|
|
422
818
|
"tabSize",
|
|
423
819
|
"tableLayout",
|
|
424
820
|
"textAlign",
|
|
821
|
+
"textAlignAll",
|
|
425
822
|
"textAlignLast",
|
|
426
823
|
"textAnchor",
|
|
824
|
+
"textAutospace",
|
|
825
|
+
"textBox",
|
|
826
|
+
"textBoxEdge",
|
|
827
|
+
"textBoxTrim",
|
|
427
828
|
"textCombineUpright",
|
|
428
829
|
"textDecoration",
|
|
830
|
+
"textDecorationBlink",
|
|
429
831
|
"textDecorationColor",
|
|
430
832
|
"textDecorationLine",
|
|
833
|
+
"textDecorationLineThrough",
|
|
834
|
+
"textDecorationNone",
|
|
835
|
+
"textDecorationOverline",
|
|
836
|
+
"textDecorationSkip",
|
|
837
|
+
"textDecorationSkipBox",
|
|
431
838
|
"textDecorationSkipInk",
|
|
839
|
+
"textDecorationSkipInset",
|
|
840
|
+
"textDecorationSkipSelf",
|
|
841
|
+
"textDecorationSkipSpaces",
|
|
432
842
|
"textDecorationStyle",
|
|
433
843
|
"textDecorationThickness",
|
|
844
|
+
"textDecorationTrim",
|
|
845
|
+
"textDecorationUnderline",
|
|
434
846
|
"textEmphasis",
|
|
847
|
+
"textEmphasisColor",
|
|
848
|
+
"textEmphasisPosition",
|
|
849
|
+
"textEmphasisSkip",
|
|
850
|
+
"textEmphasisStyle",
|
|
851
|
+
"textGroupAlign",
|
|
435
852
|
"textIndent",
|
|
853
|
+
"textJustify",
|
|
854
|
+
"textJustifyTrim",
|
|
855
|
+
"textKashida",
|
|
856
|
+
"textKashidaSpace",
|
|
857
|
+
"textLineThrough",
|
|
858
|
+
"textLineThroughColor",
|
|
859
|
+
"textLineThroughMode",
|
|
860
|
+
"textLineThroughStyle",
|
|
861
|
+
"textLineThroughWidth",
|
|
436
862
|
"textOrientation",
|
|
437
863
|
"textOverflow",
|
|
864
|
+
"textOverline",
|
|
865
|
+
"textOverlineColor",
|
|
866
|
+
"textOverlineMode",
|
|
867
|
+
"textOverlineStyle",
|
|
868
|
+
"textOverlineWidth",
|
|
438
869
|
"textRendering",
|
|
439
870
|
"textShadow",
|
|
440
871
|
"textSizeAdjust",
|
|
872
|
+
"textSpacing",
|
|
873
|
+
"textSpacingTrim",
|
|
441
874
|
"textTransform",
|
|
875
|
+
"textUnderline",
|
|
876
|
+
"textUnderlineColor",
|
|
877
|
+
"textUnderlineMode",
|
|
442
878
|
"textUnderlineOffset",
|
|
443
879
|
"textUnderlinePosition",
|
|
880
|
+
"textUnderlineStyle",
|
|
881
|
+
"textUnderlineWidth",
|
|
444
882
|
"textWrap",
|
|
883
|
+
"textWrapMode",
|
|
884
|
+
"textWrapStyle",
|
|
885
|
+
"timelineScope",
|
|
445
886
|
"top",
|
|
446
887
|
"touchAction",
|
|
888
|
+
"touchActionDelay",
|
|
447
889
|
"transform",
|
|
890
|
+
"transformBox",
|
|
448
891
|
"transformOrigin",
|
|
892
|
+
"transformOriginX",
|
|
893
|
+
"transformOriginY",
|
|
894
|
+
"transformOriginZ",
|
|
449
895
|
"transformStyle",
|
|
450
896
|
"transition",
|
|
897
|
+
"transitionBehavior",
|
|
451
898
|
"transitionDelay",
|
|
452
899
|
"transitionDuration",
|
|
453
900
|
"transitionProperty",
|
|
454
901
|
"transitionTimingFunction",
|
|
455
902
|
"translate",
|
|
903
|
+
"types",
|
|
904
|
+
"ucAltSkin",
|
|
905
|
+
"ucSkin",
|
|
456
906
|
"unicodeBidi",
|
|
907
|
+
"unicodeRange",
|
|
457
908
|
"userSelect",
|
|
909
|
+
"userZoom",
|
|
910
|
+
"vectorEffect",
|
|
458
911
|
"verticalAlign",
|
|
912
|
+
"viewTimeline",
|
|
913
|
+
"viewTimelineAxis",
|
|
914
|
+
"viewTimelineInset",
|
|
915
|
+
"viewTimelineName",
|
|
916
|
+
"viewTransitionClass",
|
|
917
|
+
"viewTransitionGroup",
|
|
918
|
+
"viewTransitionName",
|
|
919
|
+
"viewportFill",
|
|
920
|
+
"viewportFillOpacity",
|
|
921
|
+
"viewportFit",
|
|
459
922
|
"visibility",
|
|
923
|
+
"voiceBalance",
|
|
924
|
+
"voiceDuration",
|
|
925
|
+
"voiceFamily",
|
|
926
|
+
"voicePitch",
|
|
927
|
+
"voiceRange",
|
|
928
|
+
"voiceRate",
|
|
929
|
+
"voiceStress",
|
|
930
|
+
"voiceVolume",
|
|
931
|
+
"volume",
|
|
460
932
|
"whiteSpace",
|
|
933
|
+
"whiteSpaceCollapse",
|
|
934
|
+
"whiteSpaceTrim",
|
|
461
935
|
"widows",
|
|
462
936
|
"width",
|
|
463
937
|
"willChange",
|
|
464
938
|
"wordBreak",
|
|
939
|
+
"wordSpaceTransform",
|
|
465
940
|
"wordSpacing",
|
|
941
|
+
"wordWrap",
|
|
942
|
+
"wrapAfter",
|
|
943
|
+
"wrapBefore",
|
|
944
|
+
"wrapFlow",
|
|
945
|
+
"wrapInside",
|
|
946
|
+
"wrapThrough",
|
|
466
947
|
"writingMode",
|
|
467
|
-
"
|
|
468
|
-
|
|
948
|
+
"x",
|
|
949
|
+
"y",
|
|
950
|
+
"zIndex",
|
|
951
|
+
"zoom"
|
|
952
|
+
];
|
|
953
|
+
/**
|
|
954
|
+
* Properties that ship in browsers or sit in a spec, but have not landed in
|
|
955
|
+
* `known-css-properties` yet. Hand-maintained, and pruned as the dataset catches
|
|
956
|
+
* up — the guard test fails on any entry the dataset already covers.
|
|
957
|
+
*/
|
|
958
|
+
const EMERGING_CSS_PROPERTIES = [
|
|
959
|
+
"cornerShape",
|
|
960
|
+
"cornerTopShape",
|
|
961
|
+
"cornerRightShape",
|
|
962
|
+
"cornerBottomShape",
|
|
963
|
+
"cornerLeftShape",
|
|
964
|
+
"cornerBlockStartShape",
|
|
965
|
+
"cornerBlockEndShape",
|
|
966
|
+
"cornerInlineStartShape",
|
|
967
|
+
"cornerInlineEndShape",
|
|
968
|
+
"cornerTopLeftShape",
|
|
969
|
+
"cornerTopRightShape",
|
|
970
|
+
"cornerBottomRightShape",
|
|
971
|
+
"cornerBottomLeftShape",
|
|
972
|
+
"cornerStartStartShape",
|
|
973
|
+
"cornerStartEndShape",
|
|
974
|
+
"cornerEndStartShape",
|
|
975
|
+
"cornerEndEndShape"
|
|
976
|
+
];
|
|
977
|
+
/**
|
|
978
|
+
* Every CSS property `known-property` accepts as a camelCase style key.
|
|
979
|
+
*/
|
|
980
|
+
const KNOWN_CSS_PROPERTIES = new Set([...DATASET_CSS_PROPERTIES, ...EMERGING_CSS_PROPERTIES]);
|
|
469
981
|
/**
|
|
470
982
|
* Built-in custom units recognized by the tasty parser.
|
|
471
983
|
*/
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Built-in tasty style properties that are always valid as style keys.\n */\nexport const KNOWN_TASTY_PROPERTIES = new Set([\n 'display',\n 'font',\n 'preset',\n 'hide',\n 'whiteSpace',\n 'opacity',\n 'transition',\n 'gridArea',\n 'order',\n 'gridColumn',\n 'gridRow',\n 'placeSelf',\n 'alignSelf',\n 'justifySelf',\n 'zIndex',\n 'margin',\n 'inset',\n 'position',\n 'padding',\n 'paddingInline',\n 'paddingBlock',\n 'overflow',\n 'scrollbar',\n 'textAlign',\n 'border',\n 'radius',\n 'shadow',\n 'outline',\n 'color',\n 'fill',\n 'fade',\n 'image',\n 'textTransform',\n 'fontWeight',\n 'fontStyle',\n 'width',\n 'height',\n 'flexBasis',\n 'flexGrow',\n 'flexShrink',\n 'flex',\n 'flow',\n 'placeItems',\n 'placeContent',\n 'alignItems',\n 'alignContent',\n 'justifyItems',\n 'justifyContent',\n 'align',\n 'justify',\n 'gap',\n 'columnGap',\n 'rowGap',\n 'gridColumns',\n 'gridRows',\n 'gridTemplate',\n 'gridAreas',\n 'recipe',\n 'textOverflow',\n 'textDecoration',\n 'animation',\n 'cursor',\n 'pointerEvents',\n 'userSelect',\n 'transform',\n 'transformOrigin',\n 'filter',\n 'backdropFilter',\n 'mixBlendMode',\n 'objectFit',\n 'objectPosition',\n 'resize',\n 'appearance',\n 'listStyle',\n 'listStyleType',\n 'content',\n 'boxSizing',\n 'verticalAlign',\n 'wordBreak',\n 'overflowWrap',\n 'hyphens',\n 'tabSize',\n 'direction',\n 'unicodeBidi',\n 'writingMode',\n 'lineClamp',\n 'aspectRatio',\n 'contain',\n 'container',\n 'containerType',\n 'containerName',\n 'interpolateSize',\n 'willChange',\n 'isolation',\n 'touchAction',\n 'scrollBehavior',\n 'scrollSnapType',\n 'scrollSnapAlign',\n 'caretColor',\n 'accentColor',\n 'colorScheme',\n]);\n\n/**\n * Special top-level keys that are valid but not regular style properties.\n *\n * These match the real CSS at-rule names Tasty emits, so they are kebab-case.\n */\nexport const SPECIAL_STYLE_KEYS = new Set([\n '@keyframes',\n '@property',\n '@font-face',\n '@counter-style',\n '@function',\n]);\n\n/**\n * At-rule style keys renamed in Tasty v3, mapped old spelling -> new.\n *\n * The v2 spellings were camelCase; v3 uses the CSS at-rule names Tasty already\n * emitted. Reported (and auto-fixed) so upgrading is mechanical.\n */\nexport const RENAMED_SPECIAL_STYLE_KEYS: Record<string, string> = {\n '@properties': '@property',\n '@fontFace': '@font-face',\n '@counterStyle': '@counter-style',\n};\n\n/**\n * CSS property names (common subset for validation).\n * When a key is camelCase and matches a known CSS property, it's valid.\n */\nexport const KNOWN_CSS_PROPERTIES = new Set([\n 'all',\n 'animation',\n 'animationDelay',\n 'animationDirection',\n 'animationDuration',\n 'animationFillMode',\n 'animationIterationCount',\n 'animationName',\n 'animationPlayState',\n 'animationTimingFunction',\n 'appearance',\n 'aspectRatio',\n 'backdropFilter',\n 'backfaceVisibility',\n 'background',\n 'backgroundAttachment',\n 'backgroundBlendMode',\n 'backgroundClip',\n 'backgroundColor',\n 'backgroundImage',\n 'backgroundOrigin',\n 'backgroundPosition',\n 'backgroundRepeat',\n 'backgroundSize',\n 'blockSize',\n 'border',\n 'borderBlock',\n 'borderBlockColor',\n 'borderBlockEnd',\n 'borderBlockEndColor',\n 'borderBlockEndStyle',\n 'borderBlockEndWidth',\n 'borderBlockStart',\n 'borderBlockStartColor',\n 'borderBlockStartStyle',\n 'borderBlockStartWidth',\n 'borderBlockStyle',\n 'borderBlockWidth',\n 'borderBottom',\n 'borderBottomColor',\n 'borderBottomLeftRadius',\n 'borderBottomRightRadius',\n 'borderBottomStyle',\n 'borderBottomWidth',\n 'borderCollapse',\n 'borderColor',\n 'borderImage',\n 'borderInline',\n 'borderInlineColor',\n 'borderInlineEnd',\n 'borderInlineStart',\n 'borderInlineStyle',\n 'borderInlineWidth',\n 'borderLeft',\n 'borderLeftColor',\n 'borderLeftStyle',\n 'borderLeftWidth',\n 'borderRadius',\n 'borderRight',\n 'borderRightColor',\n 'borderRightStyle',\n 'borderRightWidth',\n 'borderSpacing',\n 'borderStyle',\n 'borderTop',\n 'borderTopColor',\n 'borderTopLeftRadius',\n 'borderTopRightRadius',\n 'borderTopStyle',\n 'borderTopWidth',\n 'borderWidth',\n 'bottom',\n 'boxDecorationBreak',\n 'boxShadow',\n 'boxSizing',\n 'breakAfter',\n 'breakBefore',\n 'breakInside',\n 'captionSide',\n 'caretColor',\n 'clear',\n 'clip',\n 'clipPath',\n 'clipRule',\n 'color',\n 'colorScheme',\n 'columnCount',\n 'columnFill',\n 'columnGap',\n 'columnRule',\n 'columnRuleColor',\n 'columnRuleStyle',\n 'columnRuleWidth',\n 'columnSpan',\n 'columnWidth',\n 'columns',\n 'contain',\n 'containerName',\n 'containerType',\n 'content',\n 'contentVisibility',\n 'counterIncrement',\n 'counterReset',\n 'counterSet',\n 'cursor',\n 'direction',\n 'display',\n 'dominantBaseline',\n 'emptyCells',\n 'fillOpacity',\n 'fillRule',\n 'filter',\n 'flex',\n 'flexBasis',\n 'flexDirection',\n 'flexFlow',\n 'flexGrow',\n 'flexShrink',\n 'flexWrap',\n 'float',\n 'floodColor',\n 'floodOpacity',\n 'font',\n 'fontFamily',\n 'fontFeatureSettings',\n 'fontKerning',\n 'fontOpticalSizing',\n 'fontSize',\n 'fontSizeAdjust',\n 'fontStretch',\n 'fontStyle',\n 'fontSynthesis',\n 'fontVariant',\n 'fontVariantAlternates',\n 'fontVariantCaps',\n 'fontVariantEastAsian',\n 'fontVariantLigatures',\n 'fontVariantNumeric',\n 'fontVariantPosition',\n 'fontWeight',\n 'gap',\n 'grid',\n 'gridArea',\n 'gridAutoColumns',\n 'gridAutoFlow',\n 'gridAutoRows',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowStart',\n 'gridTemplate',\n 'gridTemplateAreas',\n 'gridTemplateColumns',\n 'gridTemplateRows',\n 'height',\n 'hyphens',\n 'imageRendering',\n 'inlineSize',\n 'inset',\n 'insetBlock',\n 'insetBlockEnd',\n 'insetBlockStart',\n 'insetInline',\n 'insetInlineEnd',\n 'insetInlineStart',\n 'isolation',\n 'justifyContent',\n 'justifyItems',\n 'justifySelf',\n 'left',\n 'letterSpacing',\n 'lightingColor',\n 'lineBreak',\n 'lineHeight',\n 'listStyle',\n 'listStyleImage',\n 'listStylePosition',\n 'listStyleType',\n 'marker',\n 'markerEnd',\n 'markerMid',\n 'markerStart',\n 'margin',\n 'marginBlock',\n 'marginBlockEnd',\n 'marginBlockStart',\n 'marginBottom',\n 'marginInline',\n 'marginInlineEnd',\n 'marginInlineStart',\n 'marginLeft',\n 'marginRight',\n 'marginTop',\n 'maskImage',\n 'maxBlockSize',\n 'maxHeight',\n 'maxInlineSize',\n 'maxWidth',\n 'minBlockSize',\n 'minHeight',\n 'minInlineSize',\n 'minWidth',\n 'mixBlendMode',\n 'objectFit',\n 'objectPosition',\n 'opacity',\n 'order',\n 'orphans',\n 'outline',\n 'outlineColor',\n 'outlineOffset',\n 'outlineStyle',\n 'outlineWidth',\n 'overflow',\n 'overflowAnchor',\n 'overflowWrap',\n 'overflowX',\n 'overflowY',\n 'overscrollBehavior',\n 'padding',\n 'paddingBlock',\n 'paddingBlockEnd',\n 'paddingBlockStart',\n 'paddingBottom',\n 'paddingInline',\n 'paddingInlineEnd',\n 'paddingInlineStart',\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'perspective',\n 'perspectiveOrigin',\n 'placeContent',\n 'placeItems',\n 'placeSelf',\n 'pointerEvents',\n 'position',\n 'quotes',\n 'resize',\n 'right',\n 'rotate',\n 'rowGap',\n 'scale',\n 'scrollBehavior',\n 'scrollMargin',\n 'scrollMarginBlock',\n 'scrollMarginBlockEnd',\n 'scrollMarginBlockStart',\n 'scrollMarginBottom',\n 'scrollMarginInline',\n 'scrollMarginInlineEnd',\n 'scrollMarginInlineStart',\n 'scrollMarginLeft',\n 'scrollMarginRight',\n 'scrollMarginTop',\n 'scrollPadding',\n 'scrollPaddingBlock',\n 'scrollPaddingBlockEnd',\n 'scrollPaddingBlockStart',\n 'scrollPaddingBottom',\n 'scrollPaddingInline',\n 'scrollPaddingInlineEnd',\n 'scrollPaddingInlineStart',\n 'scrollPaddingLeft',\n 'scrollPaddingRight',\n 'scrollPaddingTop',\n 'scrollSnapAlign',\n 'scrollSnapStop',\n 'scrollSnapType',\n 'scrollbarColor',\n 'scrollbarGutter',\n 'scrollbarWidth',\n 'shapeOutside',\n 'shapeRendering',\n 'stopColor',\n 'stopOpacity',\n 'stroke',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeLinecap',\n 'strokeLinejoin',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n 'tabSize',\n 'tableLayout',\n 'textAlign',\n 'textAlignLast',\n 'textAnchor',\n 'textCombineUpright',\n 'textDecoration',\n 'textDecorationColor',\n 'textDecorationLine',\n 'textDecorationSkipInk',\n 'textDecorationStyle',\n 'textDecorationThickness',\n 'textEmphasis',\n 'textIndent',\n 'textOrientation',\n 'textOverflow',\n 'textRendering',\n 'textShadow',\n 'textSizeAdjust',\n 'textTransform',\n 'textUnderlineOffset',\n 'textUnderlinePosition',\n 'textWrap',\n 'top',\n 'touchAction',\n 'transform',\n 'transformOrigin',\n 'transformStyle',\n 'transition',\n 'transitionDelay',\n 'transitionDuration',\n 'transitionProperty',\n 'transitionTimingFunction',\n 'translate',\n 'unicodeBidi',\n 'userSelect',\n 'verticalAlign',\n 'visibility',\n 'whiteSpace',\n 'widows',\n 'width',\n 'willChange',\n 'wordBreak',\n 'wordSpacing',\n 'writingMode',\n 'zIndex',\n]);\n\n/**\n * Built-in custom units recognized by the tasty parser.\n */\nexport const BUILT_IN_UNITS = new Set(['x', 'r', 'cr', 'bw', 'ow', 'lh', 'sf']);\n\n/**\n * Standard CSS units (always valid).\n */\nexport const CSS_UNITS = new Set([\n 'px',\n 'em',\n 'rem',\n '%',\n 'vw',\n 'vh',\n 'vmin',\n 'vmax',\n 'ch',\n 'ex',\n 'cm',\n 'mm',\n 'in',\n 'pt',\n 'pc',\n 'fr',\n 'deg',\n 'rad',\n 'turn',\n 'grad',\n 's',\n 'ms',\n 'dpi',\n 'dpcm',\n 'dppx',\n 'svw',\n 'svh',\n 'lvw',\n 'lvh',\n 'dvw',\n 'dvh',\n 'cqw',\n 'cqh',\n 'cqi',\n 'cqb',\n 'cqmin',\n 'cqmax',\n 'cap',\n 'ic',\n 'rlh',\n 'vi',\n 'vb',\n]);\n\n/**\n * Properties that accept `true` as a value (means \"use default\").\n */\nexport const BOOLEAN_TRUE_PROPERTIES = new Set([\n 'border',\n 'radius',\n 'padding',\n 'margin',\n 'gap',\n 'fill',\n 'color',\n 'shadow',\n 'outline',\n 'inset',\n 'width',\n 'height',\n // `fade: true` falls back to `calc(2 * var(--gap))` — a token-following\n // default no explicit value can express, so it is genuinely useful.\n 'fade',\n 'hide',\n 'preset',\n 'font',\n 'scrollbar',\n]);\n\n/**\n * Directional modifiers and which properties accept them.\n */\nexport const DIRECTIONAL_MODIFIERS: Record<string, Set<string>> = {\n border: new Set(['top', 'right', 'bottom', 'left']),\n radius: new Set([\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n ]),\n padding: new Set(['top', 'right', 'bottom', 'left']),\n margin: new Set(['top', 'right', 'bottom', 'left']),\n fade: new Set(['top', 'right', 'bottom', 'left']),\n scrollMargin: new Set(['top', 'right', 'bottom', 'left']),\n inset: new Set(['top', 'right', 'bottom', 'left', 'dock']),\n};\n\n/**\n * Properties where a group naming directions carries exactly **one** value.\n *\n * Tasty v3 dropped the positional multi-value form for these: values and\n * modifiers are bucketed separately per comma group, so `'2x 4x top right'` and\n * `'2x top 4x right'` were the same input and the pairing depended on modifier\n * order. Per-side values now come from comma groups.\n *\n * Deliberately excludes `border` and `radius`. A `border` group legitimately\n * carries width + style + color, and a `radius` group can carry two values with\n * `leaf`/`backleaf`; neither takes the positional-per-side form, so neither is\n * subject to the rule.\n */\nexport const SINGLE_VALUE_DIRECTIONAL_PROPERTIES = new Set([\n 'padding',\n 'margin',\n 'inset',\n 'scrollMargin',\n 'fade',\n]);\n\n/**\n * Position names a 4-value box maps onto, in source order.\n */\nexport const BOX_SIDES = ['top', 'right', 'bottom', 'left'] as const;\nexport const BOX_CORNERS = [\n 'top-left',\n 'top-right',\n 'bottom-right',\n 'bottom-left',\n] as const;\n\nexport interface DirectionalBoxConfig {\n /**\n * The token that marks an unset position — dropping it from the shorthand\n * leaves the emitted CSS unchanged. This is the CSS initial value of the\n * longhand, which is not always `0`: `inset` initialises to `auto`, so a `0`\n * there is a real offset the shorthand must not drop.\n */\n identity: string;\n /** Modifier names for each of the four positions, in source order. */\n positions: readonly string[];\n /**\n * Whether `eslint --fix` may apply the rewrite. False when the rewrite is\n * still an improvement but changes what the browser renders, so a human has\n * to opt in.\n */\n fixable: boolean;\n /**\n * Set when the 4-value form is not interpreted per-position at all, so the\n * current output is wrong rather than merely verbose. Surfaced in the report.\n */\n note?: string;\n}\n\n/**\n * Properties whose 4-value box syntax has a directional-shorthand equivalent.\n *\n * `radius` uses corner names rather than sides: a directional modifier\n * addresses the corner *pair* along an edge, so only `top-left` & co. can\n * express a single corner (requires `@tenphi/tasty` >= 2.10).\n */\nexport const DIRECTIONAL_BOX: Record<string, DirectionalBoxConfig> = {\n margin: { identity: '0', positions: BOX_SIDES, fixable: true },\n padding: { identity: '0', positions: BOX_SIDES, fixable: true },\n inset: { identity: 'auto', positions: BOX_SIDES, fixable: true },\n radius: { identity: '0', positions: BOX_CORNERS, fixable: true },\n fade: { identity: '0', positions: BOX_SIDES, fixable: true },\n // Four `border` tokens parse as a single border value (width/style/color),\n // not as a box: `border: '0 0 1bw 0'` emits `border: 0 solid …` — no border\n // on any side. The directional form is what the author meant, but applying\n // it changes rendering, so it stays a manual fix.\n border: {\n identity: '0',\n positions: BOX_SIDES,\n fixable: false,\n note: 'four border tokens parse as one border value, so the current style sets no border at all',\n },\n};\n\n/**\n * Properties that support a `dock` modifier — pin one edge and span its full\n * length. Lets a 4-value box with a single `identity` side collapse, e.g.\n * `inset: 'auto 0 0 0'` -> `inset: '0 bottom dock'`.\n * Requires `@tenphi/tasty` >= 2.10.\n */\nexport const DOCK_PROPERTIES = new Set(['inset']);\n\n/**\n * Valid radius shape keywords.\n */\nexport const RADIUS_SHAPES = new Set(['round', 'ellipse', 'leaf', 'backleaf']);\n\n/**\n * Known semantic transition names.\n */\nexport const SEMANTIC_TRANSITIONS = new Set([\n 'fade',\n 'fill',\n 'border',\n 'radius',\n 'shadow',\n 'preset',\n 'gap',\n 'theme',\n 'color',\n 'outline',\n 'dimension',\n 'flow',\n 'inset',\n 'text',\n 'opacity',\n 'translate',\n 'rotate',\n 'scale',\n 'filter',\n 'image',\n 'background',\n 'width',\n 'height',\n 'zIndex',\n]);\n\n/**\n * Mapping of native CSS properties to tasty shorthand alternatives.\n */\nexport const SHORTHAND_MAPPING: Record<\n string,\n { property: string; hint: string; safeFix?: boolean }\n> = {\n backgroundColor: { property: 'fill', hint: \"fill: '...'\", safeFix: true },\n borderColor: { property: 'border', hint: \"border: '...'\" },\n borderWidth: { property: 'border', hint: \"border: '...'\" },\n borderStyle: { property: 'border', hint: \"border: '...'\" },\n borderTop: { property: 'border', hint: \"border: '... top'\" },\n borderRight: { property: 'border', hint: \"border: '... right'\" },\n borderBottom: { property: 'border', hint: \"border: '... bottom'\" },\n borderLeft: { property: 'border', hint: \"border: '... left'\" },\n borderRadius: { property: 'radius', hint: \"radius: '...'\", safeFix: true },\n maxWidth: { property: 'width', hint: \"width: 'max ...'\" },\n minWidth: { property: 'width', hint: \"width: 'min ...'\" },\n maxHeight: { property: 'height', hint: \"height: 'max ...'\" },\n minHeight: { property: 'height', hint: \"height: 'min ...'\" },\n flexDirection: { property: 'flow', hint: \"flow: '...'\" },\n flexWrap: { property: 'flow', hint: \"flow: '...'\" },\n flexFlow: { property: 'flow', hint: \"flow: '...'\" },\n gridAutoFlow: { property: 'flow', hint: \"flow: '...'\" },\n outlineOffset: { property: 'outline', hint: \"outline: '... / offset'\" },\n paddingTop: { property: 'padding', hint: \"padding: '... top'\" },\n paddingRight: { property: 'padding', hint: \"padding: '... right'\" },\n paddingBottom: { property: 'padding', hint: \"padding: '... bottom'\" },\n paddingLeft: { property: 'padding', hint: \"padding: '... left'\" },\n marginTop: { property: 'margin', hint: \"margin: '... top'\" },\n marginRight: { property: 'margin', hint: \"margin: '... right'\" },\n marginBottom: { property: 'margin', hint: \"margin: '... bottom'\" },\n marginLeft: { property: 'margin', hint: \"margin: '... left'\" },\n fontSize: { property: 'preset', hint: \"preset: '...'\" },\n fontWeight: {\n property: 'preset',\n hint: \"preset: 'name / strong' (with strong modifier)\",\n },\n lineHeight: {\n property: 'preset',\n hint: \"preset: 'name / tight' (with tight modifier)\",\n },\n boxShadow: { property: 'shadow', hint: \"shadow: '...'\" },\n backgroundImage: { property: 'image', hint: \"image: '...'\" },\n fontFamily: { property: 'font', hint: \"font: '...'\" },\n fontStyle: {\n property: 'preset',\n hint: \"preset: 'name / italic' (with italic modifier)\",\n },\n letterSpacing: { property: 'preset', hint: \"preset: '...'\" },\n textTransform: { property: 'preset', hint: \"preset: '...'\" },\n flexGap: { property: 'gap', hint: \"gap: '...'\" },\n scrollbarWidth: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n scrollbarColor: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n scrollbarGutter: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n gridTemplateColumns: {\n property: 'gridColumns',\n hint: \"gridColumns: '...'\",\n },\n gridTemplateRows: { property: 'gridRows', hint: \"gridRows: '...'\" },\n gridTemplateAreas: { property: 'gridAreas', hint: \"gridAreas: '...'\" },\n top: { property: 'inset', hint: \"inset: '... top'\" },\n right: { property: 'inset', hint: \"inset: '... right'\" },\n bottom: { property: 'inset', hint: \"inset: '... bottom'\" },\n left: { property: 'inset', hint: \"inset: '... left'\" },\n outlineColor: { property: 'outline', hint: \"outline: '...'\" },\n outlineWidth: { property: 'outline', hint: \"outline: '...'\" },\n outlineStyle: { property: 'outline', hint: \"outline: '...'\" },\n lineClamp: {\n property: 'textOverflow',\n hint: \"textOverflow: 'ellipsis / {lines}'\",\n },\n};\n\n/**\n * CSS shorthands whose *longhands* are the preferred Tasty form — the reverse\n * of `SHORTHAND_MAPPING`.\n *\n * `flex` is lossy in a way the longhands are not: it resets the two components\n * you did not write to values that are not their CSS initial. `flex: '0'`\n * expands to `flex-grow: 0; flex-shrink: 1; flex-basis: 0%`, so it cannot\n * express \"do not shrink\" (`flexShrink: 0`) at all, and it silently changes\n * `flex-basis`. Writing the longhands keeps each component independent, which\n * also lets them carry separate state maps.\n */\nexport const LONGHAND_MAPPING: Record<\n string,\n { longhands: string[]; hint: string }\n> = {\n flex: {\n longhands: ['flexGrow', 'flexShrink', 'flexBasis'],\n hint: 'flexGrow / flexShrink / flexBasis',\n },\n};\n\n/**\n * CSS transition property names mapped to Tasty semantic transition names.\n */\nexport const TRANSITION_SEMANTIC_MAPPING: Record<string, string> = {\n backgroundColor: 'fill',\n 'background-color': 'fill',\n backgroundImage: 'image',\n 'background-image': 'image',\n borderRadius: 'radius',\n 'border-radius': 'radius',\n borderColor: 'border',\n 'border-color': 'border',\n borderWidth: 'border',\n 'border-width': 'border',\n borderStyle: 'border',\n 'border-style': 'border',\n boxShadow: 'shadow',\n 'box-shadow': 'shadow',\n outlineColor: 'outline',\n 'outline-color': 'outline',\n outlineWidth: 'outline',\n 'outline-width': 'outline',\n outlineOffset: 'outline',\n 'outline-offset': 'outline',\n gridTemplateColumns: 'gridColumns',\n 'grid-template-columns': 'gridColumns',\n gridTemplateRows: 'gridRows',\n 'grid-template-rows': 'gridRows',\n flexDirection: 'flow',\n 'flex-direction': 'flow',\n gridAutoFlow: 'flow',\n 'grid-auto-flow': 'flow',\n fontSize: 'preset',\n 'font-size': 'preset',\n lineHeight: 'preset',\n 'line-height': 'preset',\n letterSpacing: 'preset',\n 'letter-spacing': 'preset',\n};\n\n/**\n * Known preset modifiers.\n */\nexport const PRESET_MODIFIERS = new Set([\n 'strong',\n 'bold',\n 'italic',\n 'icon',\n 'tight',\n]);\n\n/**\n * Default import sources for tasty.\n */\nexport const DEFAULT_IMPORT_SOURCES = ['@tenphi/tasty', '@tenphi/tasty/static'];\n\n/**\n * Built-in state prefixes that are always valid (not aliases).\n */\nexport const BUILT_IN_STATE_PREFIXES = new Set([\n '@media',\n '@root',\n '@parent',\n '@own',\n '@supports',\n '@starting',\n '@keyframes',\n '@property',\n '@font-face',\n '@counter-style',\n '@function',\n]);\n\n/**\n * Known CSS pseudo-classes.\n */\nexport const KNOWN_PSEUDO_CLASSES = new Set([\n ':hover',\n ':focus',\n ':focus-visible',\n ':focus-within',\n ':active',\n ':visited',\n ':link',\n ':checked',\n ':disabled',\n ':enabled',\n ':empty',\n ':first-child',\n ':last-child',\n ':first-of-type',\n ':last-of-type',\n ':only-child',\n ':only-of-type',\n ':root',\n ':target',\n ':valid',\n ':invalid',\n ':required',\n ':optional',\n ':read-only',\n ':read-write',\n ':placeholder-shown',\n ':autofill',\n ':default',\n ':indeterminate',\n ':in-range',\n ':out-of-range',\n ':any-link',\n ':local-link',\n ':is',\n ':not',\n ':where',\n ':has',\n ':nth-child',\n ':nth-last-child',\n ':nth-of-type',\n ':nth-last-of-type',\n '::before',\n '::after',\n '::placeholder',\n '::selection',\n '::first-line',\n '::first-letter',\n '::marker',\n '::backdrop',\n]);\n\n/**\n * CSS named colors (level 1–4) that should be replaced by `#color` tokens.\n * `transparent` and `currentcolor` are excluded — they have their own token\n * suggestions (`#clear`, `#current`) handled by `prefer-custom-property-syntax`.\n */\nexport const NAMED_CSS_COLORS = new Set<string>([\n 'aliceblue',\n 'antiquewhite',\n 'aqua',\n 'aquamarine',\n 'azure',\n 'beige',\n 'bisque',\n 'black',\n 'blanchedalmond',\n 'blue',\n 'blueviolet',\n 'brown',\n 'burlywood',\n 'cadetblue',\n 'chartreuse',\n 'chocolate',\n 'coral',\n 'cornflowerblue',\n 'cornsilk',\n 'crimson',\n 'cyan',\n 'darkblue',\n 'darkcyan',\n 'darkgoldenrod',\n 'darkgray',\n 'darkgreen',\n 'darkgrey',\n 'darkkhaki',\n 'darkmagenta',\n 'darkolivegreen',\n 'darkorange',\n 'darkorchid',\n 'darkred',\n 'darksalmon',\n 'darkseagreen',\n 'darkslateblue',\n 'darkslategray',\n 'darkslategrey',\n 'darkturquoise',\n 'darkviolet',\n 'deeppink',\n 'deepskyblue',\n 'dimgray',\n 'dimgrey',\n 'dodgerblue',\n 'firebrick',\n 'floralwhite',\n 'forestgreen',\n 'fuchsia',\n 'gainsboro',\n 'ghostwhite',\n 'gold',\n 'goldenrod',\n 'gray',\n 'green',\n 'greenyellow',\n 'grey',\n 'honeydew',\n 'hotpink',\n 'indianred',\n 'indigo',\n 'ivory',\n 'khaki',\n 'lavender',\n 'lavenderblush',\n 'lawngreen',\n 'lemonchiffon',\n 'lightblue',\n 'lightcoral',\n 'lightcyan',\n 'lightgoldenrodyellow',\n 'lightgray',\n 'lightgreen',\n 'lightgrey',\n 'lightpink',\n 'lightsalmon',\n 'lightseagreen',\n 'lightskyblue',\n 'lightslategray',\n 'lightslategrey',\n 'lightsteelblue',\n 'lightyellow',\n 'lime',\n 'limegreen',\n 'linen',\n 'magenta',\n 'maroon',\n 'mediumaquamarine',\n 'mediumblue',\n 'mediumorchid',\n 'mediumpurple',\n 'mediumseagreen',\n 'mediumslateblue',\n 'mediumspringgreen',\n 'mediumturquoise',\n 'mediumvioletred',\n 'midnightblue',\n 'mintcream',\n 'mistyrose',\n 'moccasin',\n 'navajowhite',\n 'navy',\n 'oldlace',\n 'olive',\n 'olivedrab',\n 'orange',\n 'orangered',\n 'orchid',\n 'palegoldenrod',\n 'palegreen',\n 'paleturquoise',\n 'palevioletred',\n 'papayawhip',\n 'peachpuff',\n 'peru',\n 'pink',\n 'plum',\n 'powderblue',\n 'purple',\n 'rebeccapurple',\n 'red',\n 'rosybrown',\n 'royalblue',\n 'saddlebrown',\n 'salmon',\n 'sandybrown',\n 'seagreen',\n 'seashell',\n 'sienna',\n 'silver',\n 'skyblue',\n 'slateblue',\n 'slategray',\n 'slategrey',\n 'snow',\n 'springgreen',\n 'steelblue',\n 'tan',\n 'teal',\n 'thistle',\n 'tomato',\n 'turquoise',\n 'violet',\n 'wheat',\n 'white',\n 'whitesmoke',\n 'yellow',\n 'yellowgreen',\n]);\n\n/**\n * Properties that accept color values. Used to scope named-color checks so\n * string properties like `content` or `cursor` don't false-positive.\n */\nexport const COLOR_BEARING_PROPERTIES = new Set<string>([\n // Tasty enhanced properties\n 'fill',\n 'color',\n 'caretColor',\n 'accentColor',\n 'shadow',\n 'border',\n 'outline',\n 'fade',\n // CSS background\n 'background',\n 'backgroundColor',\n // CSS border colors\n 'borderColor',\n 'borderTopColor',\n 'borderRightColor',\n 'borderBottomColor',\n 'borderLeftColor',\n // CSS shadows\n 'boxShadow',\n 'textShadow',\n // CSS text decoration\n 'textDecorationColor',\n // CSS outline / misc\n 'outlineColor',\n 'scrollbarColor',\n 'columnRuleColor',\n // SVG\n 'stroke',\n 'stopColor',\n 'floodColor',\n 'lightingColor',\n]);\n\n/**\n * Properties where tasty does NOT expand a `$name` custom-property reference.\n *\n * These have their own style handlers that pass the value through verbatim, so\n * `fontFamily: '$font-sans'` emits a literal `font-family: $font-sans` — an\n * invalid declaration the browser drops. Rewriting `var(--font-sans)` to\n * `$font-sans` here silently deletes the style.\n *\n * Note that the colour properties (`color`, `fill`, `backgroundColor`) are in\n * this list but NOT in {@link PROPERTIES_WITHOUT_COLOR_TOKEN_EXPANSION}: they\n * expand `#token` and not `$name`. The two sets are genuinely different.\n *\n * Derived from the runtime, not by hand — `constants.round-trip.test.ts` rebuilds\n * both sets against the installed `@tenphi/tasty` and fails if either drifts.\n */\nexport const PROPERTIES_WITHOUT_CUSTOM_PROPERTY_EXPANSION = new Set([\n 'align',\n 'alignContent',\n 'alignItems',\n 'backgroundAttachment',\n 'backgroundClip',\n 'backgroundColor',\n 'backgroundOrigin',\n 'backgroundRepeat',\n 'color',\n 'display',\n 'fill',\n 'font',\n 'fontFamily',\n 'justify',\n 'justifyContent',\n 'justifyItems',\n 'overflow',\n 'placeContent',\n 'placeItems',\n 'textTransform',\n 'whiteSpace',\n]);\n\n/**\n * Properties where tasty does NOT expand a `#name` colour token.\n *\n * Mostly dimension and keyword properties: `fontSize: '#accent'` is meaningless,\n * so the handler leaves the value alone and the declaration is dropped. Suggesting\n * `#x` for a `var(--x-color)` inside one of these would break it.\n *\n * See {@link PROPERTIES_WITHOUT_CUSTOM_PROPERTY_EXPANSION} for why this is a\n * separate list rather than the same one.\n */\nexport const PROPERTIES_WITHOUT_COLOR_TOKEN_EXPANSION = new Set([\n 'align',\n 'alignContent',\n 'alignItems',\n 'backgroundAttachment',\n 'backgroundClip',\n 'backgroundOrigin',\n 'backgroundRepeat',\n 'display',\n 'font',\n 'fontFamily',\n 'fontSize',\n 'fontWeight',\n 'justify',\n 'justifyContent',\n 'justifyItems',\n 'letterSpacing',\n 'lineHeight',\n 'outlineOffset',\n 'overflow',\n 'placeContent',\n 'placeItems',\n 'textTransform',\n 'whiteSpace',\n]);\n"],"mappings":";;;;AAGA,MAAa,yBAAyB,IAAI,IAAI;CAC5C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;AAOF,MAAa,qBAAqB,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;AAQF,MAAa,6BAAqD;CAChE,eAAe;CACf,aAAa;CACb,iBAAiB;CAClB;;;;;AAMD,MAAa,uBAAuB,IAAI,IAAI;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,iBAAiB,I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CACjB,oBAAoB;CACpB,iBAAiB;CACjB,oBAAoB;CACpB,cAAc;CACd,iBAAiB;CACjB,aAAa;CACb,gBAAgB;CAChB,aAAa;CACb,gBAAgB;CAChB,aAAa;CACb,gBAAgB;CAChB,WAAW;CACX,cAAc;CACd,cAAc;CACd,iBAAiB;CACjB,cAAc;CACd,iBAAiB;CACjB,eAAe;CACf,kBAAkB;CAClB,qBAAqB;CACrB,yBAAyB;CACzB,kBAAkB;CAClB,sBAAsB;CACtB,eAAe;CACf,kBAAkB;CAClB,cAAc;CACd,kBAAkB;CAClB,UAAU;CACV,aAAa;CACb,YAAY;CACZ,eAAe;CACf,eAAe;CACf,kBAAkB;CACnB;;;;AAKD,MAAa,mBAAmB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,yBAAyB,CAAC,iBAAiB,uBAAuB;;;;AAK/E,MAAa,0BAA0B,IAAI,IAAI;CAC7C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,uBAAuB,IAAI,IAAI;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;AAOF,MAAa,mBAAmB,IAAI,IAAY;CAC9C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;AAMF,MAAa,2BAA2B,IAAI,IAAY;CAEtD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CAEA;CACA;CACA;CAEA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;;;;;;;;;AAiBF,MAAa,+CAA+C,IAAI,IAAI;CAClE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;;;;AAYF,MAAa,2CAA2C,IAAI,IAAI;CAC9D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Built-in tasty style properties that are always valid as style keys.\n */\nexport const KNOWN_TASTY_PROPERTIES = new Set([\n 'display',\n 'font',\n 'preset',\n 'hide',\n 'whiteSpace',\n 'opacity',\n 'transition',\n 'gridArea',\n 'order',\n 'gridColumn',\n 'gridRow',\n 'placeSelf',\n 'alignSelf',\n 'justifySelf',\n 'zIndex',\n 'margin',\n 'inset',\n 'position',\n 'padding',\n 'paddingInline',\n 'paddingBlock',\n 'overflow',\n 'scrollbar',\n 'textAlign',\n 'border',\n 'radius',\n 'shadow',\n 'outline',\n 'color',\n 'fill',\n 'fade',\n 'image',\n 'textTransform',\n 'fontWeight',\n 'fontStyle',\n 'width',\n 'height',\n 'flexBasis',\n 'flexGrow',\n 'flexShrink',\n 'flex',\n 'flow',\n 'placeItems',\n 'placeContent',\n 'alignItems',\n 'alignContent',\n 'justifyItems',\n 'justifyContent',\n 'align',\n 'justify',\n 'gap',\n 'columnGap',\n 'rowGap',\n 'gridColumns',\n 'gridRows',\n 'gridTemplate',\n 'gridAreas',\n 'recipe',\n 'textOverflow',\n 'textDecoration',\n 'animation',\n 'cursor',\n 'pointerEvents',\n 'userSelect',\n 'transform',\n 'transformOrigin',\n 'filter',\n 'backdropFilter',\n 'mixBlendMode',\n 'objectFit',\n 'objectPosition',\n 'resize',\n 'appearance',\n 'listStyle',\n 'listStyleType',\n 'content',\n 'boxSizing',\n 'verticalAlign',\n 'wordBreak',\n 'overflowWrap',\n 'hyphens',\n 'tabSize',\n 'direction',\n 'unicodeBidi',\n 'writingMode',\n 'lineClamp',\n 'aspectRatio',\n 'contain',\n 'container',\n 'containerType',\n 'containerName',\n 'interpolateSize',\n 'willChange',\n 'isolation',\n 'touchAction',\n 'scrollBehavior',\n 'scrollSnapType',\n 'scrollSnapAlign',\n 'caretColor',\n 'accentColor',\n 'colorScheme',\n]);\n\n/**\n * Special top-level keys that are valid but not regular style properties.\n *\n * These match the real CSS at-rule names Tasty emits, so they are kebab-case.\n */\nexport const SPECIAL_STYLE_KEYS = new Set([\n '@keyframes',\n '@property',\n '@font-face',\n '@counter-style',\n '@function',\n]);\n\n/**\n * At-rule style keys renamed in Tasty v3, mapped old spelling -> new.\n *\n * The v2 spellings were camelCase; v3 uses the CSS at-rule names Tasty already\n * emitted. Reported (and auto-fixed) so upgrading is mechanical.\n */\nexport const RENAMED_SPECIAL_STYLE_KEYS: Record<string, string> = {\n '@properties': '@property',\n '@fontFace': '@font-face',\n '@counterStyle': '@counter-style',\n};\n\n/**\n * CSS property names, camelCase, derived from `known-css-properties` — the\n * MDN/W3C-sourced dataset stylelint uses for `property-no-unknown`.\n *\n * Generated. Run `pnpm generate:css-properties` after bumping the dataset rather\n * than editing this list; `constants.css-properties.test.ts` fails on drift.\n *\n * Tasty renders any camelCase style key straight through to its kebab-case CSS\n * declaration (`maskSize` -> `mask-size`), so anything absent here is a false\n * positive from `known-property` on valid CSS — which is why the list is derived\n * from data instead of maintained by hand.\n *\n * The dataset also carries at-rule descriptors (`src`, `syntax`, `symbols`, `size`),\n * which are kept, as stylelint keeps them. They are only reachable as top-level\n * style keys, where the cost is a declaration browsers drop rather than a report —\n * and separating them would mean hand-maintaining the exclusion list this change\n * exists to delete. Inside an at-rule block nothing validates them: `known-property`\n * exempts every `@`-prefixed key and does not descend.\n */\nconst DATASET_CSS_PROPERTIES = [\n 'accelerator',\n 'accentColor',\n 'additiveSymbols',\n 'alignContent',\n 'alignItems',\n 'alignSelf',\n 'alignmentBaseline',\n 'all',\n 'alt',\n 'anchorName',\n 'anchorScope',\n 'animation',\n 'animationComposition',\n 'animationDelay',\n 'animationDirection',\n 'animationDuration',\n 'animationFillMode',\n 'animationIterationCount',\n 'animationName',\n 'animationPlayState',\n 'animationRange',\n 'animationRangeEnd',\n 'animationRangeStart',\n 'animationTimeline',\n 'animationTimingFunction',\n 'animationTrigger',\n 'animationTriggerBehavior',\n 'animationTriggerExitRange',\n 'animationTriggerExitRangeEnd',\n 'animationTriggerExitRangeStart',\n 'animationTriggerRange',\n 'animationTriggerRangeEnd',\n 'animationTriggerRangeStart',\n 'animationTriggerTimeline',\n 'appRegion',\n 'appearance',\n 'ascentOverride',\n 'aspectRatio',\n 'audioLevel',\n 'azimuth',\n 'backdropFilter',\n 'backfaceVisibility',\n 'background',\n 'backgroundAttachment',\n 'backgroundBlendMode',\n 'backgroundClip',\n 'backgroundColor',\n 'backgroundImage',\n 'backgroundOrigin',\n 'backgroundPosition',\n 'backgroundPositionX',\n 'backgroundPositionY',\n 'backgroundRepeat',\n 'backgroundRepeatX',\n 'backgroundRepeatY',\n 'backgroundSize',\n 'basePalette',\n 'baselineShift',\n 'baselineSource',\n 'behavior',\n 'blockEllipsis',\n 'blockSize',\n 'blockStep',\n 'blockStepAlign',\n 'blockStepInsert',\n 'blockStepRound',\n 'blockStepSize',\n 'bookmarkLabel',\n 'bookmarkLevel',\n 'bookmarkState',\n 'border',\n 'borderBlock',\n 'borderBlockColor',\n 'borderBlockEnd',\n 'borderBlockEndColor',\n 'borderBlockEndStyle',\n 'borderBlockEndWidth',\n 'borderBlockStart',\n 'borderBlockStartColor',\n 'borderBlockStartStyle',\n 'borderBlockStartWidth',\n 'borderBlockStyle',\n 'borderBlockWidth',\n 'borderBottom',\n 'borderBottomColor',\n 'borderBottomLeftRadius',\n 'borderBottomRightRadius',\n 'borderBottomStyle',\n 'borderBottomWidth',\n 'borderBoundary',\n 'borderCollapse',\n 'borderColor',\n 'borderEndEndRadius',\n 'borderEndStartRadius',\n 'borderImage',\n 'borderImageOutset',\n 'borderImageRepeat',\n 'borderImageSlice',\n 'borderImageSource',\n 'borderImageWidth',\n 'borderInline',\n 'borderInlineColor',\n 'borderInlineEnd',\n 'borderInlineEndColor',\n 'borderInlineEndStyle',\n 'borderInlineEndWidth',\n 'borderInlineStart',\n 'borderInlineStartColor',\n 'borderInlineStartStyle',\n 'borderInlineStartWidth',\n 'borderInlineStyle',\n 'borderInlineWidth',\n 'borderLeft',\n 'borderLeftColor',\n 'borderLeftStyle',\n 'borderLeftWidth',\n 'borderRadius',\n 'borderRight',\n 'borderRightColor',\n 'borderRightStyle',\n 'borderRightWidth',\n 'borderSpacing',\n 'borderStartEndRadius',\n 'borderStartStartRadius',\n 'borderStyle',\n 'borderTop',\n 'borderTopColor',\n 'borderTopLeftRadius',\n 'borderTopRightRadius',\n 'borderTopStyle',\n 'borderTopWidth',\n 'borderWidth',\n 'bottom',\n 'boxDecorationBreak',\n 'boxShadow',\n 'boxSizing',\n 'boxSnap',\n 'breakAfter',\n 'breakBefore',\n 'breakInside',\n 'bufferedRendering',\n 'captionSide',\n 'caret',\n 'caretAnimation',\n 'caretColor',\n 'caretShape',\n 'chains',\n 'clear',\n 'clip',\n 'clipPath',\n 'clipRule',\n 'color',\n 'colorAdjust',\n 'colorInterpolation',\n 'colorInterpolationFilters',\n 'colorProfile',\n 'colorRendering',\n 'colorScheme',\n 'columnCount',\n 'columnFill',\n 'columnGap',\n 'columnHeight',\n 'columnProgression',\n 'columnRule',\n 'columnRuleBreak',\n 'columnRuleColor',\n 'columnRuleOutset',\n 'columnRuleStyle',\n 'columnRuleWidth',\n 'columnSpan',\n 'columnWidth',\n 'columnWrap',\n 'columns',\n 'contain',\n 'containIntrinsicBlockSize',\n 'containIntrinsicHeight',\n 'containIntrinsicInlineSize',\n 'containIntrinsicSize',\n 'containIntrinsicWidth',\n 'container',\n 'containerName',\n 'containerType',\n 'content',\n 'contentVisibility',\n 'continue',\n 'counterIncrement',\n 'counterReset',\n 'counterSet',\n 'cue',\n 'cueAfter',\n 'cueBefore',\n 'cursor',\n 'cx',\n 'cy',\n 'd',\n 'descentOverride',\n 'direction',\n 'display',\n 'displayAlign',\n 'dominantBaseline',\n 'dynamicRangeLimit',\n 'elevation',\n 'emptyCells',\n 'enableBackground',\n 'epubCaptionSide',\n 'epubHyphens',\n 'epubTextCombine',\n 'epubTextEmphasis',\n 'epubTextEmphasisColor',\n 'epubTextEmphasisStyle',\n 'epubTextOrientation',\n 'epubTextTransform',\n 'epubWordBreak',\n 'epubWritingMode',\n 'fallback',\n 'fieldSizing',\n 'fill',\n 'fillBreak',\n 'fillColor',\n 'fillImage',\n 'fillOpacity',\n 'fillOrigin',\n 'fillPosition',\n 'fillRepeat',\n 'fillRule',\n 'fillSize',\n 'filter',\n 'flex',\n 'flexBasis',\n 'flexDirection',\n 'flexFlow',\n 'flexGrow',\n 'flexShrink',\n 'flexWrap',\n 'float',\n 'floatDefer',\n 'floatOffset',\n 'floatReference',\n 'floodColor',\n 'floodOpacity',\n 'flow',\n 'flowFrom',\n 'flowInto',\n 'font',\n 'fontDisplay',\n 'fontFamily',\n 'fontFeatureSettings',\n 'fontKerning',\n 'fontLanguageOverride',\n 'fontOpticalSizing',\n 'fontPalette',\n 'fontSize',\n 'fontSizeAdjust',\n 'fontStretch',\n 'fontStyle',\n 'fontSynthesis',\n 'fontSynthesisPosition',\n 'fontSynthesisSmallCaps',\n 'fontSynthesisStyle',\n 'fontSynthesisWeight',\n 'fontVariant',\n 'fontVariantAlternates',\n 'fontVariantCaps',\n 'fontVariantEastAsian',\n 'fontVariantEmoji',\n 'fontVariantLigatures',\n 'fontVariantNumeric',\n 'fontVariantPosition',\n 'fontVariationSettings',\n 'fontWeight',\n 'fontWidth',\n 'footnoteDisplay',\n 'footnotePolicy',\n 'forcedColorAdjust',\n 'gap',\n 'glyphOrientationHorizontal',\n 'glyphOrientationVertical',\n 'grid',\n 'gridArea',\n 'gridAutoColumns',\n 'gridAutoFlow',\n 'gridAutoRows',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnGap',\n 'gridColumnStart',\n 'gridGap',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowGap',\n 'gridRowStart',\n 'gridTemplate',\n 'gridTemplateAreas',\n 'gridTemplateColumns',\n 'gridTemplateRows',\n 'hangingPunctuation',\n 'height',\n 'hyphenateCharacter',\n 'hyphenateLimitChars',\n 'hyphenateLimitLast',\n 'hyphenateLimitLines',\n 'hyphenateLimitZone',\n 'hyphens',\n 'imageOrientation',\n 'imageRendering',\n 'imageResolution',\n 'imeMode',\n 'inherits',\n 'initialLetter',\n 'initialLetterAlign',\n 'initialLetterWrap',\n 'initialValue',\n 'inlineSize',\n 'inlineSizing',\n 'inputFormat',\n 'inputSecurity',\n 'inset',\n 'insetArea',\n 'insetBlock',\n 'insetBlockEnd',\n 'insetBlockStart',\n 'insetInline',\n 'insetInlineEnd',\n 'insetInlineStart',\n 'interactivity',\n 'interpolateSize',\n 'isolation',\n 'itemCross',\n 'itemDirection',\n 'itemFlow',\n 'itemPack',\n 'itemSlack',\n 'itemTrack',\n 'itemWrap',\n 'justifyContent',\n 'justifyItems',\n 'justifySelf',\n 'kerning',\n 'layoutFlow',\n 'layoutGrid',\n 'layoutGridChar',\n 'layoutGridLine',\n 'layoutGridMode',\n 'layoutGridType',\n 'left',\n 'letterSpacing',\n 'lightingColor',\n 'lineBreak',\n 'lineClamp',\n 'lineFitEdge',\n 'lineGapOverride',\n 'lineGrid',\n 'lineHeight',\n 'lineHeightStep',\n 'lineIncrement',\n 'linePadding',\n 'lineSnap',\n 'listStyle',\n 'listStyleImage',\n 'listStylePosition',\n 'listStyleType',\n 'margin',\n 'marginBlock',\n 'marginBlockEnd',\n 'marginBlockStart',\n 'marginBottom',\n 'marginBreak',\n 'marginInline',\n 'marginInlineEnd',\n 'marginInlineStart',\n 'marginLeft',\n 'marginRight',\n 'marginTop',\n 'marginTrim',\n 'marker',\n 'markerEnd',\n 'markerKnockoutLeft',\n 'markerKnockoutRight',\n 'markerMid',\n 'markerOffset',\n 'markerPattern',\n 'markerSegment',\n 'markerSide',\n 'markerStart',\n 'marks',\n 'mask',\n 'maskBorder',\n 'maskBorderMode',\n 'maskBorderOutset',\n 'maskBorderRepeat',\n 'maskBorderSlice',\n 'maskBorderSource',\n 'maskBorderWidth',\n 'maskClip',\n 'maskComposite',\n 'maskImage',\n 'maskMode',\n 'maskOrigin',\n 'maskPosition',\n 'maskPositionX',\n 'maskPositionY',\n 'maskRepeat',\n 'maskSize',\n 'maskSourceType',\n 'maskType',\n 'mathDepth',\n 'mathShift',\n 'mathStyle',\n 'maxBlockSize',\n 'maxHeight',\n 'maxInlineSize',\n 'maxLines',\n 'maxWidth',\n 'maxZoom',\n 'minBlockSize',\n 'minHeight',\n 'minInlineSize',\n 'minIntrinsicSizing',\n 'minWidth',\n 'minZoom',\n 'mixBlendMode',\n 'motion',\n 'motionOffset',\n 'motionPath',\n 'motionRotation',\n 'navDown',\n 'navIndex',\n 'navLeft',\n 'navRight',\n 'navUp',\n 'navigation',\n 'negative',\n 'objectFit',\n 'objectPosition',\n 'objectViewBox',\n 'offset',\n 'offsetAnchor',\n 'offsetBlockEnd',\n 'offsetBlockStart',\n 'offsetDistance',\n 'offsetInlineEnd',\n 'offsetInlineStart',\n 'offsetPath',\n 'offsetPosition',\n 'offsetRotate',\n 'offsetRotation',\n 'opacity',\n 'order',\n 'orientation',\n 'orphans',\n 'outline',\n 'outlineColor',\n 'outlineOffset',\n 'outlineStyle',\n 'outlineWidth',\n 'overflow',\n 'overflowAnchor',\n 'overflowBlock',\n 'overflowClipMargin',\n 'overflowClipMarginBlock',\n 'overflowClipMarginBlockEnd',\n 'overflowClipMarginBlockStart',\n 'overflowClipMarginBottom',\n 'overflowClipMarginInline',\n 'overflowClipMarginInlineEnd',\n 'overflowClipMarginInlineStart',\n 'overflowClipMarginLeft',\n 'overflowClipMarginRight',\n 'overflowClipMarginTop',\n 'overflowInline',\n 'overflowWrap',\n 'overflowX',\n 'overflowY',\n 'overlay',\n 'overrideColors',\n 'overscrollBehavior',\n 'overscrollBehaviorBlock',\n 'overscrollBehaviorInline',\n 'overscrollBehaviorX',\n 'overscrollBehaviorY',\n 'pad',\n 'padding',\n 'paddingBlock',\n 'paddingBlockEnd',\n 'paddingBlockStart',\n 'paddingBottom',\n 'paddingInline',\n 'paddingInlineEnd',\n 'paddingInlineStart',\n 'paddingLeft',\n 'paddingRight',\n 'paddingTop',\n 'page',\n 'pageBreakAfter',\n 'pageBreakBefore',\n 'pageBreakInside',\n 'pageOrientation',\n 'paintOrder',\n 'pause',\n 'pauseAfter',\n 'pauseBefore',\n 'penAction',\n 'perspective',\n 'perspectiveOrigin',\n 'perspectiveOriginX',\n 'perspectiveOriginY',\n 'pitch',\n 'pitchRange',\n 'placeContent',\n 'placeItems',\n 'placeSelf',\n 'playDuring',\n 'pointerEvents',\n 'position',\n 'positionAnchor',\n 'positionArea',\n 'positionTry',\n 'positionTryFallbacks',\n 'positionTryOptions',\n 'positionTryOrder',\n 'positionVisibility',\n 'prefix',\n 'printColorAdjust',\n 'propertyName',\n 'quotes',\n 'r',\n 'range',\n 'readingFlow',\n 'readingOrder',\n 'regionFragment',\n 'resize',\n 'rest',\n 'restAfter',\n 'restBefore',\n 'richness',\n 'right',\n 'rotate',\n 'rowGap',\n 'rowRule',\n 'rowRuleBreak',\n 'rowRuleColor',\n 'rowRuleOutset',\n 'rowRuleStyle',\n 'rowRuleWidth',\n 'rubyAlign',\n 'rubyMerge',\n 'rubyOverhang',\n 'rubyPosition',\n 'rule',\n 'ruleBreak',\n 'ruleColor',\n 'ruleOutset',\n 'rulePaintOrder',\n 'ruleStyle',\n 'ruleWidth',\n 'running',\n 'rx',\n 'ry',\n 'scale',\n 'scrollBehavior',\n 'scrollInitialTarget',\n 'scrollMargin',\n 'scrollMarginBlock',\n 'scrollMarginBlockEnd',\n 'scrollMarginBlockStart',\n 'scrollMarginBottom',\n 'scrollMarginInline',\n 'scrollMarginInlineEnd',\n 'scrollMarginInlineStart',\n 'scrollMarginLeft',\n 'scrollMarginRight',\n 'scrollMarginTop',\n 'scrollMarkerGroup',\n 'scrollPadding',\n 'scrollPaddingBlock',\n 'scrollPaddingBlockEnd',\n 'scrollPaddingBlockStart',\n 'scrollPaddingBottom',\n 'scrollPaddingInline',\n 'scrollPaddingInlineEnd',\n 'scrollPaddingInlineStart',\n 'scrollPaddingLeft',\n 'scrollPaddingRight',\n 'scrollPaddingTop',\n 'scrollSnapAlign',\n 'scrollSnapCoordinate',\n 'scrollSnapDestination',\n 'scrollSnapMargin',\n 'scrollSnapMarginBottom',\n 'scrollSnapMarginLeft',\n 'scrollSnapMarginRight',\n 'scrollSnapMarginTop',\n 'scrollSnapPointsX',\n 'scrollSnapPointsY',\n 'scrollSnapStop',\n 'scrollSnapType',\n 'scrollSnapTypeX',\n 'scrollSnapTypeY',\n 'scrollStartTarget',\n 'scrollTargetGroup',\n 'scrollTimeline',\n 'scrollTimelineAxis',\n 'scrollTimelineName',\n 'scrollbar3dLightColor',\n 'scrollbar3dlightColor',\n 'scrollbarArrowColor',\n 'scrollbarBaseColor',\n 'scrollbarColor',\n 'scrollbarDarkShadowColor',\n 'scrollbarDarkshadowColor',\n 'scrollbarFaceColor',\n 'scrollbarGutter',\n 'scrollbarHighlightColor',\n 'scrollbarShadowColor',\n 'scrollbarTrackColor',\n 'scrollbarWidth',\n 'shapeImageThreshold',\n 'shapeInside',\n 'shapeMargin',\n 'shapeOutside',\n 'shapeRendering',\n 'size',\n 'sizeAdjust',\n 'sliderOrientation',\n 'snapHeight',\n 'solidColor',\n 'solidOpacity',\n 'spatialNavigationAction',\n 'spatialNavigationContain',\n 'spatialNavigationFunction',\n 'speak',\n 'speakAs',\n 'speakHeader',\n 'speakNumeral',\n 'speakPunctuation',\n 'speechRate',\n 'src',\n 'stopColor',\n 'stopOpacity',\n 'stress',\n 'stringSet',\n 'stroke',\n 'strokeAlign',\n 'strokeAlignment',\n 'strokeBreak',\n 'strokeColor',\n 'strokeDashCorner',\n 'strokeDashJustify',\n 'strokeDashadjust',\n 'strokeDasharray',\n 'strokeDashcorner',\n 'strokeDashoffset',\n 'strokeImage',\n 'strokeLinecap',\n 'strokeLinejoin',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeOrigin',\n 'strokePosition',\n 'strokeRepeat',\n 'strokeSize',\n 'strokeWidth',\n 'suffix',\n 'supportedColorSchemes',\n 'symbols',\n 'syntax',\n 'system',\n 'tabSize',\n 'tableLayout',\n 'textAlign',\n 'textAlignAll',\n 'textAlignLast',\n 'textAnchor',\n 'textAutospace',\n 'textBox',\n 'textBoxEdge',\n 'textBoxTrim',\n 'textCombineUpright',\n 'textDecoration',\n 'textDecorationBlink',\n 'textDecorationColor',\n 'textDecorationLine',\n 'textDecorationLineThrough',\n 'textDecorationNone',\n 'textDecorationOverline',\n 'textDecorationSkip',\n 'textDecorationSkipBox',\n 'textDecorationSkipInk',\n 'textDecorationSkipInset',\n 'textDecorationSkipSelf',\n 'textDecorationSkipSpaces',\n 'textDecorationStyle',\n 'textDecorationThickness',\n 'textDecorationTrim',\n 'textDecorationUnderline',\n 'textEmphasis',\n 'textEmphasisColor',\n 'textEmphasisPosition',\n 'textEmphasisSkip',\n 'textEmphasisStyle',\n 'textGroupAlign',\n 'textIndent',\n 'textJustify',\n 'textJustifyTrim',\n 'textKashida',\n 'textKashidaSpace',\n 'textLineThrough',\n 'textLineThroughColor',\n 'textLineThroughMode',\n 'textLineThroughStyle',\n 'textLineThroughWidth',\n 'textOrientation',\n 'textOverflow',\n 'textOverline',\n 'textOverlineColor',\n 'textOverlineMode',\n 'textOverlineStyle',\n 'textOverlineWidth',\n 'textRendering',\n 'textShadow',\n 'textSizeAdjust',\n 'textSpacing',\n 'textSpacingTrim',\n 'textTransform',\n 'textUnderline',\n 'textUnderlineColor',\n 'textUnderlineMode',\n 'textUnderlineOffset',\n 'textUnderlinePosition',\n 'textUnderlineStyle',\n 'textUnderlineWidth',\n 'textWrap',\n 'textWrapMode',\n 'textWrapStyle',\n 'timelineScope',\n 'top',\n 'touchAction',\n 'touchActionDelay',\n 'transform',\n 'transformBox',\n 'transformOrigin',\n 'transformOriginX',\n 'transformOriginY',\n 'transformOriginZ',\n 'transformStyle',\n 'transition',\n 'transitionBehavior',\n 'transitionDelay',\n 'transitionDuration',\n 'transitionProperty',\n 'transitionTimingFunction',\n 'translate',\n 'types',\n 'ucAltSkin',\n 'ucSkin',\n 'unicodeBidi',\n 'unicodeRange',\n 'userSelect',\n 'userZoom',\n 'vectorEffect',\n 'verticalAlign',\n 'viewTimeline',\n 'viewTimelineAxis',\n 'viewTimelineInset',\n 'viewTimelineName',\n 'viewTransitionClass',\n 'viewTransitionGroup',\n 'viewTransitionName',\n 'viewportFill',\n 'viewportFillOpacity',\n 'viewportFit',\n 'visibility',\n 'voiceBalance',\n 'voiceDuration',\n 'voiceFamily',\n 'voicePitch',\n 'voiceRange',\n 'voiceRate',\n 'voiceStress',\n 'voiceVolume',\n 'volume',\n 'whiteSpace',\n 'whiteSpaceCollapse',\n 'whiteSpaceTrim',\n 'widows',\n 'width',\n 'willChange',\n 'wordBreak',\n 'wordSpaceTransform',\n 'wordSpacing',\n 'wordWrap',\n 'wrapAfter',\n 'wrapBefore',\n 'wrapFlow',\n 'wrapInside',\n 'wrapThrough',\n 'writingMode',\n 'x',\n 'y',\n 'zIndex',\n 'zoom',\n];\n\n/**\n * Properties that ship in browsers or sit in a spec, but have not landed in\n * `known-css-properties` yet. Hand-maintained, and pruned as the dataset catches\n * up — the guard test fails on any entry the dataset already covers.\n */\nexport const EMERGING_CSS_PROPERTIES = [\n // CSS Borders and Box Decorations 4 — squircles and notched corners, shipped in\n // Chromium 139.\n 'cornerShape',\n 'cornerTopShape',\n 'cornerRightShape',\n 'cornerBottomShape',\n 'cornerLeftShape',\n 'cornerBlockStartShape',\n 'cornerBlockEndShape',\n 'cornerInlineStartShape',\n 'cornerInlineEndShape',\n 'cornerTopLeftShape',\n 'cornerTopRightShape',\n 'cornerBottomRightShape',\n 'cornerBottomLeftShape',\n 'cornerStartStartShape',\n 'cornerStartEndShape',\n 'cornerEndStartShape',\n 'cornerEndEndShape',\n];\n\n/**\n * Every CSS property `known-property` accepts as a camelCase style key.\n */\nexport const KNOWN_CSS_PROPERTIES = new Set([\n ...DATASET_CSS_PROPERTIES,\n ...EMERGING_CSS_PROPERTIES,\n]);\n\n/**\n * Built-in custom units recognized by the tasty parser.\n */\nexport const BUILT_IN_UNITS = new Set(['x', 'r', 'cr', 'bw', 'ow', 'lh', 'sf']);\n\n/**\n * Standard CSS units (always valid).\n */\nexport const CSS_UNITS = new Set([\n 'px',\n 'em',\n 'rem',\n '%',\n 'vw',\n 'vh',\n 'vmin',\n 'vmax',\n 'ch',\n 'ex',\n 'cm',\n 'mm',\n 'in',\n 'pt',\n 'pc',\n 'fr',\n 'deg',\n 'rad',\n 'turn',\n 'grad',\n 's',\n 'ms',\n 'dpi',\n 'dpcm',\n 'dppx',\n 'svw',\n 'svh',\n 'lvw',\n 'lvh',\n 'dvw',\n 'dvh',\n 'cqw',\n 'cqh',\n 'cqi',\n 'cqb',\n 'cqmin',\n 'cqmax',\n 'cap',\n 'ic',\n 'rlh',\n 'vi',\n 'vb',\n]);\n\n/**\n * Properties that accept `true` as a value (means \"use default\").\n */\nexport const BOOLEAN_TRUE_PROPERTIES = new Set([\n 'border',\n 'radius',\n 'padding',\n 'margin',\n 'gap',\n 'fill',\n 'color',\n 'shadow',\n 'outline',\n 'inset',\n 'width',\n 'height',\n // `fade: true` falls back to `calc(2 * var(--gap))` — a token-following\n // default no explicit value can express, so it is genuinely useful.\n 'fade',\n 'hide',\n 'preset',\n 'font',\n 'scrollbar',\n]);\n\n/**\n * Directional modifiers and which properties accept them.\n */\nexport const DIRECTIONAL_MODIFIERS: Record<string, Set<string>> = {\n border: new Set(['top', 'right', 'bottom', 'left']),\n radius: new Set([\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n ]),\n padding: new Set(['top', 'right', 'bottom', 'left']),\n margin: new Set(['top', 'right', 'bottom', 'left']),\n fade: new Set(['top', 'right', 'bottom', 'left']),\n scrollMargin: new Set(['top', 'right', 'bottom', 'left']),\n inset: new Set(['top', 'right', 'bottom', 'left', 'dock']),\n};\n\n/**\n * Properties where a group naming directions carries exactly **one** value.\n *\n * Tasty v3 dropped the positional multi-value form for these: values and\n * modifiers are bucketed separately per comma group, so `'2x 4x top right'` and\n * `'2x top 4x right'` were the same input and the pairing depended on modifier\n * order. Per-side values now come from comma groups.\n *\n * Deliberately excludes `border` and `radius`. A `border` group legitimately\n * carries width + style + color, and a `radius` group can carry two values with\n * `leaf`/`backleaf`; neither takes the positional-per-side form, so neither is\n * subject to the rule.\n */\nexport const SINGLE_VALUE_DIRECTIONAL_PROPERTIES = new Set([\n 'padding',\n 'margin',\n 'inset',\n 'scrollMargin',\n 'fade',\n]);\n\n/**\n * Position names a 4-value box maps onto, in source order.\n */\nexport const BOX_SIDES = ['top', 'right', 'bottom', 'left'] as const;\nexport const BOX_CORNERS = [\n 'top-left',\n 'top-right',\n 'bottom-right',\n 'bottom-left',\n] as const;\n\nexport interface DirectionalBoxConfig {\n /**\n * The token that marks an unset position — dropping it from the shorthand\n * leaves the emitted CSS unchanged. This is the CSS initial value of the\n * longhand, which is not always `0`: `inset` initialises to `auto`, so a `0`\n * there is a real offset the shorthand must not drop.\n */\n identity: string;\n /** Modifier names for each of the four positions, in source order. */\n positions: readonly string[];\n /**\n * Whether `eslint --fix` may apply the rewrite. False when the rewrite is\n * still an improvement but changes what the browser renders, so a human has\n * to opt in.\n */\n fixable: boolean;\n /**\n * Set when the 4-value form is not interpreted per-position at all, so the\n * current output is wrong rather than merely verbose. Surfaced in the report.\n */\n note?: string;\n}\n\n/**\n * Properties whose 4-value box syntax has a directional-shorthand equivalent.\n *\n * `radius` uses corner names rather than sides: a directional modifier\n * addresses the corner *pair* along an edge, so only `top-left` & co. can\n * express a single corner (requires `@tenphi/tasty` >= 2.10).\n */\nexport const DIRECTIONAL_BOX: Record<string, DirectionalBoxConfig> = {\n margin: { identity: '0', positions: BOX_SIDES, fixable: true },\n padding: { identity: '0', positions: BOX_SIDES, fixable: true },\n inset: { identity: 'auto', positions: BOX_SIDES, fixable: true },\n radius: { identity: '0', positions: BOX_CORNERS, fixable: true },\n fade: { identity: '0', positions: BOX_SIDES, fixable: true },\n // Four `border` tokens parse as a single border value (width/style/color),\n // not as a box: `border: '0 0 1bw 0'` emits `border: 0 solid …` — no border\n // on any side. The directional form is what the author meant, but applying\n // it changes rendering, so it stays a manual fix.\n border: {\n identity: '0',\n positions: BOX_SIDES,\n fixable: false,\n note: 'four border tokens parse as one border value, so the current style sets no border at all',\n },\n};\n\n/**\n * Properties that support a `dock` modifier — pin one edge and span its full\n * length. Lets a 4-value box with a single `identity` side collapse, e.g.\n * `inset: 'auto 0 0 0'` -> `inset: '0 bottom dock'`.\n * Requires `@tenphi/tasty` >= 2.10.\n */\nexport const DOCK_PROPERTIES = new Set(['inset']);\n\n/**\n * Valid radius shape keywords.\n */\nexport const RADIUS_SHAPES = new Set(['round', 'ellipse', 'leaf', 'backleaf']);\n\n/**\n * Known semantic transition names.\n */\nexport const SEMANTIC_TRANSITIONS = new Set([\n 'fade',\n 'fill',\n 'border',\n 'radius',\n 'shadow',\n 'preset',\n 'gap',\n 'theme',\n 'color',\n 'outline',\n 'dimension',\n 'flow',\n 'inset',\n 'text',\n 'opacity',\n 'translate',\n 'rotate',\n 'scale',\n 'filter',\n 'image',\n 'background',\n 'width',\n 'height',\n 'zIndex',\n]);\n\n/**\n * Mapping of native CSS properties to tasty shorthand alternatives.\n */\nexport const SHORTHAND_MAPPING: Record<\n string,\n { property: string; hint: string; safeFix?: boolean }\n> = {\n backgroundColor: { property: 'fill', hint: \"fill: '...'\", safeFix: true },\n borderColor: { property: 'border', hint: \"border: '...'\" },\n borderWidth: { property: 'border', hint: \"border: '...'\" },\n borderStyle: { property: 'border', hint: \"border: '...'\" },\n borderTop: { property: 'border', hint: \"border: '... top'\" },\n borderRight: { property: 'border', hint: \"border: '... right'\" },\n borderBottom: { property: 'border', hint: \"border: '... bottom'\" },\n borderLeft: { property: 'border', hint: \"border: '... left'\" },\n borderRadius: { property: 'radius', hint: \"radius: '...'\", safeFix: true },\n maxWidth: { property: 'width', hint: \"width: 'max ...'\" },\n minWidth: { property: 'width', hint: \"width: 'min ...'\" },\n maxHeight: { property: 'height', hint: \"height: 'max ...'\" },\n minHeight: { property: 'height', hint: \"height: 'min ...'\" },\n flexDirection: { property: 'flow', hint: \"flow: '...'\" },\n flexWrap: { property: 'flow', hint: \"flow: '...'\" },\n flexFlow: { property: 'flow', hint: \"flow: '...'\" },\n gridAutoFlow: { property: 'flow', hint: \"flow: '...'\" },\n outlineOffset: { property: 'outline', hint: \"outline: '... / offset'\" },\n paddingTop: { property: 'padding', hint: \"padding: '... top'\" },\n paddingRight: { property: 'padding', hint: \"padding: '... right'\" },\n paddingBottom: { property: 'padding', hint: \"padding: '... bottom'\" },\n paddingLeft: { property: 'padding', hint: \"padding: '... left'\" },\n marginTop: { property: 'margin', hint: \"margin: '... top'\" },\n marginRight: { property: 'margin', hint: \"margin: '... right'\" },\n marginBottom: { property: 'margin', hint: \"margin: '... bottom'\" },\n marginLeft: { property: 'margin', hint: \"margin: '... left'\" },\n fontSize: { property: 'preset', hint: \"preset: '...'\" },\n fontWeight: {\n property: 'preset',\n hint: \"preset: 'name / strong' (with strong modifier)\",\n },\n lineHeight: {\n property: 'preset',\n hint: \"preset: 'name / tight' (with tight modifier)\",\n },\n boxShadow: { property: 'shadow', hint: \"shadow: '...'\" },\n backgroundImage: { property: 'image', hint: \"image: '...'\" },\n fontFamily: { property: 'font', hint: \"font: '...'\" },\n fontStyle: {\n property: 'preset',\n hint: \"preset: 'name / italic' (with italic modifier)\",\n },\n letterSpacing: { property: 'preset', hint: \"preset: '...'\" },\n textTransform: { property: 'preset', hint: \"preset: '...'\" },\n flexGap: { property: 'gap', hint: \"gap: '...'\" },\n scrollbarWidth: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n scrollbarColor: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n scrollbarGutter: { property: 'scrollbar', hint: \"scrollbar: '...'\" },\n gridTemplateColumns: {\n property: 'gridColumns',\n hint: \"gridColumns: '...'\",\n },\n gridTemplateRows: { property: 'gridRows', hint: \"gridRows: '...'\" },\n gridTemplateAreas: { property: 'gridAreas', hint: \"gridAreas: '...'\" },\n top: { property: 'inset', hint: \"inset: '... top'\" },\n right: { property: 'inset', hint: \"inset: '... right'\" },\n bottom: { property: 'inset', hint: \"inset: '... bottom'\" },\n left: { property: 'inset', hint: \"inset: '... left'\" },\n outlineColor: { property: 'outline', hint: \"outline: '...'\" },\n outlineWidth: { property: 'outline', hint: \"outline: '...'\" },\n outlineStyle: { property: 'outline', hint: \"outline: '...'\" },\n lineClamp: {\n property: 'textOverflow',\n hint: \"textOverflow: 'ellipsis / {lines}'\",\n },\n};\n\n/**\n * CSS shorthands whose *longhands* are the preferred Tasty form — the reverse\n * of `SHORTHAND_MAPPING`.\n *\n * `flex` is lossy in a way the longhands are not: it resets the two components\n * you did not write to values that are not their CSS initial. `flex: '0'`\n * expands to `flex-grow: 0; flex-shrink: 1; flex-basis: 0%`, so it cannot\n * express \"do not shrink\" (`flexShrink: 0`) at all, and it silently changes\n * `flex-basis`. Writing the longhands keeps each component independent, which\n * also lets them carry separate state maps.\n */\nexport const LONGHAND_MAPPING: Record<\n string,\n { longhands: string[]; hint: string }\n> = {\n flex: {\n longhands: ['flexGrow', 'flexShrink', 'flexBasis'],\n hint: 'flexGrow / flexShrink / flexBasis',\n },\n};\n\n/**\n * CSS transition property names mapped to Tasty semantic transition names.\n */\nexport const TRANSITION_SEMANTIC_MAPPING: Record<string, string> = {\n backgroundColor: 'fill',\n 'background-color': 'fill',\n backgroundImage: 'image',\n 'background-image': 'image',\n borderRadius: 'radius',\n 'border-radius': 'radius',\n borderColor: 'border',\n 'border-color': 'border',\n borderWidth: 'border',\n 'border-width': 'border',\n borderStyle: 'border',\n 'border-style': 'border',\n boxShadow: 'shadow',\n 'box-shadow': 'shadow',\n outlineColor: 'outline',\n 'outline-color': 'outline',\n outlineWidth: 'outline',\n 'outline-width': 'outline',\n outlineOffset: 'outline',\n 'outline-offset': 'outline',\n gridTemplateColumns: 'gridColumns',\n 'grid-template-columns': 'gridColumns',\n gridTemplateRows: 'gridRows',\n 'grid-template-rows': 'gridRows',\n flexDirection: 'flow',\n 'flex-direction': 'flow',\n gridAutoFlow: 'flow',\n 'grid-auto-flow': 'flow',\n fontSize: 'preset',\n 'font-size': 'preset',\n lineHeight: 'preset',\n 'line-height': 'preset',\n letterSpacing: 'preset',\n 'letter-spacing': 'preset',\n};\n\n/**\n * Known preset modifiers.\n */\nexport const PRESET_MODIFIERS = new Set([\n 'strong',\n 'bold',\n 'italic',\n 'icon',\n 'tight',\n]);\n\n/**\n * Default import sources for tasty.\n */\nexport const DEFAULT_IMPORT_SOURCES = ['@tenphi/tasty', '@tenphi/tasty/static'];\n\n/**\n * Built-in state prefixes that are always valid (not aliases).\n */\nexport const BUILT_IN_STATE_PREFIXES = new Set([\n '@media',\n '@root',\n '@parent',\n '@own',\n '@supports',\n '@starting',\n '@keyframes',\n '@property',\n '@font-face',\n '@counter-style',\n '@function',\n]);\n\n/**\n * Known CSS pseudo-classes.\n */\nexport const KNOWN_PSEUDO_CLASSES = new Set([\n ':hover',\n ':focus',\n ':focus-visible',\n ':focus-within',\n ':active',\n ':visited',\n ':link',\n ':checked',\n ':disabled',\n ':enabled',\n ':empty',\n ':first-child',\n ':last-child',\n ':first-of-type',\n ':last-of-type',\n ':only-child',\n ':only-of-type',\n ':root',\n ':target',\n ':valid',\n ':invalid',\n ':required',\n ':optional',\n ':read-only',\n ':read-write',\n ':placeholder-shown',\n ':autofill',\n ':default',\n ':indeterminate',\n ':in-range',\n ':out-of-range',\n ':any-link',\n ':local-link',\n ':is',\n ':not',\n ':where',\n ':has',\n ':nth-child',\n ':nth-last-child',\n ':nth-of-type',\n ':nth-last-of-type',\n '::before',\n '::after',\n '::placeholder',\n '::selection',\n '::first-line',\n '::first-letter',\n '::marker',\n '::backdrop',\n]);\n\n/**\n * CSS named colors (level 1–4) that should be replaced by `#color` tokens.\n * `transparent` and `currentcolor` are excluded — they have their own token\n * suggestions (`#clear`, `#current`) handled by `prefer-custom-property-syntax`.\n */\nexport const NAMED_CSS_COLORS = new Set<string>([\n 'aliceblue',\n 'antiquewhite',\n 'aqua',\n 'aquamarine',\n 'azure',\n 'beige',\n 'bisque',\n 'black',\n 'blanchedalmond',\n 'blue',\n 'blueviolet',\n 'brown',\n 'burlywood',\n 'cadetblue',\n 'chartreuse',\n 'chocolate',\n 'coral',\n 'cornflowerblue',\n 'cornsilk',\n 'crimson',\n 'cyan',\n 'darkblue',\n 'darkcyan',\n 'darkgoldenrod',\n 'darkgray',\n 'darkgreen',\n 'darkgrey',\n 'darkkhaki',\n 'darkmagenta',\n 'darkolivegreen',\n 'darkorange',\n 'darkorchid',\n 'darkred',\n 'darksalmon',\n 'darkseagreen',\n 'darkslateblue',\n 'darkslategray',\n 'darkslategrey',\n 'darkturquoise',\n 'darkviolet',\n 'deeppink',\n 'deepskyblue',\n 'dimgray',\n 'dimgrey',\n 'dodgerblue',\n 'firebrick',\n 'floralwhite',\n 'forestgreen',\n 'fuchsia',\n 'gainsboro',\n 'ghostwhite',\n 'gold',\n 'goldenrod',\n 'gray',\n 'green',\n 'greenyellow',\n 'grey',\n 'honeydew',\n 'hotpink',\n 'indianred',\n 'indigo',\n 'ivory',\n 'khaki',\n 'lavender',\n 'lavenderblush',\n 'lawngreen',\n 'lemonchiffon',\n 'lightblue',\n 'lightcoral',\n 'lightcyan',\n 'lightgoldenrodyellow',\n 'lightgray',\n 'lightgreen',\n 'lightgrey',\n 'lightpink',\n 'lightsalmon',\n 'lightseagreen',\n 'lightskyblue',\n 'lightslategray',\n 'lightslategrey',\n 'lightsteelblue',\n 'lightyellow',\n 'lime',\n 'limegreen',\n 'linen',\n 'magenta',\n 'maroon',\n 'mediumaquamarine',\n 'mediumblue',\n 'mediumorchid',\n 'mediumpurple',\n 'mediumseagreen',\n 'mediumslateblue',\n 'mediumspringgreen',\n 'mediumturquoise',\n 'mediumvioletred',\n 'midnightblue',\n 'mintcream',\n 'mistyrose',\n 'moccasin',\n 'navajowhite',\n 'navy',\n 'oldlace',\n 'olive',\n 'olivedrab',\n 'orange',\n 'orangered',\n 'orchid',\n 'palegoldenrod',\n 'palegreen',\n 'paleturquoise',\n 'palevioletred',\n 'papayawhip',\n 'peachpuff',\n 'peru',\n 'pink',\n 'plum',\n 'powderblue',\n 'purple',\n 'rebeccapurple',\n 'red',\n 'rosybrown',\n 'royalblue',\n 'saddlebrown',\n 'salmon',\n 'sandybrown',\n 'seagreen',\n 'seashell',\n 'sienna',\n 'silver',\n 'skyblue',\n 'slateblue',\n 'slategray',\n 'slategrey',\n 'snow',\n 'springgreen',\n 'steelblue',\n 'tan',\n 'teal',\n 'thistle',\n 'tomato',\n 'turquoise',\n 'violet',\n 'wheat',\n 'white',\n 'whitesmoke',\n 'yellow',\n 'yellowgreen',\n]);\n\n/**\n * Properties that accept color values. Used to scope named-color checks so\n * string properties like `content` or `cursor` don't false-positive.\n */\nexport const COLOR_BEARING_PROPERTIES = new Set<string>([\n // Tasty enhanced properties\n 'fill',\n 'color',\n 'caretColor',\n 'accentColor',\n 'shadow',\n 'border',\n 'outline',\n 'fade',\n // CSS background\n 'background',\n 'backgroundColor',\n // CSS border colors\n 'borderColor',\n 'borderTopColor',\n 'borderRightColor',\n 'borderBottomColor',\n 'borderLeftColor',\n // CSS shadows\n 'boxShadow',\n 'textShadow',\n // CSS text decoration\n 'textDecorationColor',\n // CSS outline / misc\n 'outlineColor',\n 'scrollbarColor',\n 'columnRuleColor',\n // SVG\n 'stroke',\n 'stopColor',\n 'floodColor',\n 'lightingColor',\n]);\n\n/**\n * Properties where tasty does NOT expand a `$name` custom-property reference.\n *\n * These have their own style handlers that pass the value through verbatim, so\n * `fontFamily: '$font-sans'` emits a literal `font-family: $font-sans` — an\n * invalid declaration the browser drops. Rewriting `var(--font-sans)` to\n * `$font-sans` here silently deletes the style.\n *\n * Note that the colour properties (`color`, `fill`, `backgroundColor`) are in\n * this list but NOT in {@link PROPERTIES_WITHOUT_COLOR_TOKEN_EXPANSION}: they\n * expand `#token` and not `$name`. The two sets are genuinely different.\n *\n * Derived from the runtime, not by hand — `constants.round-trip.test.ts` rebuilds\n * both sets against the installed `@tenphi/tasty` and fails if either drifts.\n */\nexport const PROPERTIES_WITHOUT_CUSTOM_PROPERTY_EXPANSION = new Set([\n 'align',\n 'alignContent',\n 'alignItems',\n 'backgroundAttachment',\n 'backgroundClip',\n 'backgroundColor',\n 'backgroundOrigin',\n 'backgroundRepeat',\n 'color',\n 'display',\n 'fill',\n 'font',\n 'fontFamily',\n 'justify',\n 'justifyContent',\n 'justifyItems',\n 'overflow',\n 'placeContent',\n 'placeItems',\n 'textTransform',\n 'whiteSpace',\n]);\n\n/**\n * Properties where tasty does NOT expand a `#name` colour token.\n *\n * Mostly dimension and keyword properties: `fontSize: '#accent'` is meaningless,\n * so the handler leaves the value alone and the declaration is dropped. Suggesting\n * `#x` for a `var(--x-color)` inside one of these would break it.\n *\n * See {@link PROPERTIES_WITHOUT_CUSTOM_PROPERTY_EXPANSION} for why this is a\n * separate list rather than the same one.\n */\nexport const PROPERTIES_WITHOUT_COLOR_TOKEN_EXPANSION = new Set([\n 'align',\n 'alignContent',\n 'alignItems',\n 'backgroundAttachment',\n 'backgroundClip',\n 'backgroundOrigin',\n 'backgroundRepeat',\n 'display',\n 'font',\n 'fontFamily',\n 'fontSize',\n 'fontWeight',\n 'justify',\n 'justifyContent',\n 'justifyItems',\n 'letterSpacing',\n 'lineHeight',\n 'outlineOffset',\n 'overflow',\n 'placeContent',\n 'placeItems',\n 'textTransform',\n 'whiteSpace',\n]);\n"],"mappings":";;;;AAGA,MAAa,yBAAyB,IAAI,IAAI;CAC5C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;AAOF,MAAa,qBAAqB,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;AAQF,MAAa,6BAAqD;CAChE,eAAe;CACf,aAAa;CACb,iBAAiB;CAClB;;;;;;;;;;;;;;;;;;;;AAqBD,MAAM,yBAAyB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;AAOD,MAAa,0BAA0B;CAGrC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CA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;;;;;;;;;;;;AAaD,MAAa,mBAGT,EACF,MAAM;CACJ,WAAW;EAAC;EAAY;EAAc;EAAY;CAClD,MAAM;CACP,EACF;;;;AAKD,MAAa,8BAAsD;CACjE,iBAAiB;CACjB,oBAAoB;CACpB,iBAAiB;CACjB,oBAAoB;CACpB,cAAc;CACd,iBAAiB;CACjB,aAAa;CACb,gBAAgB;CAChB,aAAa;CACb,gBAAgB;CAChB,aAAa;CACb,gBAAgB;CAChB,WAAW;CACX,cAAc;CACd,cAAc;CACd,iBAAiB;CACjB,cAAc;CACd,iBAAiB;CACjB,eAAe;CACf,kBAAkB;CAClB,qBAAqB;CACrB,yBAAyB;CACzB,kBAAkB;CAClB,sBAAsB;CACtB,eAAe;CACf,kBAAkB;CAClB,cAAc;CACd,kBAAkB;CAClB,UAAU;CACV,aAAa;CACb,YAAY;CACZ,eAAe;CACf,eAAe;CACf,kBAAkB;CACnB;;;;AAKD,MAAa,mBAAmB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,yBAAyB,CAAC,iBAAiB,uBAAuB;;;;AAK/E,MAAa,0BAA0B,IAAI,IAAI;CAC7C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,uBAAuB,IAAI,IAAI;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;AAOF,MAAa,mBAAmB,IAAI,IAAY;CAC9C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;AAMF,MAAa,2BAA2B,IAAI,IAAY;CAEtD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CACA;CACA;CACA;CACA;CAEA;CACA;CAEA;CAEA;CACA;CACA;CAEA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;;;;;;;;;AAiBF,MAAa,+CAA+C,IAAI,IAAI;CAClE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;;;;AAYF,MAAa,2CAA2C,IAAI,IAAI;CAC9D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC"}
|
package/dist/context.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DEFAULT_IMPORT_SOURCES, SPECIAL_STYLE_KEYS } from "./constants.js";
|
|
1
|
+
import { DEFAULT_IMPORT_SOURCES, KNOWN_CSS_PROPERTIES, KNOWN_TASTY_PROPERTIES, SPECIAL_STYLE_KEYS } from "./constants.js";
|
|
2
2
|
import { loadConfig } from "./config.js";
|
|
3
3
|
import { getKeyName } from "./utils.js";
|
|
4
4
|
|
|
@@ -52,6 +52,44 @@ function referencesStylesType(node) {
|
|
|
52
52
|
}
|
|
53
53
|
return false;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Whether a key could plausibly be a tasty style key.
|
|
57
|
+
*
|
|
58
|
+
* Covers every top-level shape tasty accepts: a style property, a sub-element
|
|
59
|
+
* (capitalised), an at-rule or state/custom-property/colour key (`@`, `&`, `$`,
|
|
60
|
+
* `#`), and the default-state key.
|
|
61
|
+
*/
|
|
62
|
+
function isPlausibleStyleKey(key) {
|
|
63
|
+
if (key === "" || key === "_") return true;
|
|
64
|
+
if (/^[A-Z]/.test(key)) return true;
|
|
65
|
+
if (/^[@&$#]/.test(key)) return true;
|
|
66
|
+
if (SPECIAL_STYLE_KEYS.has(key)) return true;
|
|
67
|
+
return KNOWN_TASTY_PROPERTIES.has(key) || KNOWN_CSS_PROPERTIES.has(key);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Whether an object is a map of named CSS blocks rather than a tasty styles object.
|
|
71
|
+
*
|
|
72
|
+
* The shape is unmistakable — `{ table: {…}, th: {…}, td: {…} }`, `{ root: {…},
|
|
73
|
+
* toolbar: {…} }` — and it is what a React inline-style map looks like when it
|
|
74
|
+
* carries no type annotation to opt it out. Every key is a block name that is not a
|
|
75
|
+
* style key, and every value is an object.
|
|
76
|
+
*
|
|
77
|
+
* Requiring *every* value to be an object literal is what keeps this from swallowing
|
|
78
|
+
* the case it would hurt most: `const styles = { colour: 'red' }` has a string value,
|
|
79
|
+
* so it is not treated as a block map and `known-property` still reports the typo.
|
|
80
|
+
* Otherwise the rule that catches a misspelled property would be silenced by the
|
|
81
|
+
* misspelling.
|
|
82
|
+
*/
|
|
83
|
+
function isNamedCssBlockMap(node) {
|
|
84
|
+
if (node.properties.length === 0) return false;
|
|
85
|
+
for (const prop of node.properties) {
|
|
86
|
+
if (prop.type !== "Property" || prop.computed) return false;
|
|
87
|
+
const key = getKeyName(prop.key);
|
|
88
|
+
if (key === null || isPlausibleStyleKey(key)) return false;
|
|
89
|
+
if (prop.value.type !== "ObjectExpression") return false;
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
55
93
|
const TASTY_FUNCTION_NAMES = new Set([
|
|
56
94
|
"tasty",
|
|
57
95
|
"tastyStatic",
|
|
@@ -162,7 +200,7 @@ var TastyContext = class {
|
|
|
162
200
|
if (/^[A-Z][A-Z0-9_]*$/.test(name)) return false;
|
|
163
201
|
const annotated = this.stylesTypeAnnotation(current);
|
|
164
202
|
if (annotated !== null) return annotated;
|
|
165
|
-
if (name === "styles" || name.endsWith("Styles")) return
|
|
203
|
+
if (name === "styles" || name.endsWith("Styles")) return !(targetNode.type === "ObjectExpression" && isNamedCssBlockMap(targetNode));
|
|
166
204
|
return false;
|
|
167
205
|
}
|
|
168
206
|
/**
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","names":[],"sources":["../src/context.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport type { RuleContext } from '@typescript-eslint/utils/ts-eslint';\nimport type { ResolvedConfig } from './types.js';\nimport { loadConfig } from './config.js';\nimport { DEFAULT_IMPORT_SOURCES, SPECIAL_STYLE_KEYS } from './constants.js';\nimport { getKeyName } from './utils.js';\n\n/**\n * AST selectors that match ObjectExpressions in all known tasty style contexts:\n * call sites, variable declarations, satisfies/as expressions.\n */\nexport const STYLE_OBJECT_SELECTORS = [\n 'CallExpression ObjectExpression',\n 'VariableDeclarator > ObjectExpression',\n 'VariableDeclarator > TSSatisfiesExpression > ObjectExpression',\n 'VariableDeclarator > TSAsExpression > ObjectExpression',\n // `<Block styles={{…}} />`. Safe to match on the prop name alone: React's own\n // prop is `style`, singular, so a plural `styles` JSX prop is a Tasty\n // convention.\n \"JSXAttribute[name.name='styles'] > JSXExpressionContainer > ObjectExpression\",\n // A Storybook story's `args.styles`. Deliberately this specific rather than\n // matching any `styles` key: plenty of unrelated libraries take a `styles`\n // option object, and a bare key carries no evidence it is Tasty's. Story files\n // are where a lot of style code is authored and neither the call-site nor the\n // variable-name heuristic reaches them — the enclosing variable is named after\n // the story, and there is no Tasty call.\n // Superset of the `args.styles` shape; `isStylesPropertyValue` is the real\n // gate, so both `styles` and `'styles'` key forms are covered.\n 'Property > ObjectExpression > Property > ObjectExpression',\n] as const;\n\n/**\n * Creates a record of ESLint listeners that all point to the same handler,\n * one entry per style-object AST selector.\n */\nexport function styleObjectListeners(\n handler: (node: TSESTree.ObjectExpression) => void,\n): Record<string, (node: TSESTree.ObjectExpression) => void> {\n const listeners: Record<string, (node: TSESTree.ObjectExpression) => void> =\n {};\n\n // Selectors overlap — `tasty({ styles: {…} })` matches both\n // `CallExpression ObjectExpression` and the `styles` key selector — so the\n // handler must run at most once per object, or every rule double-reports.\n const visited = new WeakSet<TSESTree.ObjectExpression>();\n const once = (node: TSESTree.ObjectExpression) => {\n if (visited.has(node)) return;\n visited.add(node);\n handler(node);\n };\n\n for (const selector of STYLE_OBJECT_SELECTORS) {\n listeners[selector] = once;\n }\n\n return listeners;\n}\n\nexport interface TastyImport {\n localName: string;\n importedName: string;\n source: string;\n}\n\n/**\n * Whether a type annotation names tasty's `Styles` anywhere inside it.\n *\n * Walks the annotation rather than matching only the outermost reference, so a\n * wrapped tasty type (`Styles | undefined`, `Record<string, Styles>`,\n * `{ root: Styles }`) is recognised while `CSSProperties` in the same positions is\n * not. Deliberately name-based: the plugin has no type checker, and requiring one\n * would make every rule type-aware.\n */\nfunction referencesStylesType(node: TSESTree.TypeNode): boolean {\n const stack: TSESTree.Node[] = [node];\n\n while (stack.length) {\n const current = stack.pop()!;\n\n if (\n current.type === 'TSTypeReference' &&\n current.typeName.type === 'Identifier' &&\n /^Styles$/i.test(current.typeName.name)\n ) {\n return true;\n }\n\n for (const value of Object.values(\n current as unknown as Record<string, unknown>,\n )) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && 'type' in item) {\n stack.push(item as TSESTree.Node);\n }\n }\n } else if (value && typeof value === 'object' && 'type' in value) {\n // Skip `parent` — it points back up the tree and would loop forever.\n if (value !== (current as TSESTree.Node).parent) {\n stack.push(value as TSESTree.Node);\n }\n }\n }\n }\n\n return false;\n}\n\nconst TASTY_FUNCTION_NAMES = new Set([\n 'tasty',\n 'tastyStatic',\n 'useStyles',\n 'useGlobalStyles',\n 'configure',\n]);\n\n/**\n * Context tracker for a single file's lint pass.\n * Tracks which imports come from tasty and provides\n * helpers to determine if a node is in a tasty style context.\n */\nexport class TastyContext {\n readonly config: ResolvedConfig;\n private imports = new Map<string, TastyImport>();\n private importSources: Set<string>;\n\n constructor(\n private context: RuleContext<string, unknown[]>,\n config?: ResolvedConfig,\n ) {\n this.config = config ?? loadConfig(context.filename);\n this.importSources = new Set([\n ...DEFAULT_IMPORT_SOURCES,\n ...this.config.importSources,\n ]);\n }\n\n trackImport(node: TSESTree.ImportDeclaration): void {\n const source = node.source.value;\n if (!this.importSources.has(source)) return;\n\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportSpecifier') {\n const importedName =\n specifier.imported.type === 'Identifier'\n ? specifier.imported.name\n : specifier.imported.value;\n if (TASTY_FUNCTION_NAMES.has(importedName)) {\n this.imports.set(specifier.local.name, {\n localName: specifier.local.name,\n importedName,\n source,\n });\n }\n }\n }\n }\n\n getImport(localName: string): TastyImport | undefined {\n return this.imports.get(localName);\n }\n\n isTastyCall(node: TSESTree.CallExpression): TastyImport | undefined {\n if (node.callee.type !== 'Identifier') return undefined;\n return this.imports.get(node.callee.name);\n }\n\n /**\n * Determines whether an object expression is a tasty style object\n * by walking up the AST to find a recognized call expression.\n */\n isStyleObject(node: TSESTree.ObjectExpression): boolean {\n return this.getStyleContext(node) !== null;\n }\n\n getStyleContext(node: TSESTree.Node): {\n type: 'tasty' | 'tastyStatic' | 'useStyles' | 'useGlobalStyles';\n isStaticCall: boolean;\n isSelectorMode: boolean;\n isExtending: boolean;\n } | null {\n // Sub-element objects inherit their parent style object's context\n if (node.type === 'ObjectExpression') {\n const parent = node.parent;\n if (parent?.type === 'Property' && !parent.computed) {\n const key = getKeyName(parent.key);\n if (key && /^[A-Z]/.test(key)) {\n const grandparent = parent.parent;\n if (grandparent?.type === 'ObjectExpression') {\n return this.getStyleContext(grandparent);\n }\n }\n }\n }\n\n // An object assigned to a `styles` key (or a `styles` JSX prop) is a style\n // object on its own terms — no enclosing tasty call or `styles`-ish variable\n // name required. Checked before the walk, which would otherwise climb past it\n // to an unrelated call or declaration and reject the whole thing.\n if (node.type === 'ObjectExpression' && this.isStylesPropertyValue(node)) {\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n\n let current: TSESTree.Node | undefined = node;\n\n while (current) {\n if (current.type === 'CallExpression') {\n const imp = this.isTastyCall(current);\n if (!imp) return null;\n\n const name = imp.importedName;\n const isStaticCall = name === 'tastyStatic';\n\n if (name === 'tasty') {\n return this.getTastyCallContext(current, node);\n }\n\n if (name === 'tastyStatic') {\n return this.getTastyStaticCallContext(current, node);\n }\n\n if (name === 'useStyles') {\n if (current.arguments[0] === node) {\n return {\n type: 'useStyles',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n }\n\n if (name === 'useGlobalStyles') {\n if (current.arguments[1] === node) {\n return {\n type: 'useGlobalStyles',\n isStaticCall,\n isSelectorMode: true,\n isExtending: false,\n };\n }\n }\n\n return null;\n }\n\n if (this.isStyleVariableDeclaration(current, node)) {\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n\n current = current.parent;\n }\n\n return null;\n }\n\n private isStyleVariableDeclaration(\n current: TSESTree.Node,\n targetNode: TSESTree.Node,\n ): boolean {\n if (\n current.type !== 'VariableDeclarator' ||\n current.id.type !== 'Identifier'\n ) {\n return false;\n }\n\n let init: TSESTree.Node | null | undefined = current.init;\n while (\n init?.type === 'TSAsExpression' ||\n init?.type === 'TSSatisfiesExpression' ||\n init?.type === 'TSTypeAssertion' ||\n init?.type === 'TSNonNullExpression'\n ) {\n init = (init as TSESTree.TSAsExpression).expression;\n }\n\n if (init !== targetNode) return false;\n\n const name = current.id.name;\n\n if (/^[A-Z][A-Z0-9_]*$/.test(name)) return false;\n\n // An explicit type annotation is authoritative, in both directions. The name\n // heuristic below is a guess; a declared type is the author stating what the\n // object is, so it wins.\n //\n // This matters because the rewrites these rules offer are only valid *inside*\n // tasty: `#purple.05` and `$font-sans` are correct tasty declarations and\n // meaningless as raw CSS. A `const styles: Record<string, CSSProperties>`\n // handed to React's `style={…}` was matched on name alone, so its plain CSS\n // longhands were reported as tasty violations — and `--fix` rewrote real\n // `var(--shadow-sm-color)` to `#shadow-sm`, which nothing resolves there, so\n // the browser dropped the declaration.\n const annotated = this.stylesTypeAnnotation(current);\n\n if (annotated !== null) return annotated;\n\n // Only `styles` and `*Styles` count. The singular `style` is conventionally\n // a DOM inline-style object (`el.style`, `CSSProperties`, `setStyle(el, …)`)\n // holding raw CSS longhands, not tasty syntax — matching it reported those\n // longhands as tasty violations.\n if (name === 'styles' || name.endsWith('Styles')) return true;\n\n return false;\n }\n\n /**\n * Verdict from the declared type: `true` tasty, `false` explicitly not, `null`\n * when there is no annotation to go on and the caller should fall back to the\n * name.\n *\n * A `Styles` reference anywhere in the annotation counts, so wrappers like\n * `Styles | undefined` and `Record<string, Styles>` opt in — while\n * `CSSProperties`, `Record<string, CSSProperties>` and an inline literal of\n * them opt out.\n */\n private stylesTypeAnnotation(\n node: TSESTree.VariableDeclarator,\n ): boolean | null {\n const annotation = node.id.typeAnnotation?.typeAnnotation;\n\n if (!annotation) return null;\n\n return referencesStylesType(annotation);\n }\n\n private getTastyCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ) {\n const args = call.arguments;\n\n // tasty({ styles: { ... } }) or tasty(Component, { styles: { ... } })\n const optionsArg =\n args.length >= 2 && args[0].type !== 'ObjectExpression'\n ? args[1]\n : args[0];\n\n if (\n optionsArg?.type === 'ObjectExpression' &&\n this.isInsideStylesProperty(optionsArg, targetNode)\n ) {\n return {\n type: 'tasty' as const,\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: args.length >= 2 && args[0].type !== 'ObjectExpression',\n };\n }\n\n // Check if inside variants\n if (\n optionsArg?.type === 'ObjectExpression' &&\n this.isInsideVariantsProperty(optionsArg, targetNode)\n ) {\n return {\n type: 'tasty' as const,\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n\n return null;\n }\n\n private getTastyStaticCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ) {\n const args = call.arguments;\n\n // tastyStatic({ ... })\n if (args.length === 1 && args[0] === targetNode) {\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n\n // tastyStatic(base, { ... }) or tastyStatic('selector', { ... })\n if (args.length === 2 && args[1] === targetNode) {\n const isSelectorMode = args[0].type === 'Literal';\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode,\n isExtending: !isSelectorMode,\n };\n }\n\n return null;\n }\n\n private isInsideStylesProperty(\n optionsObj: TSESTree.ObjectExpression,\n targetNode: TSESTree.Node,\n ): boolean {\n for (const prop of optionsObj.properties) {\n if (\n prop.type === 'Property' &&\n prop.key.type === 'Identifier' &&\n prop.key.name === 'styles' &&\n prop.value === targetNode\n ) {\n return true;\n }\n }\n return false;\n }\n\n private isInsideVariantsProperty(\n optionsObj: TSESTree.ObjectExpression,\n targetNode: TSESTree.Node,\n ): boolean {\n for (const prop of optionsObj.properties) {\n if (\n prop.type === 'Property' &&\n prop.key.type === 'Identifier' &&\n prop.key.name === 'variants' &&\n prop.value.type === 'ObjectExpression'\n ) {\n for (const variantProp of prop.value.properties) {\n if (\n variantProp.type === 'Property' &&\n variantProp.value === targetNode\n ) {\n return true;\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Whether this object is a `styles` JSX prop value or a Storybook `args.styles`.\n *\n * Both are unambiguous enough to stand on their own without an import-tracked\n * call or a `styles`-ish variable name. A bare `styles` key elsewhere is not —\n * see the selector list for why.\n */\n isStylesPropertyValue(node: TSESTree.ObjectExpression): boolean {\n const parent = node.parent;\n\n if (parent?.type === 'Property' && !parent.computed) {\n if (getKeyName(parent.key) !== 'styles') return false;\n\n // Only inside `args: { … }`.\n const argsObject = parent.parent;\n const argsProperty =\n argsObject?.type === 'ObjectExpression' ? argsObject.parent : undefined;\n\n return (\n argsProperty?.type === 'Property' &&\n !argsProperty.computed &&\n getKeyName(argsProperty.key) === 'args'\n );\n }\n\n if (parent?.type === 'JSXExpressionContainer') {\n const attribute = parent.parent;\n\n return (\n attribute?.type === 'JSXAttribute' &&\n attribute.name.type === 'JSXIdentifier' &&\n attribute.name.name === 'styles'\n );\n }\n\n return false;\n }\n\n /**\n * Checks if a property value node is a state mapping object\n * (i.e., an object where keys are state expressions and values are style values).\n */\n isStateMap(\n node: TSESTree.ObjectExpression,\n parentProperty: TSESTree.Property,\n ): boolean {\n const keyName = getKeyName(parentProperty.key);\n if (keyName === null) return false;\n\n // If the key starts with uppercase, it's a sub-element, not a state map\n if (/^[A-Z]/.test(keyName)) return false;\n\n // Special keys are not state maps\n // At-rule blocks are not state maps — their object values are descriptor maps.\n if (SPECIAL_STYLE_KEYS.has(keyName)) return false;\n\n // If the object has keys that look like state expressions, it's a state map.\n // A lone `_` (the fallback floor) or `''` (the default) is enough — both are\n // already covered by the string-literal / identifier branches below.\n return node.properties.some((prop) => {\n if (prop.type !== 'Property') return false;\n if (prop.key.type === 'Literal' && prop.key.value === '') return true;\n if (prop.key.type === 'Identifier') return true;\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') {\n return true;\n }\n return false;\n });\n }\n\n /**\n * Checks if a key represents a sub-element (starts with uppercase).\n */\n isSubElementKey(key: string): boolean {\n return /^[A-Z]/.test(key);\n }\n\n /**\n * Checks if a key represents a nested selector (starts with &).\n */\n isNestedSelectorKey(key: string): boolean {\n return key.startsWith('&');\n }\n\n /**\n * Checks if a key is a custom CSS property definition ($name or $$name).\n */\n isCustomPropertyKey(key: string): boolean {\n return key.startsWith('$');\n }\n\n /**\n * Checks if a key is a color token definition (#name or ##name).\n */\n isColorTokenKey(key: string): boolean {\n return key.startsWith('#');\n }\n\n /**\n * Checks if a key is a special @ property (@keyframes, @property, ...).\n */\n isSpecialKey(key: string): boolean {\n return key.startsWith('@');\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../src/context.ts"],"sourcesContent":["import type { TSESTree } from '@typescript-eslint/utils';\nimport type { RuleContext } from '@typescript-eslint/utils/ts-eslint';\nimport type { ResolvedConfig } from './types.js';\nimport { loadConfig } from './config.js';\nimport {\n DEFAULT_IMPORT_SOURCES,\n KNOWN_CSS_PROPERTIES,\n KNOWN_TASTY_PROPERTIES,\n SPECIAL_STYLE_KEYS,\n} from './constants.js';\nimport { getKeyName } from './utils.js';\n\n/**\n * AST selectors that match ObjectExpressions in all known tasty style contexts:\n * call sites, variable declarations, satisfies/as expressions.\n */\nexport const STYLE_OBJECT_SELECTORS = [\n 'CallExpression ObjectExpression',\n 'VariableDeclarator > ObjectExpression',\n 'VariableDeclarator > TSSatisfiesExpression > ObjectExpression',\n 'VariableDeclarator > TSAsExpression > ObjectExpression',\n // `<Block styles={{…}} />`. Safe to match on the prop name alone: React's own\n // prop is `style`, singular, so a plural `styles` JSX prop is a Tasty\n // convention.\n \"JSXAttribute[name.name='styles'] > JSXExpressionContainer > ObjectExpression\",\n // A Storybook story's `args.styles`. Deliberately this specific rather than\n // matching any `styles` key: plenty of unrelated libraries take a `styles`\n // option object, and a bare key carries no evidence it is Tasty's. Story files\n // are where a lot of style code is authored and neither the call-site nor the\n // variable-name heuristic reaches them — the enclosing variable is named after\n // the story, and there is no Tasty call.\n // Superset of the `args.styles` shape; `isStylesPropertyValue` is the real\n // gate, so both `styles` and `'styles'` key forms are covered.\n 'Property > ObjectExpression > Property > ObjectExpression',\n] as const;\n\n/**\n * Creates a record of ESLint listeners that all point to the same handler,\n * one entry per style-object AST selector.\n */\nexport function styleObjectListeners(\n handler: (node: TSESTree.ObjectExpression) => void,\n): Record<string, (node: TSESTree.ObjectExpression) => void> {\n const listeners: Record<string, (node: TSESTree.ObjectExpression) => void> =\n {};\n\n // Selectors overlap — `tasty({ styles: {…} })` matches both\n // `CallExpression ObjectExpression` and the `styles` key selector — so the\n // handler must run at most once per object, or every rule double-reports.\n const visited = new WeakSet<TSESTree.ObjectExpression>();\n const once = (node: TSESTree.ObjectExpression) => {\n if (visited.has(node)) return;\n visited.add(node);\n handler(node);\n };\n\n for (const selector of STYLE_OBJECT_SELECTORS) {\n listeners[selector] = once;\n }\n\n return listeners;\n}\n\nexport interface TastyImport {\n localName: string;\n importedName: string;\n source: string;\n}\n\n/**\n * Whether a type annotation names tasty's `Styles` anywhere inside it.\n *\n * Walks the annotation rather than matching only the outermost reference, so a\n * wrapped tasty type (`Styles | undefined`, `Record<string, Styles>`,\n * `{ root: Styles }`) is recognised while `CSSProperties` in the same positions is\n * not. Deliberately name-based: the plugin has no type checker, and requiring one\n * would make every rule type-aware.\n */\nfunction referencesStylesType(node: TSESTree.TypeNode): boolean {\n const stack: TSESTree.Node[] = [node];\n\n while (stack.length) {\n const current = stack.pop()!;\n\n if (\n current.type === 'TSTypeReference' &&\n current.typeName.type === 'Identifier' &&\n /^Styles$/i.test(current.typeName.name)\n ) {\n return true;\n }\n\n for (const value of Object.values(\n current as unknown as Record<string, unknown>,\n )) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && 'type' in item) {\n stack.push(item as TSESTree.Node);\n }\n }\n } else if (value && typeof value === 'object' && 'type' in value) {\n // Skip `parent` — it points back up the tree and would loop forever.\n if (value !== (current as TSESTree.Node).parent) {\n stack.push(value as TSESTree.Node);\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Whether a key could plausibly be a tasty style key.\n *\n * Covers every top-level shape tasty accepts: a style property, a sub-element\n * (capitalised), an at-rule or state/custom-property/colour key (`@`, `&`, `$`,\n * `#`), and the default-state key.\n */\nfunction isPlausibleStyleKey(key: string): boolean {\n if (key === '' || key === '_') return true;\n if (/^[A-Z]/.test(key)) return true;\n if (/^[@&$#]/.test(key)) return true;\n if (SPECIAL_STYLE_KEYS.has(key)) return true;\n\n return KNOWN_TASTY_PROPERTIES.has(key) || KNOWN_CSS_PROPERTIES.has(key);\n}\n\n/**\n * Whether an object is a map of named CSS blocks rather than a tasty styles object.\n *\n * The shape is unmistakable — `{ table: {…}, th: {…}, td: {…} }`, `{ root: {…},\n * toolbar: {…} }` — and it is what a React inline-style map looks like when it\n * carries no type annotation to opt it out. Every key is a block name that is not a\n * style key, and every value is an object.\n *\n * Requiring *every* value to be an object literal is what keeps this from swallowing\n * the case it would hurt most: `const styles = { colour: 'red' }` has a string value,\n * so it is not treated as a block map and `known-property` still reports the typo.\n * Otherwise the rule that catches a misspelled property would be silenced by the\n * misspelling.\n */\nfunction isNamedCssBlockMap(node: TSESTree.ObjectExpression): boolean {\n if (node.properties.length === 0) return false;\n\n for (const prop of node.properties) {\n if (prop.type !== 'Property' || prop.computed) return false;\n\n const key = getKeyName(prop.key);\n\n if (key === null || isPlausibleStyleKey(key)) return false;\n if (prop.value.type !== 'ObjectExpression') return false;\n }\n\n return true;\n}\n\nconst TASTY_FUNCTION_NAMES = new Set([\n 'tasty',\n 'tastyStatic',\n 'useStyles',\n 'useGlobalStyles',\n 'configure',\n]);\n\n/**\n * Context tracker for a single file's lint pass.\n * Tracks which imports come from tasty and provides\n * helpers to determine if a node is in a tasty style context.\n */\nexport class TastyContext {\n readonly config: ResolvedConfig;\n private imports = new Map<string, TastyImport>();\n private importSources: Set<string>;\n\n constructor(\n private context: RuleContext<string, unknown[]>,\n config?: ResolvedConfig,\n ) {\n this.config = config ?? loadConfig(context.filename);\n this.importSources = new Set([\n ...DEFAULT_IMPORT_SOURCES,\n ...this.config.importSources,\n ]);\n }\n\n trackImport(node: TSESTree.ImportDeclaration): void {\n const source = node.source.value;\n if (!this.importSources.has(source)) return;\n\n for (const specifier of node.specifiers) {\n if (specifier.type === 'ImportSpecifier') {\n const importedName =\n specifier.imported.type === 'Identifier'\n ? specifier.imported.name\n : specifier.imported.value;\n if (TASTY_FUNCTION_NAMES.has(importedName)) {\n this.imports.set(specifier.local.name, {\n localName: specifier.local.name,\n importedName,\n source,\n });\n }\n }\n }\n }\n\n getImport(localName: string): TastyImport | undefined {\n return this.imports.get(localName);\n }\n\n isTastyCall(node: TSESTree.CallExpression): TastyImport | undefined {\n if (node.callee.type !== 'Identifier') return undefined;\n return this.imports.get(node.callee.name);\n }\n\n /**\n * Determines whether an object expression is a tasty style object\n * by walking up the AST to find a recognized call expression.\n */\n isStyleObject(node: TSESTree.ObjectExpression): boolean {\n return this.getStyleContext(node) !== null;\n }\n\n getStyleContext(node: TSESTree.Node): {\n type: 'tasty' | 'tastyStatic' | 'useStyles' | 'useGlobalStyles';\n isStaticCall: boolean;\n isSelectorMode: boolean;\n isExtending: boolean;\n } | null {\n // Sub-element objects inherit their parent style object's context\n if (node.type === 'ObjectExpression') {\n const parent = node.parent;\n if (parent?.type === 'Property' && !parent.computed) {\n const key = getKeyName(parent.key);\n if (key && /^[A-Z]/.test(key)) {\n const grandparent = parent.parent;\n if (grandparent?.type === 'ObjectExpression') {\n return this.getStyleContext(grandparent);\n }\n }\n }\n }\n\n // An object assigned to a `styles` key (or a `styles` JSX prop) is a style\n // object on its own terms — no enclosing tasty call or `styles`-ish variable\n // name required. Checked before the walk, which would otherwise climb past it\n // to an unrelated call or declaration and reject the whole thing.\n if (node.type === 'ObjectExpression' && this.isStylesPropertyValue(node)) {\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n\n let current: TSESTree.Node | undefined = node;\n\n while (current) {\n if (current.type === 'CallExpression') {\n const imp = this.isTastyCall(current);\n if (!imp) return null;\n\n const name = imp.importedName;\n const isStaticCall = name === 'tastyStatic';\n\n if (name === 'tasty') {\n return this.getTastyCallContext(current, node);\n }\n\n if (name === 'tastyStatic') {\n return this.getTastyStaticCallContext(current, node);\n }\n\n if (name === 'useStyles') {\n if (current.arguments[0] === node) {\n return {\n type: 'useStyles',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n }\n\n if (name === 'useGlobalStyles') {\n if (current.arguments[1] === node) {\n return {\n type: 'useGlobalStyles',\n isStaticCall,\n isSelectorMode: true,\n isExtending: false,\n };\n }\n }\n\n return null;\n }\n\n if (this.isStyleVariableDeclaration(current, node)) {\n return {\n type: 'tasty',\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n\n current = current.parent;\n }\n\n return null;\n }\n\n private isStyleVariableDeclaration(\n current: TSESTree.Node,\n targetNode: TSESTree.Node,\n ): boolean {\n if (\n current.type !== 'VariableDeclarator' ||\n current.id.type !== 'Identifier'\n ) {\n return false;\n }\n\n let init: TSESTree.Node | null | undefined = current.init;\n while (\n init?.type === 'TSAsExpression' ||\n init?.type === 'TSSatisfiesExpression' ||\n init?.type === 'TSTypeAssertion' ||\n init?.type === 'TSNonNullExpression'\n ) {\n init = (init as TSESTree.TSAsExpression).expression;\n }\n\n if (init !== targetNode) return false;\n\n const name = current.id.name;\n\n if (/^[A-Z][A-Z0-9_]*$/.test(name)) return false;\n\n // An explicit type annotation is authoritative, in both directions. The name\n // heuristic below is a guess; a declared type is the author stating what the\n // object is, so it wins.\n //\n // This matters because the rewrites these rules offer are only valid *inside*\n // tasty: `#purple.05` and `$font-sans` are correct tasty declarations and\n // meaningless as raw CSS. A `const styles: Record<string, CSSProperties>`\n // handed to React's `style={…}` was matched on name alone, so its plain CSS\n // longhands were reported as tasty violations — and `--fix` rewrote real\n // `var(--shadow-sm-color)` to `#shadow-sm`, which nothing resolves there, so\n // the browser dropped the declaration.\n const annotated = this.stylesTypeAnnotation(current);\n\n if (annotated !== null) return annotated;\n\n // Only `styles` and `*Styles` count. The singular `style` is conventionally\n // a DOM inline-style object (`el.style`, `CSSProperties`, `setStyle(el, …)`)\n // holding raw CSS longhands, not tasty syntax — matching it reported those\n // longhands as tasty violations.\n if (name === 'styles' || name.endsWith('Styles')) {\n // The name is the weakest evidence there is, so let an unmistakable shape\n // overrule it. Without an annotation to go on, a map of named CSS blocks was\n // reported as tasty — `known-property` on every HTML tag name, each block read\n // as a state map — and `--fix` offered rewrites that are only valid inside\n // tasty.\n return !(\n targetNode.type === 'ObjectExpression' && isNamedCssBlockMap(targetNode)\n );\n }\n\n return false;\n }\n\n /**\n * Verdict from the declared type: `true` tasty, `false` explicitly not, `null`\n * when there is no annotation to go on and the caller should fall back to the\n * name.\n *\n * A `Styles` reference anywhere in the annotation counts, so wrappers like\n * `Styles | undefined` and `Record<string, Styles>` opt in — while\n * `CSSProperties`, `Record<string, CSSProperties>` and an inline literal of\n * them opt out.\n */\n private stylesTypeAnnotation(\n node: TSESTree.VariableDeclarator,\n ): boolean | null {\n const annotation = node.id.typeAnnotation?.typeAnnotation;\n\n if (!annotation) return null;\n\n return referencesStylesType(annotation);\n }\n\n private getTastyCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ) {\n const args = call.arguments;\n\n // tasty({ styles: { ... } }) or tasty(Component, { styles: { ... } })\n const optionsArg =\n args.length >= 2 && args[0].type !== 'ObjectExpression'\n ? args[1]\n : args[0];\n\n if (\n optionsArg?.type === 'ObjectExpression' &&\n this.isInsideStylesProperty(optionsArg, targetNode)\n ) {\n return {\n type: 'tasty' as const,\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: args.length >= 2 && args[0].type !== 'ObjectExpression',\n };\n }\n\n // Check if inside variants\n if (\n optionsArg?.type === 'ObjectExpression' &&\n this.isInsideVariantsProperty(optionsArg, targetNode)\n ) {\n return {\n type: 'tasty' as const,\n isStaticCall: false,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n\n return null;\n }\n\n private getTastyStaticCallContext(\n call: TSESTree.CallExpression,\n targetNode: TSESTree.Node,\n ) {\n const args = call.arguments;\n\n // tastyStatic({ ... })\n if (args.length === 1 && args[0] === targetNode) {\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode: false,\n isExtending: false,\n };\n }\n\n // tastyStatic(base, { ... }) or tastyStatic('selector', { ... })\n if (args.length === 2 && args[1] === targetNode) {\n const isSelectorMode = args[0].type === 'Literal';\n return {\n type: 'tastyStatic' as const,\n isStaticCall: true,\n isSelectorMode,\n isExtending: !isSelectorMode,\n };\n }\n\n return null;\n }\n\n private isInsideStylesProperty(\n optionsObj: TSESTree.ObjectExpression,\n targetNode: TSESTree.Node,\n ): boolean {\n for (const prop of optionsObj.properties) {\n if (\n prop.type === 'Property' &&\n prop.key.type === 'Identifier' &&\n prop.key.name === 'styles' &&\n prop.value === targetNode\n ) {\n return true;\n }\n }\n return false;\n }\n\n private isInsideVariantsProperty(\n optionsObj: TSESTree.ObjectExpression,\n targetNode: TSESTree.Node,\n ): boolean {\n for (const prop of optionsObj.properties) {\n if (\n prop.type === 'Property' &&\n prop.key.type === 'Identifier' &&\n prop.key.name === 'variants' &&\n prop.value.type === 'ObjectExpression'\n ) {\n for (const variantProp of prop.value.properties) {\n if (\n variantProp.type === 'Property' &&\n variantProp.value === targetNode\n ) {\n return true;\n }\n }\n }\n }\n return false;\n }\n\n /**\n * Whether this object is a `styles` JSX prop value or a Storybook `args.styles`.\n *\n * Both are unambiguous enough to stand on their own without an import-tracked\n * call or a `styles`-ish variable name. A bare `styles` key elsewhere is not —\n * see the selector list for why.\n */\n isStylesPropertyValue(node: TSESTree.ObjectExpression): boolean {\n const parent = node.parent;\n\n if (parent?.type === 'Property' && !parent.computed) {\n if (getKeyName(parent.key) !== 'styles') return false;\n\n // Only inside `args: { … }`.\n const argsObject = parent.parent;\n const argsProperty =\n argsObject?.type === 'ObjectExpression' ? argsObject.parent : undefined;\n\n return (\n argsProperty?.type === 'Property' &&\n !argsProperty.computed &&\n getKeyName(argsProperty.key) === 'args'\n );\n }\n\n if (parent?.type === 'JSXExpressionContainer') {\n const attribute = parent.parent;\n\n return (\n attribute?.type === 'JSXAttribute' &&\n attribute.name.type === 'JSXIdentifier' &&\n attribute.name.name === 'styles'\n );\n }\n\n return false;\n }\n\n /**\n * Checks if a property value node is a state mapping object\n * (i.e., an object where keys are state expressions and values are style values).\n */\n isStateMap(\n node: TSESTree.ObjectExpression,\n parentProperty: TSESTree.Property,\n ): boolean {\n const keyName = getKeyName(parentProperty.key);\n if (keyName === null) return false;\n\n // If the key starts with uppercase, it's a sub-element, not a state map\n if (/^[A-Z]/.test(keyName)) return false;\n\n // Special keys are not state maps\n // At-rule blocks are not state maps — their object values are descriptor maps.\n if (SPECIAL_STYLE_KEYS.has(keyName)) return false;\n\n // If the object has keys that look like state expressions, it's a state map.\n // A lone `_` (the fallback floor) or `''` (the default) is enough — both are\n // already covered by the string-literal / identifier branches below.\n return node.properties.some((prop) => {\n if (prop.type !== 'Property') return false;\n if (prop.key.type === 'Literal' && prop.key.value === '') return true;\n if (prop.key.type === 'Identifier') return true;\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') {\n return true;\n }\n return false;\n });\n }\n\n /**\n * Checks if a key represents a sub-element (starts with uppercase).\n */\n isSubElementKey(key: string): boolean {\n return /^[A-Z]/.test(key);\n }\n\n /**\n * Checks if a key represents a nested selector (starts with &).\n */\n isNestedSelectorKey(key: string): boolean {\n return key.startsWith('&');\n }\n\n /**\n * Checks if a key is a custom CSS property definition ($name or $$name).\n */\n isCustomPropertyKey(key: string): boolean {\n return key.startsWith('$');\n }\n\n /**\n * Checks if a key is a color token definition (#name or ##name).\n */\n isColorTokenKey(key: string): boolean {\n return key.startsWith('#');\n }\n\n /**\n * Checks if a key is a special @ property (@keyframes, @property, ...).\n */\n isSpecialKey(key: string): boolean {\n return key.startsWith('@');\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tenphi/eslint-plugin-tasty",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "ESLint plugin for validating tasty() and tastyStatic() style objects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"@typescript-eslint/rule-tester": "^8.56.1",
|
|
57
57
|
"eslint": "^10.0.0",
|
|
58
58
|
"eslint-config-prettier": "^10.1.8",
|
|
59
|
+
"known-css-properties": "^0.37.0",
|
|
59
60
|
"prettier": "^3.8.1",
|
|
60
61
|
"react": "^19.2.8",
|
|
61
62
|
"tsdown": "^0.20.3",
|
|
@@ -78,6 +79,7 @@
|
|
|
78
79
|
"lint:fix": "eslint src --fix",
|
|
79
80
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
80
81
|
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
82
|
+
"generate:css-properties": "node scripts/generate-css-properties.mjs",
|
|
81
83
|
"changeset": "changeset",
|
|
82
84
|
"version": "changeset version",
|
|
83
85
|
"release": "changeset publish"
|