@projectwallace/css-parser 0.18.7 → 0.18.9

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.
@@ -1,6 +1,6 @@
1
1
  import { A as PARENTHESIS, B as STYLESHEET, C as MEDIA_QUERY, D as NTH_SELECTOR, E as NTH_OF_SELECTOR, F as RATIO, G as UNICODE_RANGE, H as SUPPORTS_DECLARATION, I as RAW, J as VALUE, K as UNIVERSAL_SELECTOR, L as SELECTOR, N as PSEUDO_CLASS_SELECTOR, O as NUMBER, P as PSEUDO_ELEMENT_SELECTOR, R as SELECTOR_LIST, S as MEDIA_FEATURE, T as NESTING_SELECTOR, U as SUPPORTS_QUERY, V as STYLE_RULE, W as TYPE_SELECTOR, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as LANG_SELECTOR, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PRELUDE_OPERATOR, k as OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, q as URL, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as IF_BRANCH, w as MEDIA_TYPE, x as LAYER_NAME, y as IF_CONDITION, z as STRING } from "./arena-BGvFdbj5.js";
2
2
  //#region src/constants.d.ts
3
- declare const NODE_TYPES: {
3
+ export declare const NODE_TYPES: {
4
4
  readonly STYLESHEET: 1;
5
5
  readonly STYLE_RULE: 2;
6
6
  readonly AT_RULE: 3;
@@ -48,4 +48,4 @@ declare const NODE_TYPES: {
48
48
  readonly RATIO: 58;
49
49
  };
50
50
  //#endregion
51
- export { ATTRIBUTE_SELECTOR, AT_RULE, AT_RULE_PRELUDE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, DECLARATION, DIMENSION, FEATURE_RANGE, FLAG_IMPORTANT, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, IF_BRANCH, IF_CONDITION, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NODE_TYPES, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, RATIO, RAW, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_DECLARATION, SUPPORTS_QUERY, TYPE_SELECTOR, UNICODE_RANGE, UNIVERSAL_SELECTOR, URL, VALUE };
51
+ export { ATTRIBUTE_SELECTOR, AT_RULE, AT_RULE_PRELUDE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, DECLARATION, DIMENSION, FEATURE_RANGE, FLAG_IMPORTANT, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, IF_BRANCH, IF_CONDITION, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, RATIO, RAW, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_DECLARATION, SUPPORTS_QUERY, TYPE_SELECTOR, UNICODE_RANGE, UNIVERSAL_SELECTOR, URL, VALUE };
@@ -1,5 +1,5 @@
1
1
  import "./arena-e9O_g2AN.js";
2
- import { a as is_vendor_prefixed, o as is_whitespace, s as str_equals, t as dimension_number_end, u as str_starts_with } from "./parse-dimension-CQELWb5z.js";
2
+ import { c as str_equals, d as str_starts_with, o as is_vendor_prefixed, s as is_whitespace, t as dimension_number_end } from "./parse-dimension-CIaPOmBc.js";
3
3
  //#region src/css-node.ts
4
4
  const TYPE_NAMES = {
5
5
  [1]: "StyleSheet",
@@ -114,18 +114,12 @@ var CSSNode = class CSSNode {
114
114
  this.source = source;
115
115
  this.index = index;
116
116
  }
117
- /**
118
- * @internal
119
- * Get the arena (for internal/advanced use only)
120
- */
121
117
  __get_arena() {
122
118
  return this.arena;
123
119
  }
124
- /** @internal */
125
120
  __get_source() {
126
121
  return this.source;
127
122
  }
128
- /** @internal */
129
123
  __get_index() {
130
124
  return this.index;
131
125
  }
@@ -224,7 +218,7 @@ var CSSNode = class CSSNode {
224
218
  if (pos >= node_end) return null;
225
219
  let ch1 = this.source.charCodeAt(pos);
226
220
  let ch2 = pos + 1 < node_end ? this.source.charCodeAt(pos + 1) : 0;
227
- if (ch1 === 61) return this.source.substring(pos, pos + 1);
221
+ if (ch1 === 61) return this.source.at(pos);
228
222
  if (ch1 === 126 && ch2 === 61) return this.source.substring(pos, pos + 2);
229
223
  if (ch1 === 124 && ch2 === 61) return this.source.substring(pos, pos + 2);
230
224
  if (ch1 === 94 && ch2 === 61) return this.source.substring(pos, pos + 2);
@@ -243,7 +237,7 @@ var CSSNode = class CSSNode {
243
237
  while (pos < node_end && is_whitespace(this.source.charCodeAt(pos))) pos++;
244
238
  if (pos >= node_end) return null;
245
239
  let flag_ch = this.source.charCodeAt(pos);
246
- if (flag_ch === 105 || flag_ch === 73 || flag_ch === 115 || flag_ch === 83) return this.source.substring(pos, pos + 1);
240
+ if (flag_ch === 105 || flag_ch === 73 || flag_ch === 115 || flag_ch === 83) return this.source.at(pos);
247
241
  return null;
248
242
  }
249
243
  /** Get the unit for dimension nodes (e.g., "px" from "100px", "%" from "50%") */
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { A as PARENTHESIS, B as STYLESHEET, C as MEDIA_QUERY, D as NTH_SELECTOR, E as NTH_OF_SELECTOR, F as RATIO, G as UNICODE_RANGE, H as SUPPORTS_DECLARATION, I as RAW, J as VALUE, K as UNIVERSAL_SELECTOR, L as SELECTOR, N as PSEUDO_CLASS_SELECTOR, O as NUMBER, P as PSEUDO_ELEMENT_SELECTOR, R as SELECTOR_LIST, S as MEDIA_FEATURE, T as NESTING_SELECTOR, U as SUPPORTS_QUERY, V as STYLE_RULE, W as TYPE_SELECTOR, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as LANG_SELECTOR, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PRELUDE_OPERATOR, k as OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, q as URL, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as IF_BRANCH, w as MEDIA_TYPE, x as LAYER_NAME, y as IF_CONDITION, z as STRING } from "./arena-BGvFdbj5.js";
2
2
  import { NODE_TYPES } from "./constants.js";
3
- import { A as TOKEN_URL, C as TOKEN_PERCENTAGE, D as TOKEN_SEMICOLON, E as TOKEN_RIGHT_PAREN, M as Token, N as TokenType, O as TOKEN_STRING, S as TOKEN_NUMBER, T as TOKEN_RIGHT_BRACKET, _ as TOKEN_HASH, a as TOKEN_AT_KEYWORD, b as TOKEN_LEFT_BRACKET, c as TOKEN_CDC, d as TOKEN_COMMA, f as TOKEN_COMMENT, g as TOKEN_FUNCTION, h as TOKEN_EOF, i as tokenize, j as TOKEN_WHITESPACE, k as TOKEN_UNICODE_RANGE, l as TOKEN_CDO, m as TOKEN_DIMENSION, o as TOKEN_BAD_STRING, p as TOKEN_DELIM, r as LexerPosition, s as TOKEN_BAD_URL, t as CommentInfo, u as TOKEN_COLON, v as TOKEN_IDENT, w as TOKEN_RIGHT_BRACE, x as TOKEN_LEFT_PAREN, y as TOKEN_LEFT_BRACE } from "./tokenize-CDEnYcVG.js";
3
+ import { A as TOKEN_URL, C as TOKEN_PERCENTAGE, D as TOKEN_SEMICOLON, E as TOKEN_RIGHT_PAREN, M as Token, N as TokenType, O as TOKEN_STRING, S as TOKEN_NUMBER, T as TOKEN_RIGHT_BRACKET, _ as TOKEN_HASH, a as TOKEN_AT_KEYWORD, b as TOKEN_LEFT_BRACKET, c as TOKEN_CDC, d as TOKEN_COMMA, f as TOKEN_COMMENT, g as TOKEN_FUNCTION, h as TOKEN_EOF, i as tokenize, j as TOKEN_WHITESPACE, k as TOKEN_UNICODE_RANGE, l as TOKEN_CDO, m as TOKEN_DIMENSION, o as TOKEN_BAD_STRING, p as TOKEN_DELIM, r as LexerPosition, s as TOKEN_BAD_URL, t as CommentInfo, u as TOKEN_COLON, v as TOKEN_IDENT, w as TOKEN_RIGHT_BRACE, x as TOKEN_LEFT_PAREN, y as TOKEN_LEFT_BRACE } from "./tokenize-CaWtrHw_.js";
4
4
  import { $ as is_atrule_prelude, A as Parenthesis, At as is_ratio, B as SelectorNode, Bt as is_unicode_range, C as MediaQuery, Ct as is_number, D as NthSelector, Dt as is_prelude_selectorlist, E as NthOfSelector, Et as is_prelude_operator, F as Ratio, Ft as is_string, G as ToPlain, Gt as PlainCSSNode, H as StyleSheet, Ht as is_url, I as Raw, It as is_stylesheet, J as UniversalSelector, K as TypeSelector, Kt as TYPE_NAMES, L as Rule, Lt as is_supports_declaration, M as PreludeSelectorList, Mt as is_rule, N as PseudoClassSelector, Nt as is_selector, O as Number, Ot as is_pseudo_class_selector, P as PseudoElementSelector, Pt as is_selector_list, Q as is_atrule, R as Selector, Rt as is_supports_query, S as MediaFeature, St as is_nth_selector, T as NestingSelector, Tt as is_parenthesis, U as SupportsDeclaration, Ut as is_value, V as String, Vt as is_universal_selector, W as SupportsQuery, Wt as CloneOptions, X as Value, Y as Url, Z as WithChildren, _ as Identifier, _t as is_media_feature, a as Block, at as is_container_query, b as LangSelector, bt as is_nesting_selector, c as Combinator, ct as is_feature_range, d as Declaration, dt as is_id_selector, et as is_attribute_selector, f as Dimension, ft as is_identifier, g as IdSelector, gt as is_layer_name, h as Hash, ht as is_lang_selector, i as AttributeSelector, it as is_comment, j as PreludeOperator, jt as is_raw, k as Operator, kt as is_pseudo_element_selector, l as Comment, lt as is_function, m as Function, mt as is_if_condition, n as Atrule, nt as is_class_selector, o as CSSNode, ot as is_declaration, p as FeatureRange, pt as is_if_branch, q as UnicodeRange, r as AtrulePrelude, rt as is_combinator, s as ClassSelector, st as is_dimension, t as AnyNode, tt as is_block, u as ContainerQuery, ut as is_hash, v as IfBranch, vt as is_media_query, w as MediaType, wt as is_operator, x as LayerName, xt as is_nth_of_selector, y as IfCondition, yt as is_media_type, z as SelectorList, zt as is_type_selector } from "./node-types-YnOKcNfU.js";
5
5
  import { ParserOptions, parse } from "./parse.js";
6
6
  import { parse_selector, parse_selector_list } from "./parse-selector.js";
@@ -14,15 +14,15 @@ import { BREAK, SKIP, traverse, walk } from "./walk.js";
14
14
  * @param a Base string, MUST be lowercase!
15
15
  * @param b Compare string
16
16
  */
17
- declare function str_equals(a: string, b: string): boolean;
17
+ export declare function str_equals(a: string, b: string): boolean;
18
18
  /** Case-insensitive ASCII prefix check without allocations. `prefix` MUST be lowercase. */
19
- declare function str_starts_with(str: string, prefix: string): boolean;
19
+ export declare function str_starts_with(str: string, prefix: string): boolean;
20
20
  /** Case-insensitive substring search without allocations, or -1 if not found. `searchChar` MUST be lowercase. */
21
- declare function str_index_of(str: string, searchChar: string): number;
21
+ export declare function str_index_of(str: string, searchChar: string): number;
22
22
  /** True if the string/range is vendor-prefixed (-webkit-, -moz-, -ms-, -o-). `--custom-property` is not. */
23
- declare function is_vendor_prefixed(text: string): boolean;
24
- declare function is_vendor_prefixed(source: string, start: number, end: number): boolean;
23
+ export declare function is_vendor_prefixed(text: string): boolean;
24
+ export declare function is_vendor_prefixed(source: string, start: number, end: number): boolean;
25
25
  /** True if the string is a CSS custom property (starts with `--`). */
26
- declare function is_custom(str: string): boolean;
26
+ export declare function is_custom(str: string): boolean;
27
27
  //#endregion
28
- export { ATTRIBUTE_SELECTOR, AT_RULE, AT_RULE_PRELUDE, type AnyNode, type Atrule, type AtrulePrelude, type AttributeSelector, BLOCK, BREAK, type Block, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, type CSSNode, type ClassSelector, type CloneOptions, type Combinator, type Comment, type CommentInfo, type ContainerQuery, DECLARATION, DIMENSION, type Declaration, type Dimension, FEATURE_RANGE, FLAG_IMPORTANT, FUNCTION, type FeatureRange, type Function, HASH, type Hash, IDENTIFIER, ID_SELECTOR, IF_BRANCH, IF_CONDITION, type IdSelector, type Identifier, type IfBranch, type IfCondition, LANG_SELECTOR, LAYER_NAME, type LangSelector, type LayerName, type LexerPosition, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, type MediaFeature, type MediaQuery, type MediaType, NESTING_SELECTOR, NODE_TYPES, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, type NestingSelector, type NthOfSelector, type NthSelector, type Number, OPERATOR, type Operator, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, type Parenthesis, type ParserOptions, type PlainCSSNode, type PreludeOperator, type PreludeSelectorList, type PseudoClassSelector, type PseudoElementSelector, RATIO, RAW, type Ratio, type Raw, type Rule, SELECTOR, SELECTOR_LIST, SKIP, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_DECLARATION, SUPPORTS_QUERY, type Selector, type SelectorList, type SelectorNode, type String, type StyleSheet, type SupportsDeclaration, type SupportsQuery, TOKEN_AT_KEYWORD, TOKEN_BAD_STRING, TOKEN_BAD_URL, TOKEN_CDC, TOKEN_CDO, TOKEN_COLON, TOKEN_COMMA, TOKEN_COMMENT, TOKEN_DELIM, TOKEN_DIMENSION, TOKEN_EOF, TOKEN_FUNCTION, TOKEN_HASH, TOKEN_IDENT, TOKEN_LEFT_BRACE, TOKEN_LEFT_BRACKET, TOKEN_LEFT_PAREN, TOKEN_NUMBER, TOKEN_PERCENTAGE, TOKEN_RIGHT_BRACE, TOKEN_RIGHT_BRACKET, TOKEN_RIGHT_PAREN, TOKEN_SEMICOLON, TOKEN_STRING, TOKEN_UNICODE_RANGE, TOKEN_URL, TOKEN_WHITESPACE, TYPE_NAMES, TYPE_SELECTOR, type ToPlain, Token, TokenType, type TypeSelector, UNICODE_RANGE, UNIVERSAL_SELECTOR, URL, type UnicodeRange, type UniversalSelector, type Url, VALUE, type Value, type WithChildren, is_atrule, is_atrule_prelude, is_attribute_selector, is_block, is_class_selector, is_combinator, is_comment, is_container_query, is_custom, is_declaration, is_dimension, is_feature_range, is_function, is_hash, is_id_selector, is_identifier, is_if_branch, is_if_condition, is_lang_selector, is_layer_name, is_media_feature, is_media_query, is_media_type, is_nesting_selector, is_nth_of_selector, is_nth_selector, is_number, is_operator, is_parenthesis, is_prelude_operator, is_prelude_selectorlist, is_pseudo_class_selector, is_pseudo_element_selector, is_ratio, is_raw, is_rule, is_selector, is_selector_list, is_string, is_stylesheet, is_supports_declaration, is_supports_query, is_type_selector, is_unicode_range, is_universal_selector, is_url, is_value, is_vendor_prefixed, parse, parse_atrule_prelude, parse_declaration, parse_dimension, parse_selector, parse_selector_list, parse_value, str_equals, str_index_of, str_starts_with, tokenize, traverse, walk };
28
+ export { ATTRIBUTE_SELECTOR, AT_RULE, AT_RULE_PRELUDE, type AnyNode, type Atrule, type AtrulePrelude, type AttributeSelector, BLOCK, BREAK, type Block, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, type CSSNode, type ClassSelector, type CloneOptions, type Combinator, type Comment, type CommentInfo, type ContainerQuery, DECLARATION, DIMENSION, type Declaration, type Dimension, FEATURE_RANGE, FLAG_IMPORTANT, FUNCTION, type FeatureRange, type Function, HASH, type Hash, IDENTIFIER, ID_SELECTOR, IF_BRANCH, IF_CONDITION, type IdSelector, type Identifier, type IfBranch, type IfCondition, LANG_SELECTOR, LAYER_NAME, type LangSelector, type LayerName, type LexerPosition, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, type MediaFeature, type MediaQuery, type MediaType, NESTING_SELECTOR, NODE_TYPES, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, type NestingSelector, type NthOfSelector, type NthSelector, type Number, OPERATOR, type Operator, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, type Parenthesis, type ParserOptions, type PlainCSSNode, type PreludeOperator, type PreludeSelectorList, type PseudoClassSelector, type PseudoElementSelector, RATIO, RAW, type Ratio, type Raw, type Rule, SELECTOR, SELECTOR_LIST, SKIP, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_DECLARATION, SUPPORTS_QUERY, type Selector, type SelectorList, type SelectorNode, type String, type StyleSheet, type SupportsDeclaration, type SupportsQuery, TOKEN_AT_KEYWORD, TOKEN_BAD_STRING, TOKEN_BAD_URL, TOKEN_CDC, TOKEN_CDO, TOKEN_COLON, TOKEN_COMMA, TOKEN_COMMENT, TOKEN_DELIM, TOKEN_DIMENSION, TOKEN_EOF, TOKEN_FUNCTION, TOKEN_HASH, TOKEN_IDENT, TOKEN_LEFT_BRACE, TOKEN_LEFT_BRACKET, TOKEN_LEFT_PAREN, TOKEN_NUMBER, TOKEN_PERCENTAGE, TOKEN_RIGHT_BRACE, TOKEN_RIGHT_BRACKET, TOKEN_RIGHT_PAREN, TOKEN_SEMICOLON, TOKEN_STRING, TOKEN_UNICODE_RANGE, TOKEN_URL, TOKEN_WHITESPACE, TYPE_NAMES, TYPE_SELECTOR, type ToPlain, Token, TokenType, type TypeSelector, UNICODE_RANGE, UNIVERSAL_SELECTOR, URL, type UnicodeRange, type UniversalSelector, type Url, VALUE, type Value, type WithChildren, is_atrule, is_atrule_prelude, is_attribute_selector, is_block, is_class_selector, is_combinator, is_comment, is_container_query, is_declaration, is_dimension, is_feature_range, is_function, is_hash, is_id_selector, is_identifier, is_if_branch, is_if_condition, is_lang_selector, is_layer_name, is_media_feature, is_media_query, is_media_type, is_nesting_selector, is_nth_of_selector, is_nth_selector, is_number, is_operator, is_parenthesis, is_prelude_operator, is_prelude_selectorlist, is_pseudo_class_selector, is_pseudo_element_selector, is_ratio, is_raw, is_rule, is_selector, is_selector_list, is_string, is_stylesheet, is_supports_declaration, is_supports_query, is_type_selector, is_unicode_range, is_universal_selector, is_url, is_value, parse, parse_atrule_prelude, parse_declaration, parse_dimension, parse_selector, parse_selector_list, parse_value, tokenize, traverse, walk };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { C as TOKEN_RIGHT_BRACKET, D as TOKEN_UNICODE_RANGE, E as TOKEN_STRING, O as TOKEN_URL, S as TOKEN_RIGHT_BRACE, T as TOKEN_SEMICOLON, _ as TOKEN_LEFT_BRACE, a as TOKEN_BAD_URL, b as TOKEN_NUMBER, c as TOKEN_COLON, d as TOKEN_DELIM, f as TOKEN_DIMENSION, g as TOKEN_IDENT, h as TOKEN_HASH, i as TOKEN_BAD_STRING, k as TOKEN_WHITESPACE, l as TOKEN_COMMA, m as TOKEN_FUNCTION, n as tokenize, o as TOKEN_CDC, p as TOKEN_EOF, r as TOKEN_AT_KEYWORD, s as TOKEN_CDO, u as TOKEN_COMMENT, v as TOKEN_LEFT_BRACKET, w as TOKEN_RIGHT_PAREN, x as TOKEN_PERCENTAGE, y as TOKEN_LEFT_PAREN } from "./tokenize-DK24ACbY.js";
1
+ import { C as TOKEN_RIGHT_BRACKET, D as TOKEN_UNICODE_RANGE, E as TOKEN_STRING, O as TOKEN_URL, S as TOKEN_RIGHT_BRACE, T as TOKEN_SEMICOLON, _ as TOKEN_LEFT_BRACE, a as TOKEN_BAD_URL, b as TOKEN_NUMBER, c as TOKEN_COLON, d as TOKEN_DELIM, f as TOKEN_DIMENSION, g as TOKEN_IDENT, h as TOKEN_HASH, i as TOKEN_BAD_STRING, k as TOKEN_WHITESPACE, l as TOKEN_COMMA, m as TOKEN_FUNCTION, n as tokenize, o as TOKEN_CDC, p as TOKEN_EOF, r as TOKEN_AT_KEYWORD, s as TOKEN_CDO, u as TOKEN_COMMENT, v as TOKEN_LEFT_BRACKET, w as TOKEN_RIGHT_PAREN, x as TOKEN_PERCENTAGE, y as TOKEN_LEFT_PAREN } from "./tokenize-0ADWAELW.js";
2
2
  import { A as PARENTHESIS, B as STYLE_RULE, C as MEDIA_QUERY, D as NTH_SELECTOR, E as NTH_OF_SELECTOR, F as RAW, G as UNIVERSAL_SELECTOR, H as SUPPORTS_QUERY, I as SELECTOR, K as URL, L as SELECTOR_LIST, M as PSEUDO_CLASS_SELECTOR, N as PSEUDO_ELEMENT_SELECTOR, O as NUMBER, P as RATIO, R as STRING, S as MEDIA_FEATURE, T as NESTING_SELECTOR, U as TYPE_SELECTOR, V as SUPPORTS_DECLARATION, W as UNICODE_RANGE, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as LANG_SELECTOR, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PRELUDE_OPERATOR, k as OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, q as VALUE, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as IF_BRANCH, w as MEDIA_TYPE, x as LAYER_NAME, y as IF_CONDITION, z as STYLESHEET } from "./arena-e9O_g2AN.js";
3
- import { a as is_vendor_prefixed, i as is_custom, l as str_index_of, n as parse_dimension, s as str_equals, u as str_starts_with } from "./parse-dimension-CQELWb5z.js";
4
- import { n as TYPE_NAMES } from "./css-node-C6TLE3qd.js";
5
- import { n as parse_selector, r as parse_selector_list } from "./parse-selector-Ce5HUZJ5.js";
3
+ import { a as is_custom, c as str_equals, d as str_starts_with, n as parse_dimension, o as is_vendor_prefixed, u as str_index_of } from "./parse-dimension-CIaPOmBc.js";
4
+ import { n as TYPE_NAMES } from "./css-node-DfJEsKN0.js";
5
+ import { n as parse_selector, r as parse_selector_list } from "./parse-selector-rTXB4IN2.js";
6
6
  import { parse_atrule_prelude } from "./parse-atrule-prelude.js";
7
7
  import { parse_value } from "./parse-value.js";
8
8
  import { parse_declaration } from "./parse-declaration.js";
@@ -2,7 +2,7 @@ import { l as CSSDataArena } from "./arena-BGvFdbj5.js";
2
2
  import { D as NthSelector } from "./node-types-YnOKcNfU.js";
3
3
  //#region src/parse-anplusb.d.ts
4
4
  /** @internal */
5
- declare class ANplusBParser {
5
+ export declare class ANplusBParser {
6
6
  private lexer;
7
7
  private arena;
8
8
  private source;
@@ -21,6 +21,5 @@ declare class ANplusBParser {
21
21
  private skip_whitespace;
22
22
  private create_anplusb_node;
23
23
  }
24
- declare function parse_anplusb(expr: string): NthSelector | null;
25
- //#endregion
26
- export { ANplusBParser, parse_anplusb };
24
+ export declare function parse_anplusb(expr: string): NthSelector | null;
25
+ //#endregion
@@ -1,7 +1,7 @@
1
- import { t as Lexer } from "./tokenize-DK24ACbY.js";
1
+ import { t as Lexer } from "./tokenize-0ADWAELW.js";
2
2
  import { l as CSSDataArena } from "./arena-e9O_g2AN.js";
3
- import { l as str_index_of, s as str_equals } from "./parse-dimension-CQELWb5z.js";
4
- import { t as CSSNode } from "./css-node-C6TLE3qd.js";
3
+ import { c as str_equals, u as str_index_of } from "./parse-dimension-CIaPOmBc.js";
4
+ import { t as CSSNode } from "./css-node-DfJEsKN0.js";
5
5
  //#region src/parse-anplusb.ts
6
6
  /** @internal */
7
7
  var ANplusBParser = class {
@@ -2,7 +2,7 @@ import { l as CSSDataArena } from "./arena-BGvFdbj5.js";
2
2
  import { t as AnyNode } from "./node-types-YnOKcNfU.js";
3
3
  //#region src/parse-atrule-prelude.d.ts
4
4
  /** @internal */
5
- declare class AtRulePreludeParser {
5
+ export declare class AtRulePreludeParser {
6
6
  private lexer;
7
7
  private arena;
8
8
  private source;
@@ -14,7 +14,8 @@ declare class AtRulePreludeParser {
14
14
  private parse_prelude_dispatch;
15
15
  private parse_media_query_list;
16
16
  private create_node;
17
- private is_and_or_not;
17
+ private paren_content_end;
18
+ private paren_close_end;
18
19
  private scan_matching_paren;
19
20
  private parse_single_media_query;
20
21
  private parse_container_query;
@@ -40,6 +41,5 @@ declare class AtRulePreludeParser {
40
41
  * @param prelude - The at-rule prelude to parse (e.g., "(min-width: 768px)", "utilities")
41
42
  * @returns An array of CSSNode objects representing the parsed prelude
42
43
  */
43
- declare function parse_atrule_prelude(at_rule_name: string, prelude: string): AnyNode[];
44
- //#endregion
45
- export { AtRulePreludeParser, parse_atrule_prelude };
44
+ export declare function parse_atrule_prelude(at_rule_name: string, prelude: string): AnyNode[];
45
+ //#endregion
@@ -1,9 +1,9 @@
1
- import { t as Lexer } from "./tokenize-DK24ACbY.js";
1
+ import { t as Lexer } from "./tokenize-0ADWAELW.js";
2
2
  import { l as CSSDataArena } from "./arena-e9O_g2AN.js";
3
- import { d as strip_vendor_prefix, s as str_equals } from "./parse-dimension-CQELWb5z.js";
4
- import { t as CSSNode } from "./css-node-C6TLE3qd.js";
5
- import { s as trim_boundaries } from "./parse-selector-Ce5HUZJ5.js";
6
- import { n as ConditionParser, t as ValueNodeParser } from "./value-node-parser-DfkneBdM.js";
3
+ import { f as strip_vendor_prefix, l as str_equals_range, r as is_and_or_not_range } from "./parse-dimension-CIaPOmBc.js";
4
+ import { t as CSSNode } from "./css-node-DfJEsKN0.js";
5
+ import { s as trim_boundaries } from "./parse-selector-rTXB4IN2.js";
6
+ import { n as ConditionParser, t as ValueNodeParser } from "./value-node-parser-DizbcN1a.js";
7
7
  //#region src/parse-atrule-prelude.ts
8
8
  /** @internal */
9
9
  var AtRulePreludeParser = class {
@@ -66,9 +66,8 @@ var AtRulePreludeParser = class {
66
66
  create_node(type, start, end) {
67
67
  return this.arena.create_node(type, start, end - start, this.lexer.token_line, this.lexer.token_column);
68
68
  }
69
- is_and_or_not(str) {
70
- return str_equals("and", str) || str_equals("or", str) || str_equals("not", str);
71
- }
69
+ paren_content_end = 0;
70
+ paren_close_end = 0;
72
71
  scan_matching_paren() {
73
72
  let depth = 1;
74
73
  let content_end = this.lexer.pos;
@@ -84,11 +83,9 @@ var AtRulePreludeParser = class {
84
83
  }
85
84
  } else if (token_type === 26) break;
86
85
  }
87
- return [
88
- content_end,
89
- close_end,
90
- depth === 0
91
- ];
86
+ this.paren_content_end = content_end;
87
+ this.paren_close_end = close_end;
88
+ return depth === 0;
92
89
  }
93
90
  parse_single_media_query() {
94
91
  let query_start = this.lexer.pos;
@@ -99,9 +96,11 @@ var AtRulePreludeParser = class {
99
96
  const saved_token_start = this.lexer.save_position();
100
97
  this.next_token();
101
98
  if (this.lexer.token_type === 1) {
102
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
103
- if (str_equals("only", text) || str_equals("not", text)) {
104
- let modifier = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
99
+ let source = this.source;
100
+ let token_start = this.lexer.token_start;
101
+ let token_end = this.lexer.token_end;
102
+ if (str_equals_range(source, token_start, token_end, "only") || str_equals_range(source, token_start, token_end, "not")) {
103
+ let modifier = this.create_node(38, token_start, token_end);
105
104
  first_component = modifier;
106
105
  last_component = modifier;
107
106
  } else this.lexer.restore_position(saved_token_start);
@@ -115,11 +114,12 @@ var AtRulePreludeParser = class {
115
114
  let component = null;
116
115
  if (token_type === 21) {
117
116
  component = this.condition_parser.parse_media_feature(this.lexer.token_start, this.prelude_end, this.lexer.token_line, this.lexer.token_column);
118
- if (component !== null) this.lexer.seek(...this.condition_parser.end_position);
117
+ if (component !== null) this.condition_parser.seek_to_end(this.lexer);
119
118
  } else if (token_type === 1) {
120
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
121
- if (this.is_and_or_not(text)) component = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
122
- else component = this.create_node(34, this.lexer.token_start, this.lexer.token_end);
119
+ let token_start = this.lexer.token_start;
120
+ let token_end = this.lexer.token_end;
121
+ if (is_and_or_not_range(this.source, token_start, token_end)) component = this.create_node(38, token_start, token_end);
122
+ else component = this.create_node(34, token_start, token_end);
123
123
  } else break;
124
124
  if (component !== null) {
125
125
  if (first_component === 0) first_component = component;
@@ -144,14 +144,15 @@ var AtRulePreludeParser = class {
144
144
  let component = null;
145
145
  if (token_type === 21) {
146
146
  component = this.condition_parser.parse_media_feature(this.lexer.token_start, this.prelude_end, this.lexer.token_line, this.lexer.token_column);
147
- if (component !== null) this.lexer.seek(...this.condition_parser.end_position);
147
+ if (component !== null) this.condition_parser.seek_to_end(this.lexer);
148
148
  } else if (token_type === 2) {
149
149
  component = this.condition_parser.parse_function_condition(this.lexer.token_start, this.prelude_end, this.lexer.token_line, this.lexer.token_column);
150
- this.lexer.seek(...this.condition_parser.end_position);
150
+ this.condition_parser.seek_to_end(this.lexer);
151
151
  } else if (token_type === 1) {
152
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
153
- if (this.is_and_or_not(text)) component = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
154
- else component = this.create_node(10, this.lexer.token_start, this.lexer.token_end);
152
+ let token_start = this.lexer.token_start;
153
+ let token_end = this.lexer.token_end;
154
+ if (is_and_or_not_range(this.source, token_start, token_end)) component = this.create_node(38, token_start, token_end);
155
+ else component = this.create_node(10, token_start, token_end);
155
156
  }
156
157
  if (component !== null) {
157
158
  if (first_component === 0) first_component = component;
@@ -249,8 +250,8 @@ var AtRulePreludeParser = class {
249
250
  let url_start = this.lexer.token_start;
250
251
  let url_end = this.lexer.token_end;
251
252
  if (this.lexer.token_type === 2) {
252
- let [, close_end] = this.scan_matching_paren();
253
- url_end = close_end;
253
+ this.scan_matching_paren();
254
+ url_end = this.paren_close_end;
254
255
  }
255
256
  return this.create_node(18, url_start, url_end);
256
257
  }
@@ -258,16 +259,17 @@ var AtRulePreludeParser = class {
258
259
  const saved = this.lexer.save_position();
259
260
  this.next_token();
260
261
  if (this.lexer.token_type === 1 || this.lexer.token_type === 2) {
261
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
262
- if (this.lexer.token_type === 2 && text.endsWith("(")) text = text.slice(0, -1);
263
- if (str_equals("layer", text)) {
262
+ let name_end = this.lexer.token_type === 2 ? this.lexer.token_end - 1 : this.lexer.token_end;
263
+ if (str_equals_range(this.source, this.lexer.token_start, name_end, "layer")) {
264
264
  let layer_start = this.lexer.token_start;
265
265
  let layer_end = this.lexer.token_end;
266
266
  let content_start = 0;
267
267
  let content_length = 0;
268
268
  if (this.lexer.token_type === 2) {
269
269
  content_start = this.lexer.pos;
270
- let [content_end, close_end, matched] = this.scan_matching_paren();
270
+ let matched = this.scan_matching_paren();
271
+ let content_end = this.paren_content_end;
272
+ let close_end = this.paren_close_end;
271
273
  if (matched) {
272
274
  content_length = content_end - content_start;
273
275
  layer_end = close_end;
@@ -291,11 +293,12 @@ var AtRulePreludeParser = class {
291
293
  const saved = this.lexer.save_position();
292
294
  this.next_token();
293
295
  if (this.lexer.token_type === 2) {
294
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end - 1);
295
- if (str_equals("supports", text)) {
296
+ if (str_equals_range(this.source, this.lexer.token_start, this.lexer.token_end - 1, "supports")) {
296
297
  let supports_start = this.lexer.token_start;
297
298
  let content_start = this.lexer.token_end;
298
- let [content_end, supports_end] = this.scan_matching_paren();
299
+ this.scan_matching_paren();
300
+ let content_end = this.paren_content_end;
301
+ let supports_end = this.paren_close_end;
299
302
  let supports_node = this.create_node(36, supports_start, supports_end);
300
303
  let trimmed = trim_boundaries(this.source, content_start, content_end);
301
304
  if (trimmed) {
@@ -351,7 +354,9 @@ var AtRulePreludeParser = class {
351
354
  this.next_token();
352
355
  let paren_start = this.lexer.token_start;
353
356
  let content_start = this.lexer.pos;
354
- let [content_end, paren_end] = this.scan_matching_paren();
357
+ this.scan_matching_paren();
358
+ let content_end = this.paren_content_end;
359
+ let paren_end = this.paren_close_end;
355
360
  let scope_node = this.create_node(41, paren_start, paren_end);
356
361
  let trimmed = trim_boundaries(this.source, content_start, content_end);
357
362
  if (trimmed) {
@@ -361,8 +366,7 @@ var AtRulePreludeParser = class {
361
366
  nodes.push(scope_node);
362
367
  } else if (token_type === 1) {
363
368
  this.next_token();
364
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
365
- if (str_equals("to", text)) nodes.push(this.create_node(38, this.lexer.token_start, this.lexer.token_end));
369
+ if (str_equals_range(this.source, this.lexer.token_start, this.lexer.token_end, "to")) nodes.push(this.create_node(38, this.lexer.token_start, this.lexer.token_end));
366
370
  } else this.next_token();
367
371
  }
368
372
  return nodes;
@@ -1,12 +1,13 @@
1
1
  import { l as CSSDataArena } from "./arena-BGvFdbj5.js";
2
- import { n as Lexer } from "./tokenize-CDEnYcVG.js";
2
+ import { n as Lexer } from "./tokenize-CaWtrHw_.js";
3
3
  import { d as Declaration } from "./node-types-YnOKcNfU.js";
4
4
  //#region src/parse-declaration.d.ts
5
5
  /** @internal */
6
- declare class DeclarationParser {
6
+ export declare class DeclarationParser {
7
7
  private arena;
8
8
  private source;
9
9
  private value_parser;
10
+ private lookahead_position;
10
11
  constructor(arena: CSSDataArena, source: string, parse_values?: boolean);
11
12
  parse_declaration(start: number, end: number, line?: number, column?: number): number | null;
12
13
  parse_declaration_with_lexer(lexer: Lexer, end: number): number | null;
@@ -16,6 +17,5 @@ declare class DeclarationParser {
16
17
  * @param source - The CSS declaration to parse (e.g., "color: red", "margin: 10px !important")
17
18
  * @returns The DECLARATION CSSNode
18
19
  */
19
- declare function parse_declaration(source: string): Declaration;
20
- //#endregion
21
- export { DeclarationParser, parse_declaration };
20
+ export declare function parse_declaration(source: string): Declaration;
21
+ //#endregion
@@ -1,8 +1,8 @@
1
- import { t as Lexer } from "./tokenize-DK24ACbY.js";
1
+ import { t as Lexer } from "./tokenize-0ADWAELW.js";
2
2
  import { l as CSSDataArena } from "./arena-e9O_g2AN.js";
3
- import { a as is_vendor_prefixed } from "./parse-dimension-CQELWb5z.js";
4
- import { t as CSSNode } from "./css-node-C6TLE3qd.js";
5
- import { a as skip_whitespace_and_comments_backward, s as trim_boundaries } from "./parse-selector-Ce5HUZJ5.js";
3
+ import { o as is_vendor_prefixed } from "./parse-dimension-CIaPOmBc.js";
4
+ import { t as CSSNode } from "./css-node-DfJEsKN0.js";
5
+ import { a as skip_whitespace_and_comments_backward, o as skip_whitespace_and_comments_forward } from "./parse-selector-rTXB4IN2.js";
6
6
  import { ValueParser } from "./parse-value.js";
7
7
  //#region src/parse-declaration.ts
8
8
  /** @internal */
@@ -10,6 +10,7 @@ var DeclarationParser = class {
10
10
  arena;
11
11
  source;
12
12
  value_parser;
13
+ lookahead_position = new Lexer("").save_position();
13
14
  constructor(arena, source, parse_values = true) {
14
15
  this.arena = arena;
15
16
  this.source = source;
@@ -22,9 +23,8 @@ var DeclarationParser = class {
22
23
  return this.parse_declaration_with_lexer(lexer, end);
23
24
  }
24
25
  parse_declaration_with_lexer(lexer, end) {
25
- const initial_saved = lexer.save_position();
26
+ let initial_saved = null;
26
27
  let has_browser_hack = false;
27
- let has_delimiter_prefix = false;
28
28
  let browser_hack_start = 0;
29
29
  let browser_hack_line = 1;
30
30
  let browser_hack_column = 1;
@@ -56,7 +56,7 @@ var DeclarationParser = class {
56
56
  lexer.next_token_fast(true);
57
57
  if (lexer.token_type === 1) {
58
58
  has_browser_hack = true;
59
- has_delimiter_prefix = true;
59
+ initial_saved = delim_saved;
60
60
  } else lexer.restore_position(delim_saved);
61
61
  }
62
62
  if (lexer.token_type !== 1 && lexer.token_type !== 3 && lexer.token_type !== 4) return null;
@@ -64,10 +64,10 @@ var DeclarationParser = class {
64
64
  let prop_end = lexer.token_end;
65
65
  let decl_line = has_browser_hack ? browser_hack_line : lexer.token_line;
66
66
  let decl_column = has_browser_hack ? browser_hack_column : lexer.token_column;
67
- const saved = lexer.save_position();
67
+ const saved = lexer.save_position_into(this.lookahead_position);
68
68
  lexer.next_token_fast(true);
69
69
  if (lexer.token_type !== 16) {
70
- lexer.restore_position(has_delimiter_prefix ? initial_saved : saved);
70
+ lexer.restore_position(initial_saved ?? saved);
71
71
  return null;
72
72
  }
73
73
  lexer.pos = lexer.token_end;
@@ -135,15 +135,16 @@ var DeclarationParser = class {
135
135
  }
136
136
  lexer.pos++;
137
137
  }
138
- let trimmed = trim_boundaries(this.source, value_start, value_end);
139
- if (trimmed) {
140
- this.arena.set_value_start_delta(declaration, trimmed[0] - prop_start);
141
- this.arena.set_value_length(declaration, trimmed[1] - trimmed[0]);
138
+ let trimmed_start = skip_whitespace_and_comments_forward(this.source, value_start, value_end);
139
+ let trimmed_end = skip_whitespace_and_comments_backward(this.source, value_end, trimmed_start);
140
+ if (trimmed_start < trimmed_end) {
141
+ this.arena.set_value_start_delta(declaration, trimmed_start - prop_start);
142
+ this.arena.set_value_length(declaration, trimmed_end - trimmed_start);
142
143
  if (this.value_parser) {
143
- let valueNode = this.value_parser.parse_value(value_start, trimmed[1], value_start_line, value_start_column);
144
+ let valueNode = this.value_parser.parse_value(value_start, trimmed_end, value_start_line, value_start_column);
144
145
  this.arena.set_first_child(declaration, valueNode);
145
146
  } else {
146
- let rawNode = this.arena.create_node(8, trimmed[0], trimmed[1] - trimmed[0], value_start_line, value_start_column);
147
+ let rawNode = this.arena.create_node(8, trimmed_start, trimmed_end - trimmed_start, value_start_line, value_start_column);
147
148
  this.arena.set_first_child(declaration, rawNode);
148
149
  }
149
150
  } else {
@@ -1,7 +1,3 @@
1
- /**
2
- * Check if a character code is whitespace (space, tab, newline, CR, or FF)
3
- * @internal
4
- */
5
1
  function is_whitespace(ch) {
6
2
  return ch === 32 || ch === 9 || ch === 10 || ch === 13 || ch === 12;
7
3
  }
@@ -9,7 +5,6 @@ function is_whitespace(ch) {
9
5
  function is_combinator(ch) {
10
6
  return ch === 62 || ch === 43 || ch === 126;
11
7
  }
12
- /** @internal */
13
8
  function is_digit(ch) {
14
9
  return ch >= 48 && ch <= 57;
15
10
  }
@@ -27,11 +22,6 @@ function str_equals(a, b) {
27
22
  }
28
23
  return true;
29
24
  }
30
- /**
31
- * Case-insensitive equality between `source[start, end)` and `literal`, without allocating
32
- * a substring first. Same semantics as `str_equals(literal, source.substring(start, end))`.
33
- * `literal` MUST be lowercase.
34
- */
35
25
  function str_equals_range(source, start, end, literal) {
36
26
  if (end - start !== literal.length) return false;
37
27
  for (let i = 0; i < literal.length; i++) {
@@ -41,6 +31,11 @@ function str_equals_range(source, start, end, literal) {
41
31
  }
42
32
  return true;
43
33
  }
34
+ function is_and_or_not_range(source, start, end) {
35
+ let length = end - start;
36
+ if (length === 3) return str_equals_range(source, start, end, "and") || str_equals_range(source, start, end, "not");
37
+ return length === 2 && str_equals_range(source, start, end, "or");
38
+ }
44
39
  /** Case-insensitive ASCII prefix check without allocations. `prefix` MUST be lowercase. */
45
40
  function str_starts_with(str, prefix) {
46
41
  if (str.length < prefix.length) return false;
@@ -95,7 +90,6 @@ function is_custom(str) {
95
90
  if (str.length < 3) return false;
96
91
  return str.charCodeAt(0) === 45 && str.charCodeAt(1) === 45;
97
92
  }
98
- /** Strip a vendor prefix, e.g. `-webkit-keyframes` → `keyframes`. Returns the input unchanged if it has no prefix. */
99
93
  function strip_vendor_prefix(str) {
100
94
  if (!is_vendor_prefixed(str)) return str;
101
95
  for (let i = 2; i < str.length; i++) if (str.charCodeAt(i) === 45) return str.substring(i + 1);
@@ -146,4 +140,4 @@ function parse_dimension(text) {
146
140
  };
147
141
  }
148
142
  //#endregion
149
- export { is_vendor_prefixed as a, str_equals_range as c, strip_vendor_prefix as d, is_custom as i, str_index_of as l, parse_dimension as n, is_whitespace as o, is_combinator as r, str_equals as s, dimension_number_end as t, str_starts_with as u };
143
+ export { is_custom as a, str_equals as c, str_starts_with as d, strip_vendor_prefix as f, is_combinator as i, str_equals_range as l, parse_dimension as n, is_vendor_prefixed as o, is_and_or_not_range as r, is_whitespace as s, dimension_number_end as t, str_index_of as u };
@@ -6,11 +6,10 @@
6
6
  * substrings for both.
7
7
  * @internal
8
8
  */
9
- declare function dimension_number_end(text: string): number;
9
+ export declare function dimension_number_end(text: string): number;
10
10
  /** Parse a dimension string into value and unit, e.g. "100px" → { value: 100, unit: "px" } or "2%" → { value: 2, unit: "%" } */
11
- declare function parse_dimension(text: string): {
11
+ export declare function parse_dimension(text: string): {
12
12
  value: number;
13
13
  unit: string;
14
14
  };
15
- //#endregion
16
- export { dimension_number_end, parse_dimension };
15
+ //#endregion
@@ -1,2 +1 @@
1
- import { n as parse_dimension, t as dimension_number_end } from "./parse-dimension-CQELWb5z.js";
2
- export { dimension_number_end, parse_dimension };
1
+ export { t as dimension_number_end, n as parse_dimension } from "./parse-dimension-CIaPOmBc.js";
@@ -1,15 +1,13 @@
1
- import { t as Lexer } from "./tokenize-DK24ACbY.js";
1
+ import { t as Lexer } from "./tokenize-0ADWAELW.js";
2
2
  import { l as CSSDataArena } from "./arena-e9O_g2AN.js";
3
- import { c as str_equals_range, o as is_whitespace, r as is_combinator } from "./parse-dimension-CQELWb5z.js";
4
- import { t as CSSNode } from "./css-node-C6TLE3qd.js";
3
+ import { i as is_combinator, l as str_equals_range, s as is_whitespace } from "./parse-dimension-CIaPOmBc.js";
4
+ import { t as CSSNode } from "./css-node-DfJEsKN0.js";
5
5
  import { ANplusBParser } from "./parse-anplusb.js";
6
6
  //#region src/parse-utils.ts
7
- /** @internal */
8
7
  function skip_whitespace_forward(source, pos, end) {
9
8
  while (pos < end && is_whitespace(source.charCodeAt(pos))) pos++;
10
9
  return pos;
11
10
  }
12
- /** @internal */
13
11
  function skip_whitespace_and_comments_forward(source, pos, end) {
14
12
  while (pos < end) {
15
13
  let ch = source.charCodeAt(pos);
@@ -32,7 +30,6 @@ function skip_whitespace_and_comments_forward(source, pos, end) {
32
30
  }
33
31
  return pos;
34
32
  }
35
- /** @internal */
36
33
  function skip_whitespace_and_comments_backward(source, pos, start) {
37
34
  while (pos > start) {
38
35
  let ch = source.charCodeAt(pos - 1);
@@ -55,17 +52,12 @@ function skip_whitespace_and_comments_backward(source, pos, start) {
55
52
  }
56
53
  return pos;
57
54
  }
58
- /**
59
- * Trims whitespace and CSS comments from both ends; returns null if the range is only whitespace/comments.
60
- * @internal
61
- */
62
55
  function trim_boundaries(source, start, end) {
63
56
  start = skip_whitespace_and_comments_forward(source, start, end);
64
57
  end = skip_whitespace_and_comments_backward(source, end, start);
65
58
  if (start >= end) return null;
66
59
  return [start, end];
67
60
  }
68
- /** Find the position of the first ':' at parenthesis depth 0 in [start, end). Returns -1 if not found. @internal */
69
61
  function find_colon_at_depth_zero(source, start, end) {
70
62
  let depth = 0;
71
63
  for (let i = start; i < end; i++) {
@@ -424,18 +416,20 @@ var SelectorParser = class {
424
416
  this.arena.set_content_start_delta(node, func_name_start - start);
425
417
  this.arena.set_content_length(node, func_name_end - func_name_start);
426
418
  this.arena.set_flag(node, 64);
427
- if (content_end > content_start) if (this.is_nth_pseudo(func_name_start, func_name_end)) {
428
- let child = this.parse_nth_expression(content_start, content_end);
429
- if (child !== null) this.arena.set_first_child(node, child);
430
- } else if (str_equals_range(this.source, func_name_start, func_name_end, "lang")) this.parse_lang_identifiers(content_start, content_end, node);
431
- else {
432
- let saved_selector_end = this.selector_end;
433
- const saved = this.lexer.save_position();
434
- let allow_relative = str_equals_range(this.source, func_name_start, func_name_end, "has");
435
- let child_selector = this.parse_selector(content_start, content_end, this.lexer.line, this.lexer.column, allow_relative);
436
- this.selector_end = saved_selector_end;
437
- this.lexer.restore_position(saved);
438
- if (child_selector !== null) this.arena.set_first_child(node, child_selector);
419
+ if (content_end > content_start) {
420
+ if (this.is_nth_pseudo(func_name_start, func_name_end)) {
421
+ let child = this.parse_nth_expression(content_start, content_end);
422
+ if (child !== null) this.arena.set_first_child(node, child);
423
+ } else if (str_equals_range(this.source, func_name_start, func_name_end, "lang")) this.parse_lang_identifiers(content_start, content_end, node);
424
+ else {
425
+ let saved_selector_end = this.selector_end;
426
+ const saved = this.lexer.save_position();
427
+ let allow_relative = str_equals_range(this.source, func_name_start, func_name_end, "has");
428
+ let child_selector = this.parse_selector(content_start, content_end, this.lexer.line, this.lexer.column, allow_relative);
429
+ this.selector_end = saved_selector_end;
430
+ this.lexer.restore_position(saved);
431
+ if (child_selector !== null) this.arena.set_first_child(node, child_selector);
432
+ }
439
433
  }
440
434
  return node;
441
435
  }
@@ -2,7 +2,7 @@ import { l as CSSDataArena } from "./arena-BGvFdbj5.js";
2
2
  import { R as Selector, z as SelectorList } from "./node-types-YnOKcNfU.js";
3
3
  //#region src/parse-selector.d.ts
4
4
  /** @internal */
5
- declare class SelectorParser {
5
+ export declare class SelectorParser {
6
6
  private lexer;
7
7
  private arena;
8
8
  private source;
@@ -32,7 +32,6 @@ declare class SelectorParser {
32
32
  private create_node;
33
33
  private skip_whitespace;
34
34
  }
35
- declare function parse_selector_list(source: string): SelectorList;
36
- declare function parse_selector(source: string): Selector;
37
- //#endregion
38
- export { SelectorParser, parse_selector, parse_selector_list };
35
+ export declare function parse_selector_list(source: string): SelectorList;
36
+ export declare function parse_selector(source: string): Selector;
37
+ //#endregion
@@ -1,2 +1 @@
1
- import { n as parse_selector, r as parse_selector_list, t as SelectorParser } from "./parse-selector-Ce5HUZJ5.js";
2
- export { SelectorParser, parse_selector, parse_selector_list };
1
+ export { t as SelectorParser, n as parse_selector, r as parse_selector_list } from "./parse-selector-rTXB4IN2.js";
@@ -2,7 +2,7 @@ import { l as CSSDataArena } from "./arena-BGvFdbj5.js";
2
2
  import { X as Value } from "./node-types-YnOKcNfU.js";
3
3
  //#region src/parse-value.d.ts
4
4
  /** @internal */
5
- declare class ValueParser {
5
+ export declare class ValueParser {
6
6
  private nodes;
7
7
  private arena;
8
8
  constructor(arena: CSSDataArena, source: string);
@@ -13,6 +13,5 @@ declare class ValueParser {
13
13
  * @param value_string - The CSS value to parse (e.g., "1px solid red")
14
14
  * @returns A CSSNode VALUE wrapper containing the parsed value tokens as children
15
15
  */
16
- declare function parse_value(value_string: string): Value;
17
- //#endregion
18
- export { ValueParser, parse_value };
16
+ export declare function parse_value(value_string: string): Value;
17
+ //#endregion
@@ -1,6 +1,6 @@
1
1
  import { l as CSSDataArena } from "./arena-e9O_g2AN.js";
2
- import { t as CSSNode } from "./css-node-C6TLE3qd.js";
3
- import { t as ValueNodeParser } from "./value-node-parser-DfkneBdM.js";
2
+ import { t as CSSNode } from "./css-node-DfJEsKN0.js";
3
+ import { t as ValueNodeParser } from "./value-node-parser-DizbcN1a.js";
4
4
  //#region src/parse-value.ts
5
5
  /** @internal */
6
6
  var ValueParser = class {
package/dist/parse.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { l as CSSDataArena } from "./arena-BGvFdbj5.js";
2
- import { t as CommentInfo } from "./tokenize-CDEnYcVG.js";
2
+ import { t as CommentInfo } from "./tokenize-CaWtrHw_.js";
3
3
  import { H as StyleSheet } from "./node-types-YnOKcNfU.js";
4
4
  //#region src/parse.d.ts
5
- interface ParserOptions {
5
+ export interface ParserOptions {
6
6
  parse_values?: boolean;
7
7
  parse_selectors?: boolean;
8
8
  parse_atrule_preludes?: boolean;
9
9
  on_comment?: (info: CommentInfo) => void;
10
10
  }
11
11
  /** @internal */
12
- declare class Parser {
12
+ export declare class Parser {
13
13
  private source;
14
14
  private lexer;
15
15
  private arena;
@@ -40,6 +40,5 @@ declare class Parser {
40
40
  * @param options - Parser options
41
41
  * @returns The root CSSNode of the AST
42
42
  */
43
- declare function parse(source: string, options?: ParserOptions): StyleSheet;
44
- //#endregion
45
- export { Parser, ParserOptions, parse };
43
+ export declare function parse(source: string, options?: ParserOptions): StyleSheet;
44
+ //#endregion
package/dist/parse.js CHANGED
@@ -1,7 +1,7 @@
1
- import { t as Lexer } from "./tokenize-DK24ACbY.js";
1
+ import { t as Lexer } from "./tokenize-0ADWAELW.js";
2
2
  import { l as CSSDataArena } from "./arena-e9O_g2AN.js";
3
- import { t as CSSNode } from "./css-node-C6TLE3qd.js";
4
- import { a as skip_whitespace_and_comments_backward, s as trim_boundaries, t as SelectorParser } from "./parse-selector-Ce5HUZJ5.js";
3
+ import { t as CSSNode } from "./css-node-DfJEsKN0.js";
4
+ import { a as skip_whitespace_and_comments_backward, o as skip_whitespace_and_comments_forward, t as SelectorParser } from "./parse-selector-rTXB4IN2.js";
5
5
  import { AtRulePreludeParser } from "./parse-atrule-prelude.js";
6
6
  import { DeclarationParser } from "./parse-declaration.js";
7
7
  //#region src/parse.ts
@@ -187,15 +187,18 @@ var Parser = class {
187
187
  prelude_end = this.lexer.token_end;
188
188
  this.next_token();
189
189
  }
190
- let trimmed = trim_boundaries(this.source, prelude_start, prelude_end);
190
+ let trimmed_start = skip_whitespace_and_comments_forward(this.source, prelude_start, prelude_end);
191
+ let trimmed_end = skip_whitespace_and_comments_backward(this.source, prelude_end, trimmed_start);
191
192
  let prelude_wrapper = null;
192
- if (trimmed) if (this.prelude_parser) {
193
- let prelude_nodes = this.prelude_parser.parse_prelude(at_rule_name, trimmed[0], trimmed[1], at_rule_line, at_rule_column);
194
- if (prelude_nodes.length > 0) {
195
- prelude_wrapper = this.arena.create_node(40, trimmed[0], trimmed[1] - trimmed[0], at_rule_line, at_rule_column);
196
- this.arena.append_children(prelude_wrapper, prelude_nodes);
197
- } else prelude_wrapper = this.arena.create_node(8, trimmed[0], trimmed[1] - trimmed[0], at_rule_line, at_rule_column);
198
- } else prelude_wrapper = this.arena.create_node(8, trimmed[0], trimmed[1] - trimmed[0], at_rule_line, at_rule_column);
193
+ if (trimmed_start < trimmed_end) {
194
+ if (this.prelude_parser) {
195
+ let prelude_nodes = this.prelude_parser.parse_prelude(at_rule_name, trimmed_start, trimmed_end, at_rule_line, at_rule_column);
196
+ if (prelude_nodes.length > 0) {
197
+ prelude_wrapper = this.arena.create_node(40, trimmed_start, trimmed_end - trimmed_start, at_rule_line, at_rule_column);
198
+ this.arena.append_children(prelude_wrapper, prelude_nodes);
199
+ } else prelude_wrapper = this.arena.create_node(8, trimmed_start, trimmed_end - trimmed_start, at_rule_line, at_rule_column);
200
+ } else prelude_wrapper = this.arena.create_node(8, trimmed_start, trimmed_end - trimmed_start, at_rule_line, at_rule_column);
201
+ }
199
202
  let last_end = this.lexer.token_end;
200
203
  if (this.peek_type() === 23) {
201
204
  let block_start = this.lexer.token_end;
@@ -675,6 +675,18 @@ var Lexer = class {
675
675
  token_column: this.token_column
676
676
  };
677
677
  }
678
+ save_position_into(target) {
679
+ target.pos = this.pos;
680
+ target.line = this._line;
681
+ target.column = this.pos - this._line_offset + 1;
682
+ target._line_offset = this._line_offset;
683
+ target.token_type = this.token_type;
684
+ target.token_start = this.token_start;
685
+ target.token_end = this.token_end;
686
+ target.token_line = this.token_line;
687
+ target.token_column = this.token_column;
688
+ return target;
689
+ }
678
690
  /**
679
691
  * Restore lexer state from saved position
680
692
  * @param saved The saved position to restore
@@ -701,16 +713,7 @@ var Lexer = class {
701
713
  continue;
702
714
  }
703
715
  if (ch === CHAR_FORWARD_SLASH && this.pos + 1 < end && this.source.charCodeAt(this.pos + 1) === CHAR_ASTERISK) {
704
- this.advance();
705
- this.advance();
706
- while (this.pos < end) {
707
- if (this.source.charCodeAt(this.pos) === CHAR_ASTERISK && this.pos + 1 < end && this.source.charCodeAt(this.pos + 1) === CHAR_FORWARD_SLASH) {
708
- this.advance();
709
- this.advance();
710
- break;
711
- }
712
- this.advance();
713
- }
716
+ this._skip_comment();
714
717
  continue;
715
718
  }
716
719
  break;
@@ -111,6 +111,7 @@ declare class Lexer {
111
111
  * @returns Object containing all lexer state
112
112
  */
113
113
  save_position(): LexerPosition;
114
+ save_position_into(target: LexerPosition): LexerPosition;
114
115
  /**
115
116
  * Restore lexer state from saved position
116
117
  * @param saved The saved position to restore
@@ -1,2 +1,2 @@
1
- import { i as tokenize, n as Lexer, r as LexerPosition, t as CommentInfo } from "./tokenize-CDEnYcVG.js";
1
+ import { i as tokenize, n as Lexer, r as LexerPosition, t as CommentInfo } from "./tokenize-CaWtrHw_.js";
2
2
  export { CommentInfo, Lexer, LexerPosition, tokenize };
package/dist/tokenize.js CHANGED
@@ -1,2 +1 @@
1
- import { n as tokenize, t as Lexer } from "./tokenize-DK24ACbY.js";
2
- export { Lexer, tokenize };
1
+ export { t as Lexer, n as tokenize } from "./tokenize-0ADWAELW.js";
@@ -1,9 +1,8 @@
1
- import { t as Lexer } from "./tokenize-DK24ACbY.js";
1
+ import { t as Lexer } from "./tokenize-0ADWAELW.js";
2
2
  import "./arena-e9O_g2AN.js";
3
- import { c as str_equals_range, s as str_equals } from "./parse-dimension-CQELWb5z.js";
4
- import { i as find_colon_at_depth_zero, o as skip_whitespace_and_comments_forward, s as trim_boundaries, t as SelectorParser } from "./parse-selector-Ce5HUZJ5.js";
3
+ import { l as str_equals_range, r as is_and_or_not_range } from "./parse-dimension-CIaPOmBc.js";
4
+ import { i as find_colon_at_depth_zero, o as skip_whitespace_and_comments_forward, s as trim_boundaries, t as SelectorParser } from "./parse-selector-rTXB4IN2.js";
5
5
  //#region src/parse-condition.ts
6
- /** @internal */
7
6
  var ConditionParser = class {
8
7
  lexer;
9
8
  arena;
@@ -18,12 +17,8 @@ var ConditionParser = class {
18
17
  this.value_node_parser = value_node_parser;
19
18
  this.selector_parser = new SelectorParser(arena, source);
20
19
  }
21
- get end_position() {
22
- return [
23
- this.lexer.pos,
24
- this.lexer.line,
25
- this.lexer.column
26
- ];
20
+ seek_to_end(target) {
21
+ target.seek(this.lexer.pos, this.lexer.line, this.lexer.column);
27
22
  }
28
23
  create_node(type, start, end) {
29
24
  return this.arena.create_node(type, start, end - start, this.lexer.token_line, this.lexer.token_column);
@@ -35,9 +30,8 @@ var ConditionParser = class {
35
30
  }
36
31
  return this.lexer.next_token_fast(false);
37
32
  }
38
- is_and_or_not(str) {
39
- return str_equals("and", str) || str_equals("or", str) || str_equals("not", str);
40
- }
33
+ paren_content_end = 0;
34
+ paren_close_end = 0;
41
35
  scan_matching_paren() {
42
36
  let depth = 1;
43
37
  let content_end = this.lexer.pos;
@@ -53,11 +47,9 @@ var ConditionParser = class {
53
47
  }
54
48
  } else if (token_type === 26) break;
55
49
  }
56
- return [
57
- content_end,
58
- close_end,
59
- depth === 0
60
- ];
50
+ this.paren_content_end = content_end;
51
+ this.paren_close_end = close_end;
52
+ return depth === 0;
61
53
  }
62
54
  parse_feature_value(start, end) {
63
55
  return this.value_node_parser.parse_chain(start, end, this.lexer.line, this.lexer.column);
@@ -147,15 +139,6 @@ var ConditionParser = class {
147
139
  if (first_child !== 0) this.arena.set_first_child(range_node, first_child);
148
140
  return range_node;
149
141
  }
150
- /**
151
- * Parse the content of a media feature — everything between its parentheses, already
152
- * known by the caller as `[content_start, content_end)`. `feature_start`/`feature_end`
153
- * are the span of the feature node itself: for a real `@media (min-width: 768px)` feature
154
- * this includes the surrounding parens (`feature_start < content_start`); for if()'s
155
- * `media(min-width: 768px)`, media()'s own parens already delimit the content, so callers
156
- * pass `feature_start === content_start` and `feature_end === content_end`.
157
- * Returns a MEDIA_FEATURE (name/boolean/name:value) or FEATURE_RANGE (comparison syntax) node.
158
- */
159
142
  parse_media_feature_content(feature_start, feature_end, content_start, content_end) {
160
143
  this.end = content_end;
161
144
  let has_comparison = false;
@@ -209,7 +192,9 @@ var ConditionParser = class {
209
192
  this.next_token();
210
193
  let feature_start = this.lexer.token_start;
211
194
  let content_start = this.lexer.pos;
212
- let [content_end, feature_end, matched] = this.scan_matching_paren();
195
+ let matched = this.scan_matching_paren();
196
+ let content_end = this.paren_content_end;
197
+ let feature_end = this.paren_close_end;
213
198
  if (!matched) return null;
214
199
  return this.parse_media_feature_content(feature_start, feature_end, content_start, content_end);
215
200
  }
@@ -217,41 +202,31 @@ var ConditionParser = class {
217
202
  this.end = end;
218
203
  this.lexer.seek(func_start, line, column);
219
204
  this.next_token();
220
- let func_name = this.source.substring(this.lexer.token_start, this.lexer.token_end - 1);
205
+ let func_name_start = this.lexer.token_start;
206
+ let func_name_end = this.lexer.token_end - 1;
221
207
  let content_start = this.lexer.token_end;
222
- let [content_end, func_end] = this.scan_matching_paren();
208
+ this.scan_matching_paren();
209
+ let content_end = this.paren_content_end;
210
+ let func_end = this.paren_close_end;
223
211
  let func_node = this.create_node(15, func_start, func_end);
224
212
  this.arena.set_content_start_delta(func_node, 0);
225
- this.arena.set_content_length(func_node, func_name.length);
213
+ this.arena.set_content_length(func_node, func_name_end - func_name_start);
226
214
  this.arena.set_value_start_delta(func_node, content_start - func_start);
227
215
  this.arena.set_value_length(func_node, content_end - content_start);
228
- if (str_equals("selector", func_name)) {
216
+ if (str_equals_range(this.source, func_name_start, func_name_end, "selector")) {
229
217
  let selector_list = this.selector_parser.parse_selector(content_start, content_end, this.lexer.line, this.lexer.column);
230
218
  if (selector_list !== null) this.arena.set_first_child(func_node, selector_list);
231
- } else if (str_equals("style", func_name)) {
219
+ } else if (str_equals_range(this.source, func_name_start, func_name_end, "style")) {
232
220
  let decl_child = this.parse_supports_declaration_content(content_start, content_end);
233
221
  if (decl_child !== null) this.arena.set_first_child(func_node, decl_child);
234
222
  }
235
223
  return func_node;
236
224
  }
237
- /**
238
- * Parse a single `(property: value)` supports declaration from a content range — the
239
- * `<style-feature>`/`<supports-feature>` grammar shared by `style()`, `@supports (…)`, and
240
- * `@import … supports(…)`. Returns null if no top-level ':' is found.
241
- */
242
225
  parse_supports_declaration_content(content_start, content_end) {
243
226
  let colon_pos = find_colon_at_depth_zero(this.source, content_start, content_end);
244
227
  if (colon_pos === -1) return null;
245
228
  return this.create_supports_declaration(content_start, content_end, colon_pos);
246
229
  }
247
- /**
248
- * Parse a `<supports-condition>` — the compound and/or/not grammar shared by `@supports`
249
- * preludes and if()'s `supports(...)` condition function: parenthesized `(property: value)`
250
- * declarations, `and`/`or`/`not` logical operators, and nested function conditions
251
- * (`selector()`, `style()`, etc.), chained as flat siblings.
252
- * `start`/`end` bound the range to scan; the caller has already positioned nothing — this
253
- * seeks its own lexer, so it's safe to call with any sub-range of the source.
254
- */
255
230
  parse_supports_condition(start, end, line, column) {
256
231
  let saved_end = this.end;
257
232
  this.end = end;
@@ -265,7 +240,9 @@ var ConditionParser = class {
265
240
  if (token_type === 21) {
266
241
  let feature_start = this.lexer.token_start;
267
242
  let content_start = this.lexer.pos;
268
- let [content_end, feature_end, matched] = this.scan_matching_paren();
243
+ let matched = this.scan_matching_paren();
244
+ let content_end = this.paren_content_end;
245
+ let feature_end = this.paren_close_end;
269
246
  if (matched) {
270
247
  let query = this.create_node(36, feature_start, feature_end);
271
248
  let trimmed = trim_boundaries(this.source, content_start, content_end);
@@ -278,9 +255,10 @@ var ConditionParser = class {
278
255
  nodes.push(query);
279
256
  }
280
257
  } else if (token_type === 1) {
281
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
282
- if (this.is_and_or_not(text)) {
283
- let op = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
258
+ let token_start = this.lexer.token_start;
259
+ let token_end = this.lexer.token_end;
260
+ if (is_and_or_not_range(this.source, token_start, token_end)) {
261
+ let op = this.create_node(38, token_start, token_end);
284
262
  nodes.push(op);
285
263
  }
286
264
  } else if (token_type === 2) nodes.push(this.parse_function_condition(this.lexer.token_start, this.end, this.lexer.token_line, this.lexer.token_column));
@@ -291,7 +269,6 @@ var ConditionParser = class {
291
269
  };
292
270
  //#endregion
293
271
  //#region src/value-node-parser.ts
294
- /** @internal */
295
272
  var ValueNodeParser = class ValueNodeParser {
296
273
  lexer;
297
274
  arena;
@@ -360,6 +337,8 @@ var ValueNodeParser = class ValueNodeParser {
360
337
  if (ch === 43 || ch === 45 || ch === 42 || ch === 47) return this.create_node(16, start, end);
361
338
  return null;
362
339
  }
340
+ paren_content_end = 0;
341
+ paren_close_end = 0;
363
342
  scan_matching_paren(bounded) {
364
343
  let depth = 1;
365
344
  let content_end = this.lexer.pos;
@@ -378,11 +357,9 @@ var ValueNodeParser = class ValueNodeParser {
378
357
  }
379
358
  }
380
359
  }
381
- return [
382
- content_end,
383
- close_end,
384
- depth === 0
385
- ];
360
+ this.paren_content_end = content_end;
361
+ this.paren_close_end = close_end;
362
+ return depth === 0;
386
363
  }
387
364
  parse_function_node(start, end) {
388
365
  let name_end = end - 1;
@@ -401,7 +378,9 @@ var ValueNodeParser = class ValueNodeParser {
401
378
  let func_end = end;
402
379
  let content_start = end;
403
380
  let content_end = end;
404
- let [scanned_content_end, scanned_func_end, matched] = this.scan_matching_paren(false);
381
+ let matched = this.scan_matching_paren(false);
382
+ let scanned_content_end = this.paren_content_end;
383
+ let scanned_func_end = this.paren_close_end;
405
384
  if (matched) {
406
385
  content_end = scanned_content_end;
407
386
  func_end = scanned_func_end;
@@ -445,17 +424,6 @@ var ValueNodeParser = class ValueNodeParser {
445
424
  if (first_arg !== 0) this.arena.set_first_child(node, first_arg);
446
425
  return node;
447
426
  }
448
- /**
449
- * Parse an if() inline conditional function.
450
- *
451
- * Spec grammar (CSS Values Level 5):
452
- * if( <if-branch>+ )
453
- * <if-branch> = <if-condition> : <declaration-value>? ;?
454
- * <if-condition> = style(…) | media(…) | supports(…) | else
455
- *
456
- * Each branch becomes an IF_BRANCH child (see the `IfBranch` type in node-types.ts
457
- * for its shape). Colons/semicolons here are structural separators, not OPERATOR nodes.
458
- */
459
427
  parse_if_function_node(start, end) {
460
428
  let name_end = end - 1;
461
429
  let save_line = this.lexer.token_line;
@@ -557,9 +525,6 @@ var ValueNodeParser = class ValueNodeParser {
557
525
  this.arena.append_children(node, branches);
558
526
  return node;
559
527
  }
560
- is_and_or_not(str) {
561
- return str_equals("and", str) || str_equals("or", str) || str_equals("not", str);
562
- }
563
528
  next_significant_token() {
564
529
  while (this.lexer.pos < this.end) {
565
530
  this.lexer.next_token_fast(false);
@@ -569,22 +534,9 @@ var ValueNodeParser = class ValueNodeParser {
569
534
  }
570
535
  return 26;
571
536
  }
572
- /**
573
- * Parse an if()-branch condition:
574
- * <if-condition> = <boolean-expr[ <if-test> ]> | else
575
- * <if-test> = style(…) | media(…) | supports(…)
576
- * i.e. a single test function, the bare "else" identifier, or those test functions
577
- * combined with not/and/or (e.g. "not style(--x: 1)", "style(--a: 1) and media(width > 600px)").
578
- * Called with the lexer's current token already positioned at the condition's first token.
579
- * A simple single-function/"else" condition returns that node directly, unwrapped (matching
580
- * prior behavior); a compound not/and/or condition wraps the flat operator/function chain in
581
- * an IF_CONDITION node so IfBranch.condition/.value (single first_child/next_sibling hops)
582
- * still see exactly one node for "the condition".
583
- */
584
537
  parse_if_condition() {
585
538
  if (this.lexer.token_type === 1) {
586
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
587
- if (str_equals("else", text)) return this.parse_value_node();
539
+ if (str_equals_range(this.source, this.lexer.token_start, this.lexer.token_end, "else")) return this.parse_value_node();
588
540
  }
589
541
  let first = 0;
590
542
  let last = 0;
@@ -596,10 +548,11 @@ var ValueNodeParser = class ValueNodeParser {
596
548
  let is_operator = false;
597
549
  if (tt === 2) component = this.parse_if_condition_function(this.lexer.token_start, this.lexer.token_end);
598
550
  else if (tt === 1) {
599
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
600
- if (this.is_and_or_not(text)) {
551
+ let token_start = this.lexer.token_start;
552
+ let token_end = this.lexer.token_end;
553
+ if (is_and_or_not_range(this.source, token_start, token_end)) {
601
554
  is_operator = true;
602
- component = this.arena.create_node(38, this.lexer.token_start, this.lexer.token_end - this.lexer.token_start, this.lexer.token_line, this.lexer.token_column);
555
+ component = this.arena.create_node(38, token_start, token_end - token_start, this.lexer.token_line, this.lexer.token_column);
603
556
  } else component = this.parse_value_node();
604
557
  } else component = this.parse_value_node();
605
558
  if (component !== null) {
@@ -616,8 +569,7 @@ var ValueNodeParser = class ValueNodeParser {
616
569
  continue;
617
570
  }
618
571
  if (next_tt === 1) {
619
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
620
- if (this.is_and_or_not(text)) {
572
+ if (is_and_or_not_range(this.source, this.lexer.token_start, this.lexer.token_end)) {
621
573
  compound = true;
622
574
  continue;
623
575
  }
@@ -634,28 +586,16 @@ var ValueNodeParser = class ValueNodeParser {
634
586
  this.arena.set_first_child(wrapper, first);
635
587
  return wrapper;
636
588
  }
637
- /**
638
- * Parse a condition function inside if() — style(), supports(), or media(). Content parsing
639
- * is delegated to the shared ConditionParser (see parse-condition.ts), so these produce the
640
- * same node shapes real `@supports`/`@media` conditions do:
641
- * style()/supports() → SUPPORTS_DECLARATION(s) — supports() gets the full compound
642
- * <supports-condition> grammar (and/or/not, nested conditions), same as `@supports`.
643
- * media() → a single MEDIA_FEATURE or FEATURE_RANGE (comparison syntax), same as `@media`.
644
- * anything else → generic value nodes, as before.
645
- *
646
- * Called with the current token at TOKEN_FUNCTION (the '(' already consumed).
647
- * @param func_start Offset of the function name's first char.
648
- * @param token_end Offset right after '(' (== lexer.token_end here).
649
- */
650
589
  parse_if_condition_function(func_start, token_end) {
651
590
  let func_name_end = token_end - 1;
652
- let func_name = this.source.substring(func_start, func_name_end);
653
591
  let func_line = this.lexer.token_line;
654
592
  let func_col = this.lexer.token_column;
655
593
  let content_start = token_end;
656
594
  let content_end = content_start;
657
595
  let func_end = content_start;
658
- let [scanned_content_end, scanned_func_end, matched] = this.scan_matching_paren(true);
596
+ let matched = this.scan_matching_paren(true);
597
+ let scanned_content_end = this.paren_content_end;
598
+ let scanned_func_end = this.paren_close_end;
659
599
  if (matched) {
660
600
  content_end = scanned_content_end;
661
601
  func_end = scanned_func_end;
@@ -666,20 +606,19 @@ var ValueNodeParser = class ValueNodeParser {
666
606
  this.arena.set_value_start_delta(func_node, content_start - func_start);
667
607
  this.arena.set_value_length(func_node, content_end - content_start);
668
608
  let child_nodes = [];
669
- if (str_equals("style", func_name)) {
609
+ if (str_equals_range(this.source, func_start, func_name_end, "style")) {
670
610
  let decl = this.condition_parser.parse_supports_declaration_content(content_start, content_end);
671
611
  if (decl === null) child_nodes = this.condition_parser.parse_supports_condition(content_start, content_end, func_line, func_col);
672
612
  else child_nodes = [decl];
673
- } else if (str_equals("supports", func_name)) {
613
+ } else if (str_equals_range(this.source, func_start, func_name_end, "supports")) {
674
614
  let decl = this.condition_parser.parse_supports_declaration_content(content_start, content_end);
675
615
  if (decl === null) child_nodes = this.condition_parser.parse_supports_condition(content_start, content_end, func_line, func_col);
676
616
  else child_nodes = [decl];
677
- } else if (str_equals("media", func_name)) child_nodes = [this.condition_parser.parse_media_feature_content(content_start, content_end, content_start, content_end)];
617
+ } else if (str_equals_range(this.source, func_start, func_name_end, "media")) child_nodes = [this.condition_parser.parse_media_feature_content(content_start, content_end, content_start, content_end)];
678
618
  else child_nodes = this.parse_value_nodes_in_range(content_start, content_end);
679
619
  this.arena.append_children(func_node, child_nodes);
680
620
  return func_node;
681
621
  }
682
- /** Parse value tokens in a source sub-range using save/restore to protect lexer state. */
683
622
  parse_value_nodes_in_range(start, end) {
684
623
  let saved_end = this.end;
685
624
  let saved_pos = this.lexer.save_position();
package/dist/walk.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  import { o as CSSNode, t as AnyNode } from "./node-types-YnOKcNfU.js";
2
2
  //#region src/walk.d.ts
3
- declare const SKIP: unique symbol;
4
- declare const BREAK: unique symbol;
3
+ export declare const SKIP: unique symbol;
4
+ export declare const BREAK: unique symbol;
5
5
  type WalkCallback = (node: AnyNode, depth: number) => void | typeof SKIP | typeof BREAK;
6
6
  /**
7
7
  * Walk the AST depth-first, calling `callback` for each node. Return SKIP to skip
8
8
  * children, BREAK to stop. `depth` tracks rule nesting (STYLE_RULE/AT_RULE only),
9
9
  * not tree depth.
10
10
  */
11
- declare function walk(node: CSSNode, callback: WalkCallback, depth?: number): boolean;
11
+ export declare function walk(node: CSSNode, callback: WalkCallback, depth?: number): boolean;
12
12
  type WalkEnterLeaveCallback = (node: AnyNode) => void | typeof SKIP | typeof BREAK;
13
13
  interface WalkEnterLeaveOptions {
14
14
  enter?: WalkEnterLeaveCallback;
@@ -18,6 +18,5 @@ interface WalkEnterLeaveOptions {
18
18
  * Walk the AST depth-first, calling `enter` before children and `leave` after.
19
19
  * SKIP in enter skips children (leave still runs); BREAK stops (leave doesn't run).
20
20
  */
21
- declare function traverse(node: CSSNode, { enter, leave }?: WalkEnterLeaveOptions): boolean;
22
- //#endregion
23
- export { BREAK, SKIP, traverse, walk };
21
+ export declare function traverse(node: CSSNode, { enter, leave }?: WalkEnterLeaveOptions): boolean;
22
+ //#endregion
package/dist/walk.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./arena-e9O_g2AN.js";
2
- import { t as CSSNode } from "./css-node-C6TLE3qd.js";
2
+ import { t as CSSNode } from "./css-node-DfJEsKN0.js";
3
3
  import "./constants.js";
4
4
  //#region src/walk.ts
5
5
  const SKIP = Symbol("SKIP");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectwallace/css-parser",
3
- "version": "0.18.7",
3
+ "version": "0.18.9",
4
4
  "description": "High-performance CSS lexer and parser, optimized for CSS inspection and analysis",
5
5
  "keywords": [
6
6
  "ast",
@@ -77,22 +77,20 @@
77
77
  },
78
78
  "devDependencies": {
79
79
  "@projectwallace/preset-oxlint": "^0.0.11",
80
- "@types/node": "^26.1.1",
81
- "@vitest/coverage-v8": "^4.1.9",
82
- "bootstrap": "^5.3.8",
83
- "css-tree": "^3.1.0",
84
- "knip": "^6.18.0",
85
- "oxfmt": "^0.60.0",
86
- "oxlint": "^1.71.0",
87
- "pkg-pr-new": "^0.0.88",
88
- "postcss": "^8.5.15",
89
- "publint": "^0.3.21",
90
- "tailwindcss": "^2.2.8",
91
- "tinybench": "^6.0.2",
92
- "tsdown": "^0.22.3",
80
+ "@types/node": "^26.6.5",
81
+ "@vitest/coverage-v8": "^5.0.3",
82
+ "css-tree": "^3.2.1",
83
+ "knip": "^6.41.0",
84
+ "oxfmt": "^0.72.0",
85
+ "oxlint": "^1.87.0",
86
+ "pkg-pr-new": "^0.0.91",
87
+ "postcss": "^8.5.29",
88
+ "publint": "^0.3.25",
89
+ "tinybench": "^6.2.1",
90
+ "tsdown": "^0.23.0",
93
91
  "typescript": "^7.0.2",
94
- "vite": "^8.0.16",
95
- "vitest": "^4.1.9"
92
+ "vite": "^8.3.4",
93
+ "vitest": "^5.0.3"
96
94
  },
97
95
  "engines": {
98
96
  "pnpm": ">=11.0.0"