@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.d.cts CHANGED
@@ -69,6 +69,8 @@ export declare type AstNode = {
69
69
  export declare function astToCss(ast: AstNode[], baseSelector?: string, opts?: {
70
70
  minify?: boolean;
71
71
  important?: boolean;
72
+ scope?: string;
73
+ nested?: boolean;
72
74
  }, _indent?: string): string;
73
75
 
74
76
  export declare function atRoot(nodes: AstNode[], source?: string): AstNode;
@@ -823,6 +825,14 @@ export declare type AstNode = {
823
825
 
824
826
  export declare function isSafeVariantValue(value: string, allowTopLevelComma?: boolean): boolean;
825
827
 
828
+ /**
829
+ * #392: true when every top-level comma part of an emitted selector names `escapedClass` (a class selector
830
+ * already escaped with escapeClassName, including its leading dot) as a whole class token, or, when
831
+ * `allowNesting` is set, uses the nesting selector `&`. Escapes, quoted strings and bracket groups are skipped
832
+ * when splitting. Used as a defence-in-depth serializer check: a rule scoped to no generating class is dropped.
833
+ */
834
+ export declare function isScopedSelector(selector: string, escapedClass: string, allowNesting?: boolean): boolean;
835
+
826
836
  export declare function isStructureSafeValue(value: string): boolean;
827
837
 
828
838
  /**
package/dist/index.d.ts CHANGED
@@ -69,6 +69,8 @@ export declare type AstNode = {
69
69
  export declare function astToCss(ast: AstNode[], baseSelector?: string, opts?: {
70
70
  minify?: boolean;
71
71
  important?: boolean;
72
+ scope?: string;
73
+ nested?: boolean;
72
74
  }, _indent?: string): string;
73
75
 
74
76
  export declare function atRoot(nodes: AstNode[], source?: string): AstNode;
@@ -823,6 +825,14 @@ export declare type AstNode = {
823
825
 
824
826
  export declare function isSafeVariantValue(value: string, allowTopLevelComma?: boolean): boolean;
825
827
 
828
+ /**
829
+ * #392: true when every top-level comma part of an emitted selector names `escapedClass` (a class selector
830
+ * already escaped with escapeClassName, including its leading dot) as a whole class token, or, when
831
+ * `allowNesting` is set, uses the nesting selector `&`. Escapes, quoted strings and bracket groups are skipped
832
+ * when splitting. Used as a defence-in-depth serializer check: a rule scoped to no generating class is dropped.
833
+ */
834
+ export declare function isScopedSelector(selector: string, escapedClass: string, allowNesting?: boolean): boolean;
835
+
826
836
  export declare function isStructureSafeValue(value: string): boolean;
827
837
 
828
838
  /**
package/dist/index.js CHANGED
@@ -330,7 +330,8 @@ function registerModifier(modifier, ctx) {
330
330
  function getModifier(ctx) {
331
331
  return ctx && getContextState(ctx)?.modifiers || modifierRegistry;
332
332
  }
333
- var ESCAPE_REGEX = /[^A-Za-z0-9_-]/g;
333
+ var ESCAPE_REGEX = /[^A-Za-z0-9_-]/gu;
334
+ var UNSAFE_RAW = /^[\s\p{C}\p{Z}]$/u;
334
335
  function escapeClassName(className) {
335
336
  if (className === "-") return "\\-";
336
337
  const lead = /^-?[0-9]/.exec(className);
@@ -373,6 +374,7 @@ function escapeRest(className) {
373
374
  if (c === "}") return "\\}";
374
375
  if (c === "|") return "\\|";
375
376
  if (c === "\\") return "\\\\";
377
+ if (UNSAFE_RAW.test(c)) return "\\" + c.codePointAt(0).toString(16) + " ";
376
378
  return "\\" + c;
377
379
  });
378
380
  }
@@ -911,6 +913,46 @@ function isBalancedPrelude(text) {
911
913
  return stack.length === 0 && !quote;
912
914
  }
913
915
  /**
916
+ * #392: true when every top-level comma part of an emitted selector names `escapedClass` (a class selector
917
+ * already escaped with escapeClassName, including its leading dot) as a whole class token, or, when
918
+ * `allowNesting` is set, uses the nesting selector `&`. Escapes, quoted strings and bracket groups are skipped
919
+ * when splitting. Used as a defence-in-depth serializer check: a rule scoped to no generating class is dropped.
920
+ */
921
+ function isScopedSelector(selector, escapedClass, allowNesting = false) {
922
+ const parts = [];
923
+ let depth = 0;
924
+ let quote = "";
925
+ let start = 0;
926
+ for (let i = 0; i < selector.length; i++) {
927
+ const c = selector[i];
928
+ if (c === "\\") {
929
+ i++;
930
+ continue;
931
+ }
932
+ if (quote) {
933
+ if (c === quote) quote = "";
934
+ continue;
935
+ }
936
+ if (c === "\"" || c === "'") quote = c;
937
+ else if (c === "(" || c === "[") depth++;
938
+ else if (c === ")" || c === "]") depth--;
939
+ else if (c === "," && depth === 0) {
940
+ parts.push(selector.slice(start, i));
941
+ start = i + 1;
942
+ }
943
+ }
944
+ parts.push(selector.slice(start));
945
+ return parts.every((part) => {
946
+ if (allowNesting && part.includes("&")) return true;
947
+ for (let at = part.indexOf(escapedClass); at !== -1; at = part.indexOf(escapedClass, at + 1)) {
948
+ if (at > 0 && part[at - 1] === "\\") continue;
949
+ const next = part[at + escapedClass.length];
950
+ if (escapedClass.endsWith(" ") || next === void 0 || !/[\w\-\\\u0080-\uffff]/.test(next)) return true;
951
+ }
952
+ return false;
953
+ });
954
+ }
955
+ /**
914
956
  * #323: true when emitted text contains a markup end-tag opener (less-than then slash). Generated CSS can be
915
957
  * placed inside an HTML style element, where that sequence could end the element early. CSS escapes in the
916
958
  * output never form it, and a lone less-than (range media queries) stays allowed.
@@ -1104,6 +1146,12 @@ function astToCss(ast, baseSelector, opts, _indent = "") {
1104
1146
  const indent = _indent;
1105
1147
  const nextIndent = _indent + " ";
1106
1148
  const importantString = opts?.important ?? false ? ` ${importantPrefix}` : "";
1149
+ const nestedOpts = opts ? {
1150
+ ...opts,
1151
+ nested: true
1152
+ } : opts;
1153
+ const scopeClass = opts?.scope ? "." + escapeClassName(opts.scope) : "";
1154
+ const inScope = (sel) => !scopeClass || isScopedSelector(sel, scopeClass, !!opts?.nested);
1107
1155
  if (!ast || ast.length === 0) {
1108
1156
  debugWarn("[astToCss] Empty AST received:", {
1109
1157
  ast,
@@ -1146,14 +1194,14 @@ function astToCss(ast, baseSelector, opts, _indent = "") {
1146
1194
  else return escBase + (sel.startsWith(".") ? "" : " ") + sel;
1147
1195
  }).join(", ");
1148
1196
  }
1149
- if (!isSafePrelude(selector)) return "";
1150
- if (minify) return `${indent}${selector}{${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
1151
- else return `${indent}${selector} {\n${astToCss(node.nodes, baseSelector, opts, nextIndent)}${indent}}`;
1197
+ if (!isSafePrelude(selector) || !inScope(selector)) return "";
1198
+ if (minify) return `${indent}${selector}{${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}}`;
1199
+ else return `${indent}${selector} {\n${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}${indent}}`;
1152
1200
  }
1153
1201
  case "style-rule":
1154
- if (!isSafePrelude(node.selector)) return "";
1155
- if (minify) return `${indent}${node.selector} {${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
1156
- else return `${indent}${node.selector} {\n${astToCss(node.nodes, baseSelector, opts, nextIndent)}${indent}}`;
1202
+ if (!isSafePrelude(node.selector) || !inScope(node.selector)) return "";
1203
+ if (minify) return `${indent}${node.selector} {${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}}`;
1204
+ else return `${indent}${node.selector} {\n${astToCss(node.nodes, baseSelector, nestedOpts, nextIndent)}${indent}}`;
1157
1205
  case "at-rule":
1158
1206
  if (!isSafePrelude(node.name) || !isSafePrelude(node.params)) return "";
1159
1207
  if (minify) return `${indent}@${node.name} ${node.params}{${astToCss(node.nodes, baseSelector, opts, nextIndent)}}`;
@@ -1863,7 +1911,8 @@ function generateCss(classList, ctx, opts) {
1863
1911
  const hasStyleRule = cleanAst.some((node) => node.type === "style-rule");
1864
1912
  const css = astToCss(cleanAst.filter((node) => node.type !== "at-root"), hasStyleRule ? void 0 : cls, {
1865
1913
  minify: opts?.minify,
1866
- important: parsedResult?.utility?.important ?? false
1914
+ important: parsedResult?.utility?.important ?? false,
1915
+ scope: cls
1867
1916
  });
1868
1917
  const result = css;
1869
1918
  if (!result || result.trim() === "") debugWarn("[generateCss] Empty CSS generated for class:", {
@@ -1921,7 +1970,10 @@ function generateCssRules(classList, ctx, opts) {
1921
1970
  cssList.push(css);
1922
1971
  });
1923
1972
  else {
1924
- const css = astToCss([node], cls, options);
1973
+ const css = astToCss([node], cls, {
1974
+ ...options,
1975
+ scope: cls
1976
+ });
1925
1977
  cssList.push(css);
1926
1978
  }
1927
1979
  const rootCssList = [];
@@ -4586,7 +4638,7 @@ functionalUtility({
4586
4638
  decl("box-shadow", SHADOW_COMPOSITE)
4587
4639
  ];
4588
4640
  }
4589
- return [parseColor(main) ? decl("--baro-ring-color", main) : decl("box-shadow", main)];
4641
+ return [parseColor(main) || /^var\(--[^)]+\)$/.test(main) ? decl("--baro-ring-color", main) : decl("box-shadow", main)];
4590
4642
  }
4591
4643
  if (main === "inherit" || main === "current" || main === "transparent") return [decl("--baro-ring-color", main === "current" ? "currentColor" : main)];
4592
4644
  return null;
@@ -6712,6 +6764,7 @@ functionalUtility({
6712
6764
  return [decl("background-color", value)];
6713
6765
  }
6714
6766
  if (parseLength(value)) return [decl("background-size", value)];
6767
+ if (/^var\(--[^)]+\)$/.test(value)) return [decl("background-color", value)];
6715
6768
  return null;
6716
6769
  },
6717
6770
  handleCustomProperty: (value) => {
@@ -8544,6 +8597,6 @@ function upperBound(keys, key) {
8544
8597
  return lo;
8545
8598
  }
8546
8599
  //#endregion
8547
- export { AstCache, IncrementalParser, ParseResultCache, UtilityCache, WeakCache, arbitraryPropertyRegistration, astCache, astToCss, atRoot, atRule, clearAllCaches, clearAstCache, collectDeclPaths, comment, compareKeys, configGetter, createContext, decl, declPathToAst, deepMerge, defaultConfig, escapeClassName, expandThemeFunctions, functionalModifier, functionalUtility, generateCss, generateCssFromJson, generateCssRules, getAstCacheStats, getModifier, getPreflightCSS, getUtility, hasCommentDelimiter, hasCommentToken, hasHtmlEndTagOpener, hasPreset, isBalancedPrelude, isDebug, isSafeVariantToken, isSafeVariantValue, isStructureSafeValue, isWellFormedVariantBrackets, jsonToAst, mergeAstTreeList, modifierRegistry, normalizeMathSpacing, optimizeAst, parseClassName, parseClassToAst, parseResultCache, property, raw, registerModifier, registerUtility, resolveTheme, rootToCss, rule, ruleSortKey, setContextCacheReset, setDebug, staticModifier, staticUtility, styleRule, themeGetter, themeKeyValue, themeKeyVar, themeToCssVars, tokenize, upperBound, utilityCache };
8600
+ export { AstCache, IncrementalParser, ParseResultCache, UtilityCache, WeakCache, arbitraryPropertyRegistration, astCache, astToCss, atRoot, atRule, clearAllCaches, clearAstCache, collectDeclPaths, comment, compareKeys, configGetter, createContext, decl, declPathToAst, deepMerge, defaultConfig, escapeClassName, expandThemeFunctions, functionalModifier, functionalUtility, generateCss, generateCssFromJson, generateCssRules, getAstCacheStats, getModifier, getPreflightCSS, getUtility, hasCommentDelimiter, hasCommentToken, hasHtmlEndTagOpener, hasPreset, isBalancedPrelude, isDebug, isSafeVariantToken, isSafeVariantValue, isScopedSelector, isStructureSafeValue, isWellFormedVariantBrackets, jsonToAst, mergeAstTreeList, modifierRegistry, normalizeMathSpacing, optimizeAst, parseClassName, parseClassToAst, parseResultCache, property, raw, registerModifier, registerUtility, resolveTheme, rootToCss, rule, ruleSortKey, setContextCacheReset, setDebug, staticModifier, staticUtility, styleRule, themeGetter, themeKeyValue, themeKeyVar, themeToCssVars, tokenize, upperBound, utilityCache };
8548
8601
 
8549
8602
  //# sourceMappingURL=index.js.map