@homebound/truss 2.9.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -583,6 +583,396 @@ function sortRulesByPriority(rules) {
583
583
  }
584
584
  }
585
585
 
586
+ // src/plugin/css-property-abbreviations.ts
587
+ var cssPropertyAbbreviations = {
588
+ // Alignment
589
+ alignContent: "ac",
590
+ alignItems: "ai",
591
+ alignSelf: "als",
592
+ // Animation
593
+ animation: "anim",
594
+ animationDelay: "animd",
595
+ animationDirection: "animdr",
596
+ animationDuration: "animdu",
597
+ animationFillMode: "animfm",
598
+ animationIterationCount: "animic",
599
+ animationName: "animn",
600
+ animationPlayState: "animps",
601
+ animationTimingFunction: "animtf",
602
+ // Appearance
603
+ appearance: "app",
604
+ // Aspect ratio
605
+ aspectRatio: "ar",
606
+ // Backdrop filter
607
+ backdropFilter: "bdf",
608
+ // Background
609
+ background: "bg",
610
+ backgroundAttachment: "bga",
611
+ backgroundBlendMode: "bgbm",
612
+ backgroundClip: "bgcl",
613
+ backgroundColor: "bgc",
614
+ backgroundImage: "bgi",
615
+ backgroundOrigin: "bgo",
616
+ backgroundPosition: "bgp",
617
+ backgroundRepeat: "bgr",
618
+ backgroundSize: "bgs",
619
+ // Border – shorthand
620
+ border: "bd",
621
+ borderCollapse: "bdcl",
622
+ borderColor: "bdc",
623
+ borderImage: "bdi",
624
+ borderRadius: "bra",
625
+ borderSpacing: "bdsp",
626
+ borderStyle: "bs",
627
+ borderWidth: "bw",
628
+ // Border – top
629
+ borderTop: "bdt",
630
+ borderTopColor: "btc",
631
+ borderTopLeftRadius: "btlr",
632
+ borderTopRightRadius: "btrr",
633
+ borderTopStyle: "bts",
634
+ borderTopWidth: "btw",
635
+ // Border – right
636
+ borderRight: "bdr",
637
+ borderRightColor: "brc",
638
+ borderRightStyle: "brs",
639
+ borderRightWidth: "brw",
640
+ // Border – bottom
641
+ borderBottom: "bdb",
642
+ borderBottomColor: "bbc",
643
+ borderBottomLeftRadius: "bblr",
644
+ borderBottomRightRadius: "bbrr",
645
+ borderBottomStyle: "bbs",
646
+ borderBottomWidth: "bbw",
647
+ // Border – left
648
+ borderLeft: "bdl",
649
+ borderLeftColor: "blc",
650
+ borderLeftStyle: "bls",
651
+ borderLeftWidth: "blw",
652
+ // Box
653
+ boxDecorationBreak: "bxdb",
654
+ boxShadow: "bxs",
655
+ boxSizing: "bxz",
656
+ // Break
657
+ breakAfter: "bka",
658
+ breakBefore: "bkb",
659
+ breakInside: "bki",
660
+ // Caret / caption
661
+ captionSide: "cps",
662
+ caretColor: "cac",
663
+ // Clear / clip
664
+ clear: "clr",
665
+ clip: "cli",
666
+ clipPath: "clp",
667
+ // Color
668
+ color: "c",
669
+ colorScheme: "cs",
670
+ // Columns
671
+ columnCount: "cc",
672
+ columnFill: "cf",
673
+ columnGap: "cg",
674
+ columnRule: "cr",
675
+ columnRuleColor: "crc",
676
+ columnRuleStyle: "crs",
677
+ columnRuleWidth: "crw",
678
+ columnSpan: "csp",
679
+ columnWidth: "cw",
680
+ columns: "cols",
681
+ // Contain / container
682
+ contain: "ctn",
683
+ containerName: "ctnm",
684
+ containerType: "ctnt",
685
+ content: "cnt",
686
+ contentVisibility: "cv",
687
+ // Counter
688
+ counterIncrement: "coi",
689
+ counterReset: "cor",
690
+ // Cursor
691
+ cursor: "cur",
692
+ // Direction
693
+ direction: "dir",
694
+ // Display
695
+ display: "d",
696
+ // Empty cells
697
+ emptyCells: "ec",
698
+ // Fill (SVG)
699
+ fill: "fi",
700
+ fillOpacity: "fio",
701
+ fillRule: "fir",
702
+ // Filter
703
+ filter: "flt",
704
+ // Flex
705
+ flex: "fx",
706
+ flexBasis: "fxb",
707
+ flexDirection: "fxd",
708
+ flexFlow: "fxf",
709
+ flexGrow: "fxg",
710
+ flexShrink: "fxs",
711
+ flexWrap: "fxw",
712
+ // Float
713
+ float: "fl",
714
+ // Font
715
+ font: "fnt",
716
+ fontDisplay: "fntd",
717
+ fontFamily: "ff",
718
+ fontFeatureSettings: "ffs",
719
+ fontKerning: "fk",
720
+ fontSize: "fz",
721
+ fontSizeAdjust: "fza",
722
+ fontStretch: "fst",
723
+ fontStyle: "fsy",
724
+ fontSynthesis: "fsyn",
725
+ fontVariant: "fv",
726
+ fontVariantCaps: "fvc",
727
+ fontVariantLigatures: "fvl",
728
+ fontVariantNumeric: "fvn",
729
+ fontWeight: "fw",
730
+ // Gap
731
+ gap: "g",
732
+ // Grid
733
+ grid: "gd",
734
+ gridArea: "ga",
735
+ gridAutoColumns: "gac",
736
+ gridAutoFlow: "gaf",
737
+ gridAutoRows: "gar",
738
+ gridColumn: "gc",
739
+ gridColumnEnd: "gce",
740
+ gridColumnGap: "gcg",
741
+ gridColumnStart: "gcs",
742
+ gridGap: "gg",
743
+ gridRow: "gr",
744
+ gridRowEnd: "gre",
745
+ gridRowGap: "grg",
746
+ gridRowStart: "grs",
747
+ gridTemplate: "gt",
748
+ gridTemplateAreas: "gta",
749
+ gridTemplateColumns: "gtc",
750
+ gridTemplateRows: "gtr",
751
+ // Height
752
+ height: "h",
753
+ maxHeight: "mxh",
754
+ minHeight: "mnh",
755
+ // Hyphens
756
+ hyphens: "hyp",
757
+ // Image rendering
758
+ imageRendering: "ir",
759
+ // Inset
760
+ inset: "ins",
761
+ insetBlock: "insb",
762
+ insetBlockEnd: "insbe",
763
+ insetBlockStart: "insbs",
764
+ insetInline: "insi",
765
+ insetInlineEnd: "insie",
766
+ insetInlineStart: "insis",
767
+ // Isolation
768
+ isolation: "iso",
769
+ // Justify
770
+ justifyContent: "jc",
771
+ justifyItems: "ji",
772
+ justifySelf: "jfs",
773
+ // Left
774
+ left: "l",
775
+ // Letter spacing
776
+ letterSpacing: "ls",
777
+ // Line
778
+ lineBreak: "lb",
779
+ lineHeight: "lh",
780
+ // List
781
+ listStyle: "lis",
782
+ listStyleImage: "lsi",
783
+ listStylePosition: "lsp",
784
+ listStyleType: "lst",
785
+ // Margin
786
+ margin: "m",
787
+ marginBlock: "mbl",
788
+ marginBlockEnd: "mble",
789
+ marginBlockStart: "mbls",
790
+ marginBottom: "mb",
791
+ marginInline: "mil",
792
+ marginInlineEnd: "mile",
793
+ marginInlineStart: "mils",
794
+ marginLeft: "ml",
795
+ marginRight: "mr",
796
+ marginTop: "mt",
797
+ // Mask
798
+ mask: "msk",
799
+ maskImage: "mski",
800
+ maskPosition: "mskp",
801
+ maskRepeat: "mskr",
802
+ maskSize: "msks",
803
+ // Max / min width
804
+ maxWidth: "mxw",
805
+ minWidth: "mnw",
806
+ // Mix blend mode
807
+ mixBlendMode: "mbm",
808
+ // Object
809
+ objectFit: "obf",
810
+ objectPosition: "obp",
811
+ // Offset
812
+ offset: "ofs",
813
+ offsetPath: "ofsp",
814
+ // Opacity
815
+ opacity: "op",
816
+ // Order
817
+ order: "ord",
818
+ // Orphans / widows
819
+ orphans: "orp",
820
+ widows: "wid",
821
+ // Outline
822
+ outline: "ol",
823
+ outlineColor: "olc",
824
+ outlineOffset: "olo",
825
+ outlineStyle: "ols",
826
+ outlineWidth: "olw",
827
+ // Overflow
828
+ overflow: "ov",
829
+ overflowAnchor: "ova",
830
+ overflowWrap: "ovw",
831
+ overflowX: "ovx",
832
+ overflowY: "ovy",
833
+ overscrollBehavior: "osb",
834
+ overscrollBehaviorX: "osbx",
835
+ overscrollBehaviorY: "osby",
836
+ // Padding
837
+ padding: "p",
838
+ paddingBlock: "pbl",
839
+ paddingBlockEnd: "pble",
840
+ paddingBlockStart: "pbls",
841
+ paddingBottom: "pb",
842
+ paddingInline: "pil",
843
+ paddingInlineEnd: "pile",
844
+ paddingInlineStart: "pils",
845
+ paddingLeft: "pl",
846
+ paddingRight: "pr",
847
+ paddingTop: "pt",
848
+ // Page break
849
+ pageBreakAfter: "pgba",
850
+ pageBreakBefore: "pgbb",
851
+ pageBreakInside: "pgbi",
852
+ // Perspective
853
+ perspective: "per",
854
+ perspectiveOrigin: "pero",
855
+ // Place
856
+ placeContent: "plc",
857
+ placeItems: "pli",
858
+ placeSelf: "pls",
859
+ // Pointer events
860
+ pointerEvents: "pe",
861
+ // Position
862
+ position: "pos",
863
+ // Quotes
864
+ quotes: "q",
865
+ // Resize
866
+ resize: "rsz",
867
+ // Right
868
+ right: "r",
869
+ // Rotate / scale
870
+ rotate: "rot",
871
+ scale: "sc",
872
+ // Row gap
873
+ rowGap: "rg",
874
+ // Scroll
875
+ scrollBehavior: "scb",
876
+ scrollMargin: "scm",
877
+ scrollPadding: "scp",
878
+ scrollSnapAlign: "ssa",
879
+ scrollSnapStop: "sss",
880
+ scrollSnapType: "sst",
881
+ // Shape
882
+ shapeImageThreshold: "sit",
883
+ shapeMargin: "sm",
884
+ shapeOutside: "so",
885
+ // Stroke (SVG)
886
+ stroke: "stk",
887
+ strokeDasharray: "sda",
888
+ strokeDashoffset: "sdo",
889
+ strokeLinecap: "slc",
890
+ strokeLinejoin: "slj",
891
+ strokeOpacity: "sop",
892
+ strokeWidth: "sw",
893
+ // Tab size
894
+ tabSize: "ts",
895
+ // Table layout
896
+ tableLayout: "tl",
897
+ // Text
898
+ textAlign: "ta",
899
+ textAlignLast: "tal",
900
+ textDecoration: "td",
901
+ textDecorationColor: "tdc",
902
+ textDecorationLine: "tdl",
903
+ textDecorationStyle: "tds",
904
+ textDecorationThickness: "tdt",
905
+ textEmphasis: "te",
906
+ textIndent: "ti",
907
+ textJustify: "tj",
908
+ textOrientation: "tor",
909
+ textOverflow: "to",
910
+ textRendering: "tr",
911
+ textShadow: "tsh",
912
+ textTransform: "tt",
913
+ textUnderlineOffset: "tuo",
914
+ textUnderlinePosition: "tup",
915
+ textWrap: "twp",
916
+ // Top
917
+ top: "tp",
918
+ // Touch action
919
+ touchAction: "tca",
920
+ // Transform
921
+ transform: "tf",
922
+ transformOrigin: "tfo",
923
+ transformStyle: "tfs",
924
+ // Transition
925
+ transition: "tsn",
926
+ transitionDelay: "tsnd",
927
+ transitionDuration: "tsndu",
928
+ transitionProperty: "tsnp",
929
+ transitionTimingFunction: "tsntf",
930
+ // Translate
931
+ translate: "tsl",
932
+ // Unicode / user select
933
+ unicodeBidi: "ub",
934
+ userSelect: "us",
935
+ // Vertical align
936
+ verticalAlign: "va",
937
+ // Visibility
938
+ visibility: "vis",
939
+ // Webkit
940
+ WebkitAppearance: "wkapp",
941
+ WebkitBackdropFilter: "wkbdf",
942
+ WebkitBoxOrient: "wbo",
943
+ WebkitFontSmoothing: "wkfs",
944
+ WebkitLineClamp: "wlc",
945
+ WebkitMaskImage: "wkmi",
946
+ WebkitOverflowScrolling: "wkos",
947
+ WebkitTapHighlightColor: "wkthc",
948
+ WebkitTextFillColor: "wktfc",
949
+ WebkitTextStrokeColor: "wktsc",
950
+ WebkitTextStrokeWidth: "wktsw",
951
+ // White space
952
+ whiteSpace: "ws",
953
+ // Width
954
+ width: "w",
955
+ // Will change
956
+ willChange: "wc",
957
+ // Word
958
+ wordBreak: "wdb",
959
+ wordSpacing: "wds",
960
+ wordWrap: "wdw",
961
+ writingMode: "wm",
962
+ // Z-index
963
+ zIndex: "zi",
964
+ // Bottom (positioned after "border*" to avoid scan confusion)
965
+ bottom: "bot"
966
+ };
967
+ var seen = /* @__PURE__ */ new Map();
968
+ for (const [prop, abbr] of Object.entries(cssPropertyAbbreviations)) {
969
+ const existing = seen.get(abbr);
970
+ if (existing) {
971
+ throw new Error(`CSS property abbreviation conflict: "${abbr}" is used by both "${existing}" and "${prop}"`);
972
+ }
973
+ seen.set(abbr, prop);
974
+ }
975
+
586
976
  // src/plugin/emit-truss.ts
587
977
  var PSEUDO_SUFFIX = {
588
978
  ":hover": "_h",
@@ -700,6 +1090,9 @@ function getLonghandLookup(mapping) {
700
1090
  }
701
1091
  return cachedLookup;
702
1092
  }
1093
+ function getPropertyAbbreviation(cssProp) {
1094
+ return cssPropertyAbbreviations[cssProp] ?? cssProp;
1095
+ }
703
1096
  function computeStaticBaseName(seg, cssProp, cssValue, isMultiProp, mapping) {
704
1097
  const abbr = seg.abbr;
705
1098
  if (seg.argResolved !== void 0) {
@@ -708,7 +1101,7 @@ function computeStaticBaseName(seg, cssProp, cssValue, isMultiProp, mapping) {
708
1101
  const lookup = getLonghandLookup(mapping);
709
1102
  const canonical = lookup.get(`${cssProp}\0${cssValue}`);
710
1103
  if (canonical) return canonical;
711
- return `${abbr}_${valuePart}_${cssProp}`;
1104
+ return `${getPropertyAbbreviation(cssProp)}_${cleanValueForClassName(cssValue)}`;
712
1105
  }
713
1106
  return `${abbr}_${valuePart}`;
714
1107
  }
@@ -716,7 +1109,7 @@ function computeStaticBaseName(seg, cssProp, cssValue, isMultiProp, mapping) {
716
1109
  const lookup = getLonghandLookup(mapping);
717
1110
  const canonical = lookup.get(`${cssProp}\0${cssValue}`);
718
1111
  if (canonical) return canonical;
719
- return `${abbr}_${cssProp}`;
1112
+ return `${getPropertyAbbreviation(cssProp)}_${cleanValueForClassName(cssValue)}`;
720
1113
  }
721
1114
  return abbr;
722
1115
  }
@@ -823,13 +1216,16 @@ function collectVariableRules(rules, seg, mapping) {
823
1216
  }
824
1217
  if (seg.variableExtraDefs) {
825
1218
  for (const [cssProp, value] of Object.entries(seg.variableExtraDefs)) {
826
- const extraBase = `${seg.abbr}_${cssProp}`;
1219
+ const cssValue = String(value);
1220
+ const lookup = getLonghandLookup(mapping);
1221
+ const canonical = lookup.get(`${cssProp}\0${cssValue}`);
1222
+ const extraBase = canonical ?? `${getPropertyAbbreviation(cssProp)}_${cleanValueForClassName(cssValue)}`;
827
1223
  const extraName = prefix ? `${prefix}${extraBase}` : extraBase;
828
1224
  if (!rules.has(extraName)) {
829
1225
  rules.set(extraName, {
830
1226
  className: extraName,
831
1227
  cssProperty: camelToKebab(cssProp),
832
- cssValue: String(value),
1228
+ cssValue,
833
1229
  ...!whenSelector && baseRuleFields(seg),
834
1230
  whenSelector
835
1231
  });
@@ -961,7 +1357,10 @@ function buildStyleHashProperties(segments, mapping, maybeIncHelperName) {
961
1357
  }
962
1358
  if (seg.variableExtraDefs) {
963
1359
  for (const [cssProp, value] of Object.entries(seg.variableExtraDefs)) {
964
- const extraBase = `${seg.abbr}_${cssProp}`;
1360
+ const cssValue = String(value);
1361
+ const lookup = getLonghandLookup(mapping);
1362
+ const canonical = lookup.get(`${cssProp}\0${cssValue}`);
1363
+ const extraBase = canonical ?? `${getPropertyAbbreviation(cssProp)}_${cleanValueForClassName(cssValue)}`;
965
1364
  const extraName = prefix ? `${prefix}${extraBase}` : extraBase;
966
1365
  pushEntry(cssProp, { className: extraName, isVariable: false, isConditional });
967
1366
  }
@@ -2138,14 +2537,36 @@ function buildStyleHashMembers(segments, options) {
2138
2537
  }
2139
2538
  continue;
2140
2539
  }
2540
+ if (options.debug && !seg.classNameArg && !seg.styleArrayArg && !seg.typographyLookup) {
2541
+ const isMultiProp = Object.keys(seg.defs).length > 1;
2542
+ const hasExtraDefs = seg.variableExtraDefs && Object.keys(seg.variableExtraDefs).length > 0;
2543
+ if (isMultiProp || hasExtraDefs) {
2544
+ classNameArgs.push(t3.stringLiteral(seg.abbr));
2545
+ }
2546
+ }
2141
2547
  normalSegs.push(seg);
2142
2548
  }
2143
2549
  flushNormal();
2144
2550
  if (classNameArgs.length > 0) {
2145
- members.push(t3.objectProperty(t3.identifier("className"), t3.arrayExpression(classNameArgs)));
2551
+ members.unshift(...buildCustomClassNameMembers(classNameArgs));
2146
2552
  }
2147
2553
  return members;
2148
2554
  }
2555
+ function buildCustomClassNameMembers(classNameArgs) {
2556
+ const counts = /* @__PURE__ */ new Map();
2557
+ return classNameArgs.map((arg) => {
2558
+ const baseKey = `className_${sanitizeClassNameKey(arg)}`;
2559
+ const count = (counts.get(baseKey) ?? 0) + 1;
2560
+ counts.set(baseKey, count);
2561
+ const key = count === 1 ? baseKey : `${baseKey}_${count}`;
2562
+ return t3.objectProperty(t3.identifier(key), t3.cloneNode(arg, true));
2563
+ });
2564
+ }
2565
+ function sanitizeClassNameKey(arg) {
2566
+ const raw = t3.isStringLiteral(arg) ? arg.value : t3.isTemplateLiteral(arg) && arg.expressions.length === 0 && arg.quasis.length === 1 ? arg.quasis[0].value.cooked ?? "" : generate(arg).code;
2567
+ const sanitized = raw.replace(/[^a-zA-Z0-9_$]/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
2568
+ return sanitized || "value";
2569
+ }
2149
2570
  function buildAddCssObjectMembers(styleObject) {
2150
2571
  const members = [];
2151
2572
  for (const property of styleObject.properties) {
@@ -2198,9 +2619,6 @@ function mergeConditionalBranchMembers(members, previousProperties, conditionalO
2198
2619
  }
2199
2620
  const prop = propertyName(member.key);
2200
2621
  const prior = previousProperties.get(prop);
2201
- if (prop === "className" && prior) {
2202
- return t3.objectProperty(clonePropertyKey(member.key), mergeClassNameValues(prior.value, member.value));
2203
- }
2204
2622
  if (!prior || !conditionalOnlyProps.has(prop)) {
2205
2623
  return member;
2206
2624
  }
@@ -2226,17 +2644,6 @@ function mergePropertyValues(previousValue, currentValue) {
2226
2644
  }
2227
2645
  return t3.cloneNode(currentValue, true);
2228
2646
  }
2229
- function mergeClassNameValues(previousValue, currentValue) {
2230
- return t3.arrayExpression([...toClassNameElements(previousValue), ...toClassNameElements(currentValue)]);
2231
- }
2232
- function toClassNameElements(value) {
2233
- if (t3.isArrayExpression(value)) {
2234
- return value.elements.flatMap((element) => {
2235
- return element && !t3.isSpreadElement(element) ? [t3.cloneNode(element, true)] : [];
2236
- });
2237
- }
2238
- return [t3.cloneNode(value, true)];
2239
- }
2240
2647
  function mergeTupleValue(tuple, classNames, prependClassNames, previousVars) {
2241
2648
  const currentClassNames = tupleClassNames(tuple);
2242
2649
  const mergedClassNames = prependClassNames ? `${classNames} ${currentClassNames}` : `${currentClassNames} ${classNames}`;
@@ -2285,7 +2692,7 @@ function clonePropertyKey(key) {
2285
2692
  function injectDebugInfo(expr, line, options) {
2286
2693
  if (!options.debug) return;
2287
2694
  const firstProp = expr.properties.find((p) => {
2288
- return t3.isObjectProperty(p) && !(t3.isIdentifier(p.key) && p.key.name === "className" || t3.isStringLiteral(p.key) && p.key.value === "className" || t3.isIdentifier(p.key) && p.key.name === "__marker" || t3.isStringLiteral(p.key) && p.key.value === "__marker");
2695
+ return t3.isObjectProperty(p) && !(t3.isIdentifier(p.key) && p.key.name.startsWith("className_") || t3.isStringLiteral(p.key) && p.key.value.startsWith("className_") || t3.isIdentifier(p.key) && p.key.name === "__marker" || t3.isStringLiteral(p.key) && p.key.value === "__marker");
2289
2696
  });
2290
2697
  if (!firstProp) return;
2291
2698
  options.needsTrussDebugInfo.current = true;