@homebound/truss 2.9.1 → 2.11.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
  }
@@ -2044,7 +2443,12 @@ function rewriteExpressionSites(options) {
2044
2443
  const cssAttrPath = getCssAttributePath(site.path);
2045
2444
  const line = site.path.node.loc?.start.line ?? null;
2046
2445
  if (cssAttrPath) {
2047
- cssAttrPath.replaceWith(t3.jsxSpreadAttribute(buildCssSpreadExpression(cssAttrPath, styleHash, line, options)));
2446
+ if (!options.debug && isFullyStaticStyleHash(styleHash) && !hasExistingAttribute(cssAttrPath, "className") && !hasExistingAttribute(cssAttrPath, "style")) {
2447
+ const classNames = extractStaticClassNames(styleHash);
2448
+ cssAttrPath.replaceWith(t3.jsxAttribute(t3.jsxIdentifier("className"), t3.stringLiteral(classNames)));
2449
+ } else {
2450
+ cssAttrPath.replaceWith(t3.jsxSpreadAttribute(buildCssSpreadExpression(cssAttrPath, styleHash, line, options)));
2451
+ }
2048
2452
  } else {
2049
2453
  if (options.debug && line !== null) {
2050
2454
  injectDebugInfo(styleHash, line, options);
@@ -2138,11 +2542,18 @@ function buildStyleHashMembers(segments, options) {
2138
2542
  }
2139
2543
  continue;
2140
2544
  }
2545
+ if (options.debug && !seg.classNameArg && !seg.styleArrayArg && !seg.typographyLookup) {
2546
+ const isMultiProp = Object.keys(seg.defs).length > 1;
2547
+ const hasExtraDefs = seg.variableExtraDefs && Object.keys(seg.variableExtraDefs).length > 0;
2548
+ if (isMultiProp || hasExtraDefs) {
2549
+ classNameArgs.push(t3.stringLiteral(seg.abbr));
2550
+ }
2551
+ }
2141
2552
  normalSegs.push(seg);
2142
2553
  }
2143
2554
  flushNormal();
2144
2555
  if (classNameArgs.length > 0) {
2145
- members.push(...buildCustomClassNameMembers(classNameArgs));
2556
+ members.unshift(...buildCustomClassNameMembers(classNameArgs));
2146
2557
  }
2147
2558
  return members;
2148
2559
  }
@@ -2409,6 +2820,29 @@ function extractSiblingClassName(callPath) {
2409
2820
  function isMatchingPropertyName(key, name) {
2410
2821
  return t3.isIdentifier(key) && key.name === name || t3.isStringLiteral(key) && key.value === name;
2411
2822
  }
2823
+ function isFullyStaticStyleHash(hash) {
2824
+ for (const prop of hash.properties) {
2825
+ if (!t3.isObjectProperty(prop)) return false;
2826
+ if (!t3.isStringLiteral(prop.value)) return false;
2827
+ }
2828
+ return true;
2829
+ }
2830
+ function extractStaticClassNames(hash) {
2831
+ const classNames = [];
2832
+ for (const prop of hash.properties) {
2833
+ if (t3.isObjectProperty(prop) && t3.isStringLiteral(prop.value)) {
2834
+ classNames.push(prop.value.value);
2835
+ }
2836
+ }
2837
+ return classNames.join(" ");
2838
+ }
2839
+ function hasExistingAttribute(path, attrName) {
2840
+ const openingElement = path.parentPath;
2841
+ if (!openingElement || !openingElement.isJSXOpeningElement()) return false;
2842
+ return openingElement.node.attributes.some((attr) => {
2843
+ return t3.isJSXAttribute(attr) && t3.isJSXIdentifier(attr.name, { name: attrName });
2844
+ });
2845
+ }
2412
2846
 
2413
2847
  // src/plugin/transform.ts
2414
2848
  var traverse2 = _traverse2.default ?? _traverse2;