@barocss/kit 0.10.2 → 0.10.3

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.cjs CHANGED
@@ -331,7 +331,8 @@ function registerModifier(modifier, ctx) {
331
331
  function getModifier(ctx) {
332
332
  return ctx && getContextState(ctx)?.modifiers || modifierRegistry;
333
333
  }
334
- var ESCAPE_REGEX = /[^A-Za-z0-9_-]/g;
334
+ var ESCAPE_REGEX = /[^A-Za-z0-9_-]/gu;
335
+ var UNSAFE_RAW = /^[\s\p{C}\p{Z}]$/u;
335
336
  function escapeClassName(className) {
336
337
  if (className === "-") return "\\-";
337
338
  const lead = /^-?[0-9]/.exec(className);
@@ -374,6 +375,7 @@ function escapeRest(className) {
374
375
  if (c === "}") return "\\}";
375
376
  if (c === "|") return "\\|";
376
377
  if (c === "\\") return "\\\\";
378
+ if (UNSAFE_RAW.test(c)) return "\\" + c.codePointAt(0).toString(16) + " ";
377
379
  return "\\" + c;
378
380
  });
379
381
  }
@@ -912,6 +914,46 @@ function isBalancedPrelude(text) {
912
914
  return stack.length === 0 && !quote;
913
915
  }
914
916
  /**
917
+ * #392: true when every top-level comma part of an emitted selector names `escapedClass` (a class selector
918
+ * already escaped with escapeClassName, including its leading dot) as a whole class token, or, when
919
+ * `allowNesting` is set, uses the nesting selector `&`. Escapes, quoted strings and bracket groups are skipped
920
+ * when splitting. Used as a defence-in-depth serializer check: a rule scoped to no generating class is dropped.
921
+ */
922
+ function isScopedSelector(selector, escapedClass, allowNesting = false) {
923
+ const parts = [];
924
+ let depth = 0;
925
+ let quote = "";
926
+ let start = 0;
927
+ for (let i = 0; i < selector.length; i++) {
928
+ const c = selector[i];
929
+ if (c === "\\") {
930
+ i++;
931
+ continue;
932
+ }
933
+ if (quote) {
934
+ if (c === quote) quote = "";
935
+ continue;
936
+ }
937
+ if (c === "\"" || c === "'") quote = c;
938
+ else if (c === "(" || c === "[") depth++;
939
+ else if (c === ")" || c === "]") depth--;
940
+ else if (c === "," && depth === 0) {
941
+ parts.push(selector.slice(start, i));
942
+ start = i + 1;
943
+ }
944
+ }
945
+ parts.push(selector.slice(start));
946
+ return parts.every((part) => {
947
+ if (allowNesting && part.includes("&")) return true;
948
+ for (let at = part.indexOf(escapedClass); at !== -1; at = part.indexOf(escapedClass, at + 1)) {
949
+ if (at > 0 && part[at - 1] === "\\") continue;
950
+ const next = part[at + escapedClass.length];
951
+ if (escapedClass.endsWith(" ") || next === void 0 || !/[\w\-\\\u0080-\uffff]/.test(next)) return true;
952
+ }
953
+ return false;
954
+ });
955
+ }
956
+ /**
915
957
  * #323: true when emitted text contains a markup end-tag opener (less-than then slash). Generated CSS can be
916
958
  * placed inside an HTML style element, where that sequence could end the element early. CSS escapes in the
917
959
  * output never form it, and a lone less-than (range media queries) stays allowed.
@@ -1105,6 +1147,12 @@ function astToCss(ast, baseSelector, opts, _indent = "") {
1105
1147
  const indent = _indent;
1106
1148
  const nextIndent = _indent + " ";
1107
1149
  const importantString = opts?.important ?? false ? ` ${importantPrefix}` : "";
1150
+ const nestedOpts = opts ? {
1151
+ ...opts,
1152
+ nested: true
1153
+ } : opts;
1154
+ const scopeClass = opts?.scope ? "." + escapeClassName(opts.scope) : "";
1155
+ const inScope = (sel) => !scopeClass || isScopedSelector(sel, scopeClass, !!opts?.nested);
1108
1156
  if (!ast || ast.length === 0) {
1109
1157
  debugWarn("[astToCss] Empty AST received:", {
1110
1158
  ast,
@@ -1147,14 +1195,14 @@ function astToCss(ast, baseSelector, opts, _indent = "") {
1147
1195
  else return escBase + (sel.startsWith(".") ? "" : " ") + sel;
1148
1196
  }).join(", ");
1149
1197
  }
1150
- if (!isSafePrelude(selector)) return "";
1151
- if (minify) return `${indent}${selector}{${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
1152
- else return `${indent}${selector} {\n${astToCss(node.nodes, baseSelector, opts, nextIndent)}${indent}}`;
1198
+ if (!isSafePrelude(selector) || !inScope(selector)) return "";
1199
+ if (minify) return `${indent}${selector}{${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}}`;
1200
+ else return `${indent}${selector} {\n${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}${indent}}`;
1153
1201
  }
1154
1202
  case "style-rule":
1155
- if (!isSafePrelude(node.selector)) return "";
1156
- if (minify) return `${indent}${node.selector} {${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
1157
- else return `${indent}${node.selector} {\n${astToCss(node.nodes, baseSelector, opts, nextIndent)}${indent}}`;
1203
+ if (!isSafePrelude(node.selector) || !inScope(node.selector)) return "";
1204
+ if (minify) return `${indent}${node.selector} {${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}}`;
1205
+ else return `${indent}${node.selector} {\n${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}${indent}}`;
1158
1206
  case "at-rule":
1159
1207
  if (!isSafePrelude(node.name) || !isSafePrelude(node.params)) return "";
1160
1208
  if (minify) return `${indent}@${node.name} ${node.params}{${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
@@ -1864,7 +1912,8 @@ function generateCss(classList, ctx, opts) {
1864
1912
  const hasStyleRule = cleanAst.some((node) => node.type === "style-rule");
1865
1913
  const css = astToCss(cleanAst.filter((node) => node.type !== "at-root"), hasStyleRule ? void 0 : cls, {
1866
1914
  minify: opts?.minify,
1867
- important: parsedResult?.utility?.important ?? false
1915
+ important: parsedResult?.utility?.important ?? false,
1916
+ scope: cls
1868
1917
  });
1869
1918
  const result = css;
1870
1919
  if (!result || result.trim() === "") debugWarn("[generateCss] Empty CSS generated for class:", {
@@ -1922,7 +1971,10 @@ function generateCssRules(classList, ctx, opts) {
1922
1971
  cssList.push(css);
1923
1972
  });
1924
1973
  else {
1925
- const css = astToCss([node], cls, options);
1974
+ const css = astToCss([node], cls, {
1975
+ ...options,
1976
+ scope: cls
1977
+ });
1926
1978
  cssList.push(css);
1927
1979
  }
1928
1980
  const rootCssList = [];
@@ -4587,7 +4639,7 @@ functionalUtility({
4587
4639
  decl("box-shadow", SHADOW_COMPOSITE)
4588
4640
  ];
4589
4641
  }
4590
- return [parseColor(main) ? decl("--baro-ring-color", main) : decl("box-shadow", main)];
4642
+ return [parseColor(main) || /^var\(--[^)]+\)$/.test(main) ? decl("--baro-ring-color", main) : decl("box-shadow", main)];
4591
4643
  }
4592
4644
  if (main === "inherit" || main === "current" || main === "transparent") return [decl("--baro-ring-color", main === "current" ? "currentColor" : main)];
4593
4645
  return null;
@@ -6713,6 +6765,7 @@ functionalUtility({
6713
6765
  return [decl("background-color", value)];
6714
6766
  }
6715
6767
  if (parseLength(value)) return [decl("background-size", value)];
6768
+ if (/^var\(--[^)]+\)$/.test(value)) return [decl("background-color", value)];
6716
6769
  return null;
6717
6770
  },
6718
6771
  handleCustomProperty: (value) => {
@@ -8585,6 +8638,7 @@ exports.isBalancedPrelude = isBalancedPrelude;
8585
8638
  exports.isDebug = isDebug;
8586
8639
  exports.isSafeVariantToken = isSafeVariantToken;
8587
8640
  exports.isSafeVariantValue = isSafeVariantValue;
8641
+ exports.isScopedSelector = isScopedSelector;
8588
8642
  exports.isStructureSafeValue = isStructureSafeValue;
8589
8643
  exports.isWellFormedVariantBrackets = isWellFormedVariantBrackets;
8590
8644
  exports.jsonToAst = jsonToAst;