@barocss/kit 0.9.0 → 0.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.
package/dist/index.js CHANGED
@@ -1082,7 +1082,13 @@ function parseUtility(value, ctx) {
1082
1082
  //#region src/core/astToCss.ts
1083
1083
  var isSafePrelude = (text) => {
1084
1084
  const t = String(text ?? "");
1085
- return !hasCommentDelimiter(t) && !hasHtmlEndTagOpener(t) && isBalancedPrelude(t);
1085
+ return !hasCommentDelimiter(t) && !hasHtmlEndTagOpener(t) && isBalancedPrelude(t) && !/url\s*\(/i.test(t);
1086
+ };
1087
+ var uniqueDescriptors = (node) => {
1088
+ if (node.type !== "at-rule") return [];
1089
+ if (node.name !== "property") return node.nodes;
1090
+ const seen = /* @__PURE__ */ new Set();
1091
+ return node.nodes.filter((c) => c.type !== "decl" || !seen.has(c.prop) && !!seen.add(c.prop));
1086
1092
  };
1087
1093
  var isSafeDecl = (prop, value) => isStructureSafeValue(String(prop)) && isStructureSafeValue(String(value ?? "")) && !hasHtmlEndTagOpener(String(prop)) && !hasHtmlEndTagOpener(String(value ?? ""));
1088
1094
  var importantPrefix = "!important";
@@ -1178,10 +1184,10 @@ function rootToCss(nodes, opts) {
1178
1184
  if (isSafeDecl(node.prop, node.value)) list.push(minify ? `${node.prop}:${node.value};` : `${node.prop}: ${node.value};`);
1179
1185
  } else if (node.type === "at-rule" && isSafePrelude(node.name) && isSafePrelude(node.params)) {
1180
1186
  if (minify) {
1181
- const body = node.nodes.filter((child) => child.type === "decl" && isSafeDecl(child.prop, child.value)).map((child) => child.type === "decl" ? `${child.prop}:${child.value};` : "").join("");
1187
+ const body = uniqueDescriptors(node).filter((child) => child.type === "decl" && isSafeDecl(child.prop, child.value)).map((child) => child.type === "decl" ? `${child.prop}:${child.value};` : "").join("");
1182
1188
  list.push(`@${node.name} ${node.params}{${body}}`);
1183
1189
  } else list.push(`@${node.name} ${node.params} {
1184
- ${node.nodes.map((node) => {
1190
+ ${uniqueDescriptors(node).map((node) => {
1185
1191
  if (node.type === "decl" && isSafeDecl(node.prop, node.value)) return `\t${node.prop}: ${node.value};`;
1186
1192
  }).join("\n")}
1187
1193
  }`);
@@ -1736,6 +1742,11 @@ function parseClassToAst(fullClassName, ctx) {
1736
1742
  variantChain: modifiers,
1737
1743
  index: i
1738
1744
  });
1745
+ if (result == null) {
1746
+ debugWarn(`[BAROCSS] Unknown variant: "${variant.type}" in "${fullClassName}"`);
1747
+ failures.add(fullClassName);
1748
+ return [];
1749
+ }
1739
1750
  if (plugin.wrap && (result === "&" || typeof result === "object" && !Array.isArray(result) && result.selector === "&" || Array.isArray(result) && result.length === 1 && result[0].selector === "&")) continue;
1740
1751
  if (typeof result === "string" && result.includes("&")) wrappers.push({
1741
1752
  type: "rule",
@@ -1822,10 +1833,11 @@ function getAstCacheStats(ctx) {
1822
1833
  * @example
1823
1834
  * const css = generateCss('sm:dark:hover:bg-red-500 sm:focus:bg-blue-500', ctx);
1824
1835
  */
1836
+ var CLASS_SEPARATOR = /[ \t\n\f\r]+/;
1825
1837
  function generateCss(classList, ctx, opts) {
1826
1838
  const seen = /* @__PURE__ */ new Set();
1827
1839
  const allAtRootNodes = [];
1828
- const results = classList.split(/\s+/).filter((cls) => {
1840
+ const results = classList.split(CLASS_SEPARATOR).filter((cls) => {
1829
1841
  if (!cls) return false;
1830
1842
  if (opts?.dedup) {
1831
1843
  if (seen.has(cls)) return false;
@@ -1885,7 +1897,7 @@ function generateCss(classList, ctx, opts) {
1885
1897
  */
1886
1898
  function generateCssRules(classList, ctx, opts) {
1887
1899
  const seen = /* @__PURE__ */ new Set();
1888
- return classList.split(/\s+/).filter((cls) => {
1900
+ return classList.split(CLASS_SEPARATOR).filter((cls) => {
1889
1901
  if (!cls) return false;
1890
1902
  if (opts?.dedup) {
1891
1903
  if (seen.has(cls)) return false;
@@ -3124,6 +3136,7 @@ function jsonToAst(input, ctx) {
3124
3136
  variantChain: [],
3125
3137
  index: i
3126
3138
  });
3139
+ if (result == null) continue;
3127
3140
  if (plugin.wrap && (result === "&" || typeof result === "object" && !Array.isArray(result) && result.selector === "&" || Array.isArray(result) && result.length === 1 && result[0].selector === "&")) {} else if (typeof result === "string" && result.includes("&")) wrappers.push({
3128
3141
  type: "rule",
3129
3142
  selector: result
@@ -7609,19 +7622,14 @@ staticModifier("after", ["&::after"], {
7609
7622
  source: "pseudo",
7610
7623
  astHandler: withPseudoContent
7611
7624
  });
7612
- staticModifier("placeholder", [
7613
- "&::placeholder",
7614
- "&::-webkit-input-placeholder",
7615
- "&::-moz-placeholder",
7616
- "&:-ms-input-placeholder"
7617
- ], { source: "pseudo" });
7618
- staticModifier("selection", ["&::selection", "&::-moz-selection"], { source: "pseudo" });
7619
- staticModifier("file", ["&::file-selector-button", "&::-webkit-file-upload-button"], { source: "pseudo" });
7625
+ staticModifier("placeholder", ["&::placeholder"], { source: "pseudo" });
7626
+ staticModifier("selection", ["& *::selection", "&::selection"], { source: "pseudo" });
7627
+ staticModifier("file", ["&::file-selector-button"], { source: "pseudo" });
7620
7628
  staticModifier("marker", [
7629
+ "& *::marker",
7621
7630
  "&::marker",
7622
- "&::-webkit-details-marker",
7623
- "&::-moz-list-bullet",
7624
- "&::-moz-list-number"
7631
+ "& *::-webkit-details-marker",
7632
+ "&::-webkit-details-marker"
7625
7633
  ], { source: "pseudo" });
7626
7634
  staticModifier("details-content", ["&::details-content"], { source: "pseudo" });
7627
7635
  staticModifier("first-line", ["&::first-line"], { source: "pseudo" });
@@ -7679,7 +7687,9 @@ function attributeVariantSelector(variant) {
7679
7687
  return `[${kind}-${key}=${/^(["']).*\1$/.test(raw) ? raw : `"${decodeArbitrarySelector(raw)}"`}]`;
7680
7688
  }
7681
7689
  const bare = /^data-([a-zA-Z0-9_-]+)$/.exec(variant);
7682
- return bare ? `[data-${bare[1]}]` : void 0;
7690
+ if (bare) return `[data-${bare[1]}]`;
7691
+ const aria = /^aria-([a-zA-Z0-9_-]+)$/.exec(variant);
7692
+ return aria ? `[aria-${aria[1]}="true"]` : void 0;
7683
7693
  }
7684
7694
  /**
7685
7695
  * The argument of a `:has()`/`:not()` built from an arbitrary value: a selector list is wrapped as `*:is(…)`
@@ -7700,6 +7710,80 @@ function hasTopLevelComma(value) {
7700
7710
  }
7701
7711
  return false;
7702
7712
  }
7713
+ /**
7714
+ * #335: the pseudo-class selector (`:hover`, `:first-child`, `:nth-child(odd)`) of a registered static
7715
+ * variant, for compounding in not-/group-/peer-/has- forms, or null when the variant is unknown or is not a
7716
+ * single pseudo-class (pseudo-elements, at-rules, multi-selector variants). Tailwind 4.3.3 emits nothing
7717
+ * for a compound variant whose inner variant it cannot compound (`not-foo`, `group-before`, `peer-has-foo`).
7718
+ */
7719
+ function pseudoClassOf(name, ctx) {
7720
+ const plugin = getModifier(ctx).find((p) => p.name === name && p.match(name, ctx));
7721
+ if (!plugin?.modifySelector) return null;
7722
+ const r = plugin.modifySelector({
7723
+ selector: "&",
7724
+ fullClassName: "",
7725
+ mod: { type: name },
7726
+ context: ctx
7727
+ });
7728
+ const list = Array.isArray(r) ? r : r && typeof r === "object" ? [r] : typeof r === "string" ? [{ selector: r }] : [];
7729
+ if (list.length !== 1) return null;
7730
+ const m = /^&(:(?!:)[a-zA-Z-]+(?:\(.*\))?)$/.exec(list[0].selector);
7731
+ return m ? m[1] : null;
7732
+ }
7733
+ /**
7734
+ * #352: the selector `not-<v>` / `group-not-<v>` negates: an attribute variant (`data-*`, `aria-*`), a
7735
+ * pseudo-class (#335), or a wrap-free `has-*` variant (`has-[…]`, `has-aria-*`), as Tailwind 4.3.3 compounds
7736
+ * them. Null when `<v>` is unknown or is not a single compound on `&`.
7737
+ */
7738
+ function negatableSelectorOf(name, ctx) {
7739
+ const attr = attributeVariantSelector(name);
7740
+ if (attr) return attr;
7741
+ const pc = pseudoClassOf(name, ctx);
7742
+ if (pc || !name.startsWith("has-")) return pc;
7743
+ const plugin = getModifier(ctx).find((p) => p.match(name, ctx));
7744
+ if (!plugin?.modifySelector || plugin.wrap || plugin.astHandler) return null;
7745
+ const r = plugin.modifySelector({
7746
+ selector: "&",
7747
+ fullClassName: "",
7748
+ mod: { type: name },
7749
+ context: ctx
7750
+ });
7751
+ const list = Array.isArray(r) ? r : r && typeof r === "object" ? [r] : typeof r === "string" ? [{ selector: r }] : [];
7752
+ if (list.length !== 1) return null;
7753
+ const m = /^&(:has\(.+\))$/.exec(list[0].selector);
7754
+ return m && !m[1].includes("&") ? m[1] : null;
7755
+ }
7756
+ /**
7757
+ * #352: `not-<v>` for a wrap-only at-rule variant (`md`, `max-md`, `min-[…]`, `print`, `motion-safe`,
7758
+ * `supports-[…]`, `dark` in media mode): the same at-rule with its condition negated (`@media not (…)`,
7759
+ * `@supports not (…)`), as Tailwind 4.3.3 emits it. Null for anything else, and for a prelude that is a list
7760
+ * or already combines conditions, where a leading `not` would not negate the whole query.
7761
+ */
7762
+ function negatedAtRuleOf(name, ctx) {
7763
+ if (name.startsWith("not-")) return null;
7764
+ const plugin = getModifier(ctx).find((p) => p.match(name, ctx));
7765
+ if (!plugin?.wrap || plugin.astHandler) return null;
7766
+ if (plugin.modifySelector) {
7767
+ const r = plugin.modifySelector({
7768
+ selector: "&",
7769
+ fullClassName: "",
7770
+ mod: { type: name },
7771
+ context: ctx
7772
+ });
7773
+ if ((typeof r === "string" ? r : Array.isArray(r) ? r.length === 1 ? r[0].selector : null : r?.selector) !== "&") return null;
7774
+ }
7775
+ const items = plugin.wrap({ type: name }, ctx);
7776
+ if (items.length !== 1) return null;
7777
+ const node = items[0];
7778
+ if (node.type !== "at-rule" || node.name !== "media" && node.name !== "supports" || node.nodes?.length) return null;
7779
+ const params = (node.params ?? "").trim();
7780
+ if (!params || /^not\b|,|\s(and|or)\s/i.test(params)) return null;
7781
+ return {
7782
+ ...node,
7783
+ params: `not ${params}`,
7784
+ nodes: []
7785
+ };
7786
+ }
7703
7787
  //#endregion
7704
7788
  //#region src/presets/variants/responsive.ts
7705
7789
  functionalModifier((mod, context) => {
@@ -7850,6 +7934,7 @@ function innerCompound(variant, ctx) {
7850
7934
  mod: { type: variant },
7851
7935
  context: ctx
7852
7936
  });
7937
+ if (out == null) return void 0;
7853
7938
  const list = typeof out === "string" ? [{ selector: out }] : Array.isArray(out) ? out : [out];
7854
7939
  if (list.length !== 1) return void 0;
7855
7940
  const sel = list[0].selector;
@@ -7944,6 +8029,10 @@ functionalModifier((mod, ctx) => {
7944
8029
  }, groupHasSelector);
7945
8030
  //#endregion
7946
8031
  //#region src/presets/variants/negation-variants.ts
8032
+ functionalModifier((mod, context) => /^not-(?!@)/.test(mod) && !!negatedAtRuleOf(mod.slice(4), context), () => "&", (mod, context) => {
8033
+ const node = negatedAtRuleOf(mod.type.slice(4), context);
8034
+ return node ? [node] : [];
8035
+ });
7947
8036
  functionalModifier((mod) => /^not-\[.*\]$/.test(mod), ({ selector, mod }) => {
7948
8037
  const m = /^not-\[(.+)\]$/.exec(mod.type);
7949
8038
  if (m) {
@@ -7965,10 +8054,12 @@ functionalModifier((mod) => /^not-\[.*\]$/.test(mod), ({ selector, mod }) => {
7965
8054
  source: "attribute"
7966
8055
  };
7967
8056
  });
7968
- functionalModifier((mod) => /^not-/.test(mod) && !mod.startsWith("not-@"), ({ selector, mod }) => {
8057
+ functionalModifier((mod) => /^not-/.test(mod) && !mod.startsWith("not-@"), ({ selector, mod, context }) => {
7969
8058
  const m = /^not-(.+)$/.exec(mod.type);
8059
+ const inner = m ? negatableSelectorOf(m[1], context) : null;
8060
+ if (m && !inner) return null;
7970
8061
  return {
7971
- selector: m ? `&:not(:${m[1]})` : selector,
8062
+ selector: inner ? `&:not(${inner})` : selector,
7972
8063
  flatten: false,
7973
8064
  wrappingType: "rule",
7974
8065
  source: "attribute"
@@ -8028,7 +8119,7 @@ functionalModifier((mod) => /^aria-/.test(mod), ({ selector, mod }) => {
8028
8119
  source: "aria"
8029
8120
  };
8030
8121
  }, void 0);
8031
- functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@"), ({ selector, mod }) => {
8122
+ functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@"), ({ selector, mod, context }) => {
8032
8123
  const pseudo = mod.type.replace("not-", "");
8033
8124
  if (pseudo.startsWith("[")) {
8034
8125
  const inner = pseudo.slice(1, -1);
@@ -8040,10 +8131,14 @@ functionalModifier((mod) => mod.startsWith("not-") && !mod.startsWith("not-@"),
8040
8131
  selector: `&:not(${functionalArgument(inner)})`,
8041
8132
  source: "attribute"
8042
8133
  };
8043
- } else return {
8044
- selector: `&:not(:${pseudo})`,
8045
- source: "attribute"
8046
- };
8134
+ } else {
8135
+ const inner = negatableSelectorOf(pseudo, context);
8136
+ if (!inner) return null;
8137
+ return {
8138
+ selector: `&:not(${inner})`,
8139
+ source: "attribute"
8140
+ };
8141
+ }
8047
8142
  }, void 0);
8048
8143
  functionalModifier((mod) => /^data-/.test(mod), ({ selector, mod }) => {
8049
8144
  const bracket = /^data-\[([a-zA-Z0-9_-]+)(?:=([^\]]+))?\]$/.exec(mod.type);
@@ -8156,11 +8251,13 @@ functionalModifier((mod) => /^(group|peer)-hover(\/[a-zA-Z0-9_-]+)?$/.test(mod),
8156
8251
  source: kind
8157
8252
  };
8158
8253
  }, () => [atRule("media", "(hover: hover)", [])]);
8159
- function negated(value) {
8254
+ function negated(value, ctx) {
8160
8255
  const v = value.slice(4);
8161
- return v.startsWith("[") && v.endsWith("]") ? `:not(*:is(${decodeArbitrarySelector(v.slice(1, -1))}))` : `:not(:${v})`;
8256
+ if (v.startsWith("[") && v.endsWith("]")) return `:not(*:is(${decodeArbitrarySelector(v.slice(1, -1))}))`;
8257
+ const inner = negatableSelectorOf(v, ctx);
8258
+ return inner ? `:not(${inner})` : null;
8162
8259
  }
8163
- functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod }) => {
8260
+ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod, context }) => {
8164
8261
  const raw = /^group-(.+)$/.exec(mod.type);
8165
8262
  const [variant, base] = splitGroupName("group", raw?.[1] ?? "");
8166
8263
  const m = raw ? [raw[0], variant] : null;
@@ -8176,11 +8273,14 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8176
8273
  wrappingType: "rule",
8177
8274
  source: "group"
8178
8275
  };
8179
- if (m?.[1]?.startsWith("not-")) return {
8180
- selector: `&:is(${g}${negated(m[1])} *)`,
8181
- wrappingType: "rule",
8182
- source: "group"
8183
- };
8276
+ if (m?.[1]?.startsWith("not-")) {
8277
+ const neg = negated(m[1], context);
8278
+ return neg ? {
8279
+ selector: `&:is(${g}${neg} *)`,
8280
+ wrappingType: "rule",
8281
+ source: "group"
8282
+ } : null;
8283
+ }
8184
8284
  if (m?.[1]?.startsWith("has-")) {
8185
8285
  const pattern = /^has-\[([a-zA-Z0-9_-]+)\]$/.exec(m?.[1]);
8186
8286
  if (pattern) return {
@@ -8206,8 +8306,10 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8206
8306
  };
8207
8307
  }
8208
8308
  }
8309
+ const pc = m ? pseudoClassOf(m[1], context) : null;
8310
+ if (m && !pc) return null;
8209
8311
  return m ? {
8210
- selector: `&:is(${g}:${m[1]} *)`,
8312
+ selector: `&:is(${g}${pc} *)`,
8211
8313
  wrappingType: "rule",
8212
8314
  source: "group"
8213
8315
  } : {
@@ -8215,7 +8317,7 @@ functionalModifier((mod) => /^group-(.+)$/.test(mod) && !atRuleHas(mod), ({ sele
8215
8317
  source: "group"
8216
8318
  };
8217
8319
  }, void 0);
8218
- functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod }) => {
8320
+ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selector, mod, context }) => {
8219
8321
  const raw = /^peer-(.+)$/.exec(mod.type);
8220
8322
  const [variant, base] = splitGroupName("peer", raw?.[1] ?? "");
8221
8323
  const m = raw ? [raw[0], variant] : null;
@@ -8236,14 +8338,22 @@ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selec
8236
8338
  selector: `&:is(${g}:has(${functionalArgument(value.slice(5, -1))}) ~ *)`,
8237
8339
  source: "peer"
8238
8340
  };
8239
- if (value?.startsWith("has-")) return {
8240
- selector: `&:is(${g}:has(:${value.slice(4)})~*)`,
8241
- source: "peer"
8242
- };
8243
- if (value?.startsWith("not-")) return {
8244
- selector: `&:is(${g}${negated(value)} ~ *)`,
8245
- source: "peer"
8246
- };
8341
+ if (value?.startsWith("has-")) {
8342
+ const pc = pseudoClassOf(value.slice(4), context);
8343
+ if (!pc) return null;
8344
+ return {
8345
+ selector: `&:is(${g}:has(${pc})~*)`,
8346
+ source: "peer"
8347
+ };
8348
+ }
8349
+ if (value?.startsWith("not-")) {
8350
+ const neg = negated(value, context);
8351
+ if (!neg) return null;
8352
+ return {
8353
+ selector: `&:is(${g}${neg} ~ *)`,
8354
+ source: "peer"
8355
+ };
8356
+ }
8247
8357
  if (value?.startsWith("aria-")) {
8248
8358
  let pattern = /^aria-([a-zA-Z0-9_]+)$/.exec(value);
8249
8359
  if (pattern) return {
@@ -8264,8 +8374,10 @@ functionalModifier((mod) => /^peer-(.+)$/.test(mod) && !atRuleHas(mod), ({ selec
8264
8374
  };
8265
8375
  }
8266
8376
  }
8377
+ const pc = m ? pseudoClassOf(value, context) : null;
8378
+ if (m && !pc) return null;
8267
8379
  return m ? {
8268
- selector: `&:is(${g}:${value}~*)`,
8380
+ selector: `&:is(${g}${pc}~*)`,
8269
8381
  source: "peer"
8270
8382
  } : {
8271
8383
  selector,
@@ -8314,6 +8426,7 @@ function toPx(n, unit) {
8314
8426
  }
8315
8427
  function preludeKey(kind, prelude) {
8316
8428
  const container = kind === "container";
8429
+ if (!container && /^\s*not\b/i.test(prelude)) return [0, 0];
8317
8430
  const min = MIN_W.exec(prelude);
8318
8431
  if (min) return [container ? 4 : 2, toPx(min[1], min[2])];
8319
8432
  const max = MAX_W.exec(prelude);