@projectwallace/css-parser 0.16.0 → 0.16.1

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/README.md CHANGED
@@ -3,19 +3,18 @@
3
3
  > [!WARNING]
4
4
  > This is a very experimental CSS parser. Expect several bugs and inconveniences!
5
5
 
6
- **High-performance CSS parser optimized for static analysis and formatting**
6
+ **High-performance CSS parser built for static analysis and tooling**
7
7
 
8
- Built for speed and efficiency, this parser handles large CSS files with minimal memory overhead and blazing-fast parse times. Designed with a data-oriented architecture using a single contiguous memory arena for zero allocations during parsing.
8
+ Parses large CSS files in microseconds with a fixed-size memory arena — no garbage collection pressure, no per-node allocations, no surprises. If you're building a formatter, linter, or analysis tool and need raw speed with precise source locations, this is built for that.
9
9
 
10
- This parser was heavily influenced by [CSSTree](https://github.com/csstree/csstree), one of the most robust CSS parsers available. Some of the parsing mechanics are taken from CSSTree, as well as some of the performance mechanics, but a lot of things are very different which is why this isn't a direct fork and there is very little overlap in API's.
10
+ Heavily influenced by [CSSTree](https://github.com/csstree/csstree). Some parsing mechanics are shared, but the memory model, architecture, and API are fundamentally different — not a fork.
11
11
 
12
12
  ## Features
13
13
 
14
- - **Modern CSS support** - CSS Nesting, `:is()`, `:where()`, `:has()`, `@layer`, `@container`
15
- - **Error recovery** - Continues parsing on malformed CSS
16
- - **Location tracking** - Line, column, offset, and length for all nodes
17
- - **Performance** - Low memory usage and excellent parsing speed
18
- - **Small bundle size** - Fast download and installation in any environment
14
+ - **Full modern CSS** — CSS Nesting, `:is()`, `:where()`, `:has()`, `@layer`, `@container`
15
+ - **Error-tolerant** — keeps parsing through malformed input; one bad rule won't kill the file
16
+ - **Precise source locations** — line, column, offset, and length on every node
17
+ - **Tiny footprint** — tree-shakeable subparsers; as small as 278 bytes gzipped, < 16 kB kB worst case
19
18
 
20
19
  ## Installation
21
20
 
@@ -59,20 +58,36 @@ for (const rule of ast) {
59
58
 
60
59
  ## Performance
61
60
 
62
- - **Small install size** (~200kB)
63
- - **Zero allocations during parsing** - all memory allocated upfront based on real world heuristics, which also helps prevent garbage collection running often
64
- - **Cache-friendly data layout** - contiguous memory for sequential access powered by concepts of Data Oriented Design
65
- - **First-class comment and location support** - while still being performant because analysis requires constant access to lines and columns
66
- - **No syntax validation** - focusing only on the raw data we can skip expensive syntax files and MDN data syncs
61
+ - **Zero allocations during parsing** — memory is reserved upfront using real-world heuristics; the GC never runs mid-parse
62
+ - **Cache-friendly layout** — all nodes live in a single contiguous arena, making sequential access fast
63
+ - **Location tracking with no penalty** — full line, column, and offset data without slowing the parser down
64
+ - **No syntax validation** — skipping spec checks and MDN data means nothing gets in the way of speed
65
+
66
+ ### Bundle sizes
67
+
68
+ All sizes are minified and bundled with dependencies. Import only what you need — bundlers will tree-shake the rest.
69
+
70
+ | Import | Description | Minified | Gzip |
71
+ | ------------------------------------------------- | ---------------------------- | -------- | ------- |
72
+ | `@projectwallace/css-parser` | Full parser (all subparsers) | 68.9 kB | 15.5 kB |
73
+ | `@projectwallace/css-parser/parse` | CSS stylesheet parser | 62.2 kB | 13.3 kB |
74
+ | `@projectwallace/css-parser/parse-atrule-prelude` | At-rule prelude parser | 35.4 kB | 8.4 kB |
75
+ | `@projectwallace/css-parser/parse-selector` | Selector parser | 37.7 kB | 8.9 kB |
76
+ | `@projectwallace/css-parser/parse-anplusb` | An+B syntax parser | 26.1 kB | 6.6 kB |
77
+ | `@projectwallace/css-parser/parse-declaration` | Declaration parser | 28.3 kB | 7.3 kB |
78
+ | `@projectwallace/css-parser/parse-value` | Value parser | 25.2 kB | 6.6 kB |
79
+ | `@projectwallace/css-parser/parse-dimension` | Dimension parser | 0.4 kB | 0.3 kB |
80
+ | `@projectwallace/css-parser/tokenizer` | Tokenizer | 9.8 kB | 2.4 kB |
67
81
 
68
82
  ## Documentation
69
83
 
70
- See [API.md](./API.md) for complete documentation of all parser functions and options.
84
+ See [API.md](./API.md) for complete documentation of all parser functions and nodes.
71
85
 
72
86
  ## Non-goals
73
87
 
74
- - **No syntax validation** - this parser does not try to validate your CSS structure. Everything can be anything
75
- - **No custom syntax support** - we're leaving the era of CSS preprocessors so we only focus on CSS
88
+ - **No syntax validation** — CSS structure is your responsibility; the parser accepts anything valid or not
89
+ - **No preprocessor syntax** — Sass, Less, and Stylus are out of scope; this parser targets plain CSS only
90
+ - **Tree operations** - Manipulating the AST is not within scope of this library
76
91
 
77
92
  ## License
78
93
 
@@ -52,13 +52,13 @@ var CSSDataArena = class CSSDataArena {
52
52
  growth_count;
53
53
  overflow_lengths;
54
54
  static GROWTH_FACTOR = 1.3;
55
- static NODES_PER_KB = 325;
56
- static CAPACITY_BUFFER = 1.2;
55
+ static NODES_PER_KB = 210;
56
+ static CAPACITY_BUFFER = 1.1;
57
57
  constructor(initial_capacity = 1024) {
58
58
  this.capacity = initial_capacity;
59
59
  this.count = 1;
60
60
  this.growth_count = 0;
61
- this.buffer = new ArrayBuffer(initial_capacity * BYTES_PER_NODE);
61
+ this.buffer = /* @__PURE__ */ new ArrayBuffer(initial_capacity * BYTES_PER_NODE);
62
62
  this.view = new DataView(this.buffer);
63
63
  this.overflow_lengths = /* @__PURE__ */ new Map();
64
64
  }
@@ -154,7 +154,7 @@ var CSSDataArena = class CSSDataArena {
154
154
  grow() {
155
155
  this.growth_count++;
156
156
  let new_capacity = Math.ceil(this.capacity * CSSDataArena.GROWTH_FACTOR);
157
- let new_buffer = new ArrayBuffer(new_capacity * BYTES_PER_NODE);
157
+ let new_buffer = /* @__PURE__ */ new ArrayBuffer(new_capacity * BYTES_PER_NODE);
158
158
  new Uint8Array(new_buffer).set(new Uint8Array(this.buffer));
159
159
  this.buffer = new_buffer;
160
160
  this.view = new DataView(new_buffer);
@@ -178,6 +178,22 @@ var CSSDataArena = class CSSDataArena {
178
178
  this.view.setUint32(offset + 4, children[0], true);
179
179
  for (let i = 0; i < children.length - 1; i++) this.set_next_sibling(children[i], children[i + 1]);
180
180
  }
181
+ /**
182
+ * Shrink the buffer to exactly the number of live nodes, releasing wasted capacity.
183
+ * Call once after parsing is complete. Safe to call multiple times (no-op if already tight).
184
+ *
185
+ * @see https://doc.rust-lang.org/std/vec/struct.Vec.html#method.shrink_to_fit
186
+ * @see https://en.cppreference.com/w/cpp/container/vector/shrink_to_fit
187
+ */
188
+ trim() {
189
+ if (this.count === this.capacity) return;
190
+ let byte_count = this.count * BYTES_PER_NODE;
191
+ let new_buffer = new ArrayBuffer(byte_count);
192
+ new Uint8Array(new_buffer).set(new Uint8Array(this.buffer, 0, byte_count));
193
+ this.buffer = new_buffer;
194
+ this.view = new DataView(new_buffer);
195
+ this.capacity = this.count;
196
+ }
181
197
  has_children(node_index) {
182
198
  return this.get_first_child(node_index) !== 0;
183
199
  }
@@ -84,6 +84,14 @@ declare class CSSDataArena {
84
84
  private grow;
85
85
  create_node(type: number, start_offset: number, length: number, start_line: number, start_column: number): number;
86
86
  append_children(parent_index: number, children: number[]): void;
87
+ /**
88
+ * Shrink the buffer to exactly the number of live nodes, releasing wasted capacity.
89
+ * Call once after parsing is complete. Safe to call multiple times (no-op if already tight).
90
+ *
91
+ * @see https://doc.rust-lang.org/std/vec/struct.Vec.html#method.shrink_to_fit
92
+ * @see https://en.cppreference.com/w/cpp/container/vector/shrink_to_fit
93
+ */
94
+ trim(): void;
87
95
  has_children(node_index: number): boolean;
88
96
  has_next_sibling(node_index: number): boolean;
89
97
  set_flag(node_index: number, flag: number): void;
@@ -1,4 +1,4 @@
1
- import { B as SUPPORTS_QUERY, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as SELECTOR_LIST, G as VALUE, H as UNICODE_RANGE, I as STRING, L as STYLESHEET, M as PSEUDO_ELEMENT_SELECTOR, N as RAW, O as PARENTHESIS, P as SELECTOR, R as STYLE_RULE, S as MEDIA_TYPE, T as NTH_SELECTOR, U as UNIVERSAL_SELECTOR, V as TYPE_SELECTOR, W as URL, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_CLASS_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_DECLARATION } from "./arena-CSK5NfHq.js";
1
+ import { B as SUPPORTS_QUERY, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as SELECTOR_LIST, G as VALUE, H as UNICODE_RANGE, I as STRING, L as STYLESHEET, M as PSEUDO_ELEMENT_SELECTOR, N as RAW, O as PARENTHESIS, P as SELECTOR, R as STYLE_RULE, S as MEDIA_TYPE, T as NTH_SELECTOR, U as UNIVERSAL_SELECTOR, V as TYPE_SELECTOR, W as URL, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_CLASS_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_DECLARATION } from "./arena-DfpuGV9Y.js";
2
2
 
3
3
  //#region src/constants.d.ts
4
4
  declare const NODE_TYPES: {
package/dist/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as PSEUDO_CLASS_SELECTOR, B as TYPE_SELECTOR, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as STRING, H as UNIVERSAL_SELECTOR, I as STYLESHEET, L as STYLE_RULE, M as RAW, N as SELECTOR, O as PARENTHESIS, P as SELECTOR_LIST, R as SUPPORTS_DECLARATION, S as MEDIA_TYPE, T as NTH_SELECTOR, U as URL, V as UNICODE_RANGE, W as VALUE, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_ELEMENT_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_QUERY } from "./arena-DnV0a_Ne.js";
1
+ import { A as PSEUDO_CLASS_SELECTOR, B as TYPE_SELECTOR, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as STRING, H as UNIVERSAL_SELECTOR, I as STYLESHEET, L as STYLE_RULE, M as RAW, N as SELECTOR, O as PARENTHESIS, P as SELECTOR_LIST, R as SUPPORTS_DECLARATION, S as MEDIA_TYPE, T as NTH_SELECTOR, U as URL, V as UNICODE_RANGE, W as VALUE, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_ELEMENT_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_QUERY } from "./arena-CCye9VYE.js";
2
2
  //#region src/constants.ts
3
3
  const NODE_TYPES = {
4
4
  STYLESHEET: 1,
@@ -1,5 +1,5 @@
1
- import "./arena-DnV0a_Ne.js";
2
- import { a as is_whitespace, c as str_starts_with, i as is_vendor_prefixed, t as parse_dimension } from "./parse-dimension-CCn_XRDe.js";
1
+ import "./arena-CCye9VYE.js";
2
+ import { a as is_whitespace, c as str_starts_with, i as is_vendor_prefixed, t as parse_dimension } from "./parse-dimension-B0AZRxxt.js";
3
3
  //#region src/css-node.ts
4
4
  const TYPE_NAMES = {
5
5
  [1]: "StyleSheet",
@@ -46,7 +46,7 @@ const TYPE_NAMES = {
46
46
  [40]: "AtrulePrelude",
47
47
  [41]: "PreludeSelectorList"
48
48
  };
49
- const nodes_with_name = new Set([
49
+ const nodes_with_name = /* @__PURE__ */ new Set([
50
50
  3,
51
51
  10,
52
52
  15,
@@ -62,7 +62,7 @@ const nodes_with_name = new Set([
62
62
  37,
63
63
  39
64
64
  ]);
65
- const nodes_with_children = new Set([
65
+ const nodes_with_children = /* @__PURE__ */ new Set([
66
66
  1,
67
67
  5,
68
68
  20,
@@ -187,7 +187,7 @@ var CSSNode = class CSSNode {
187
187
  if (type === 4 && first_child) return first_child;
188
188
  if (type === 33) return first_child ?? null;
189
189
  if (type === 12) return parse_dimension(text).value;
190
- if (type === 11) return Number.parseFloat(text);
190
+ if (type === 11) return Number(text);
191
191
  if (type === 18) {
192
192
  if (first_child?.type === 13) return first_child.text;
193
193
  if (str_starts_with(text, "url(")) {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { B as SUPPORTS_QUERY, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as SELECTOR_LIST, G as VALUE, H as UNICODE_RANGE, I as STRING, L as STYLESHEET, M as PSEUDO_ELEMENT_SELECTOR, N as RAW, O as PARENTHESIS, P as SELECTOR, R as STYLE_RULE, S as MEDIA_TYPE, T as NTH_SELECTOR, U as UNIVERSAL_SELECTOR, V as TYPE_SELECTOR, W as URL, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_CLASS_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_DECLARATION } from "./arena-CSK5NfHq.js";
1
+ import { B as SUPPORTS_QUERY, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as SELECTOR_LIST, G as VALUE, H as UNICODE_RANGE, I as STRING, L as STYLESHEET, M as PSEUDO_ELEMENT_SELECTOR, N as RAW, O as PARENTHESIS, P as SELECTOR, R as STYLE_RULE, S as MEDIA_TYPE, T as NTH_SELECTOR, U as UNIVERSAL_SELECTOR, V as TYPE_SELECTOR, W as URL, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_CLASS_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_DECLARATION } from "./arena-DfpuGV9Y.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-mV23Aiyb.js";
4
- import { $ as is_class_selector, A as PreludeSelectorList, At as is_stylesheet, B as SupportsDeclaration, Bt as TYPE_NAMES, C as NestingSelector, Ct as is_pseudo_class_selector, D as Operator, Dt as is_selector, E as Number, Et as is_rule, F as Selector, Ft as is_universal_selector, G as UniversalSelector, H as ToPlain, I as SelectorList, It as is_url, J as WithChildren, K as Url, L as SelectorNode, Lt as is_value, M as PseudoElementSelector, Mt as is_supports_query, N as Raw, Nt as is_type_selector, O as Parenthesis, Ot as is_selector_list, P as Rule, Pt as is_unicode_range, Q as is_block, R as String, Rt as CloneOptions, S as MediaType, St as is_prelude_selectorlist, T as NthSelector, Tt as is_raw, U as TypeSelector, V as SupportsQuery, W as UnicodeRange, X as is_atrule_prelude, Y as is_atrule, Z as is_attribute_selector, _ as Identifier, _t as is_nth_selector, a as Block, at as is_feature_range, b as MediaFeature, bt as is_parenthesis, c as Combinator, ct as is_id_selector, d as Declaration, dt as is_layer_name, et as is_combinator, f as Dimension, ft as is_media_feature, g as IdSelector, gt as is_nth_of_selector, h as Hash, ht as is_nesting_selector, i as AttributeSelector, it as is_dimension, j as PseudoClassSelector, jt as is_supports_declaration, k as PreludeOperator, kt as is_string, l as Comment, lt as is_identifier, m as Function, mt as is_media_type, n as Atrule, nt as is_container_query, o as CSSNode, ot as is_function, p as FeatureRange, pt as is_media_query, q as Value, r as AtrulePrelude, rt as is_declaration, s as ClassSelector, st as is_hash, t as AnyNode, tt as is_comment, u as ContainerQuery, ut as is_lang_selector, v as LangSelector, vt as is_number, w as NthOfSelector, wt as is_pseudo_element_selector, x as MediaQuery, xt as is_prelude_operator, y as LayerName, yt as is_operator, z as StyleSheet, zt as PlainCSSNode } from "./node-types-mntWKkN-.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-DeZYFa9R.js";
4
+ import { $ as is_class_selector, A as PreludeSelectorList, At as is_stylesheet, B as SupportsDeclaration, Bt as TYPE_NAMES, C as NestingSelector, Ct as is_pseudo_class_selector, D as Operator, Dt as is_selector, E as Number, Et as is_rule, F as Selector, Ft as is_universal_selector, G as UniversalSelector, H as ToPlain, I as SelectorList, It as is_url, J as WithChildren, K as Url, L as SelectorNode, Lt as is_value, M as PseudoElementSelector, Mt as is_supports_query, N as Raw, Nt as is_type_selector, O as Parenthesis, Ot as is_selector_list, P as Rule, Pt as is_unicode_range, Q as is_block, R as String, Rt as CloneOptions, S as MediaType, St as is_prelude_selectorlist, T as NthSelector, Tt as is_raw, U as TypeSelector, V as SupportsQuery, W as UnicodeRange, X as is_atrule_prelude, Y as is_atrule, Z as is_attribute_selector, _ as Identifier, _t as is_nth_selector, a as Block, at as is_feature_range, b as MediaFeature, bt as is_parenthesis, c as Combinator, ct as is_id_selector, d as Declaration, dt as is_layer_name, et as is_combinator, f as Dimension, ft as is_media_feature, g as IdSelector, gt as is_nth_of_selector, h as Hash, ht as is_nesting_selector, i as AttributeSelector, it as is_dimension, j as PseudoClassSelector, jt as is_supports_declaration, k as PreludeOperator, kt as is_string, l as Comment, lt as is_identifier, m as Function, mt as is_media_type, n as Atrule, nt as is_container_query, o as CSSNode, ot as is_function, p as FeatureRange, pt as is_media_query, q as Value, r as AtrulePrelude, rt as is_declaration, s as ClassSelector, st as is_hash, t as AnyNode, tt as is_comment, u as ContainerQuery, ut as is_lang_selector, v as LangSelector, vt as is_number, w as NthOfSelector, wt as is_pseudo_element_selector, x as MediaQuery, xt as is_prelude_operator, y as LayerName, yt as is_operator, z as StyleSheet, zt as PlainCSSNode } from "./node-types-BrZu8T2C.js";
5
5
  import { ParserOptions, parse } from "./parse.js";
6
6
  import { parse_selector, parse_selector_list } from "./parse-selector.js";
7
7
  import { parse_atrule_prelude } from "./parse-atrule-prelude.js";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
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-BxUina14.js";
2
- import { A as PSEUDO_CLASS_SELECTOR, B as TYPE_SELECTOR, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as STRING, H as UNIVERSAL_SELECTOR, I as STYLESHEET, L as STYLE_RULE, M as RAW, N as SELECTOR, O as PARENTHESIS, P as SELECTOR_LIST, R as SUPPORTS_DECLARATION, S as MEDIA_TYPE, T as NTH_SELECTOR, U as URL, V as UNICODE_RANGE, W as VALUE, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_ELEMENT_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_QUERY } from "./arena-DnV0a_Ne.js";
3
- import { c as str_starts_with, i as is_vendor_prefixed, o as str_equals, r as is_custom, s as str_index_of, t as parse_dimension } from "./parse-dimension-CCn_XRDe.js";
4
- import { n as TYPE_NAMES } from "./css-node-BTgoFWDU.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-BiRLfVbm.js";
2
+ import { A as PSEUDO_CLASS_SELECTOR, B as TYPE_SELECTOR, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as STRING, H as UNIVERSAL_SELECTOR, I as STYLESHEET, L as STYLE_RULE, M as RAW, N as SELECTOR, O as PARENTHESIS, P as SELECTOR_LIST, R as SUPPORTS_DECLARATION, S as MEDIA_TYPE, T as NTH_SELECTOR, U as URL, V as UNICODE_RANGE, W as VALUE, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_ELEMENT_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, p as FLAG_IMPORTANT, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_QUERY } from "./arena-CCye9VYE.js";
3
+ import { c as str_starts_with, i as is_vendor_prefixed, o as str_equals, r as is_custom, s as str_index_of, t as parse_dimension } from "./parse-dimension-B0AZRxxt.js";
4
+ import { n as TYPE_NAMES } from "./css-node-CuLhABl8.js";
5
5
  import { parse_selector, parse_selector_list } from "./parse-selector.js";
6
6
  import { parse_atrule_prelude } from "./parse-atrule-prelude.js";
7
7
  import { parse_value } from "./parse-value.js";
@@ -1,4 +1,4 @@
1
- import { A as PRELUDE_SELECTORLIST, B as SUPPORTS_QUERY, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as SELECTOR_LIST, G as VALUE, H as UNICODE_RANGE, I as STRING, L as STYLESHEET, M as PSEUDO_ELEMENT_SELECTOR, N as RAW, O as PARENTHESIS, P as SELECTOR, R as STYLE_RULE, S as MEDIA_TYPE, T as NTH_SELECTOR, U as UNIVERSAL_SELECTOR, V as TYPE_SELECTOR, W as URL, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_CLASS_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_DECLARATION } from "./arena-CSK5NfHq.js";
1
+ import { A as PRELUDE_SELECTORLIST, B as SUPPORTS_QUERY, C as NESTING_SELECTOR, D as OPERATOR, E as NUMBER, F as SELECTOR_LIST, G as VALUE, H as UNICODE_RANGE, I as STRING, L as STYLESHEET, M as PSEUDO_ELEMENT_SELECTOR, N as RAW, O as PARENTHESIS, P as SELECTOR, R as STYLE_RULE, S as MEDIA_TYPE, T as NTH_SELECTOR, U as UNIVERSAL_SELECTOR, V as TYPE_SELECTOR, W as URL, _ as ID_SELECTOR, a as CLASS_SELECTOR, b as MEDIA_FEATURE, c as CONTAINER_QUERY, d as DIMENSION, f as FEATURE_RANGE, g as IDENTIFIER, h as HASH, i as BLOCK, j as PSEUDO_CLASS_SELECTOR, k as PRELUDE_OPERATOR, m as FUNCTION, n as AT_RULE, o as COMBINATOR, r as AT_RULE_PRELUDE, s as COMMENT, t as ATTRIBUTE_SELECTOR, u as DECLARATION, v as LANG_SELECTOR, w as NTH_OF_SELECTOR, x as MEDIA_QUERY, y as LAYER_NAME, z as SUPPORTS_DECLARATION } from "./arena-DfpuGV9Y.js";
2
2
 
3
3
  //#region src/css-node.d.ts
4
4
  declare const TYPE_NAMES: {
@@ -1,5 +1,5 @@
1
- import { l as CSSDataArena } from "./arena-CSK5NfHq.js";
2
- import { T as NthSelector } from "./node-types-mntWKkN-.js";
1
+ import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
2
+ import { T as NthSelector } from "./node-types-BrZu8T2C.js";
3
3
 
4
4
  //#region src/parse-anplusb.d.ts
5
5
  /** @internal */
@@ -1,7 +1,7 @@
1
- import { t as Lexer } from "./tokenize-BxUina14.js";
2
- import { l as CSSDataArena } from "./arena-DnV0a_Ne.js";
3
- import { o as str_equals, s as str_index_of } from "./parse-dimension-CCn_XRDe.js";
4
- import { t as CSSNode } from "./css-node-BTgoFWDU.js";
1
+ import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
+ import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
+ import { o as str_equals, s as str_index_of } from "./parse-dimension-B0AZRxxt.js";
4
+ import { t as CSSNode } from "./css-node-CuLhABl8.js";
5
5
  //#region src/parse-anplusb.ts
6
6
  /** @internal */
7
7
  var ANplusBParser = class {
@@ -1,5 +1,5 @@
1
- import { l as CSSDataArena } from "./arena-CSK5NfHq.js";
2
- import { t as AnyNode } from "./node-types-mntWKkN-.js";
1
+ import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
2
+ import { t as AnyNode } from "./node-types-BrZu8T2C.js";
3
3
 
4
4
  //#region src/parse-atrule-prelude.d.ts
5
5
  /** @internal */
@@ -1,8 +1,8 @@
1
- import { t as Lexer } from "./tokenize-BxUina14.js";
2
- import { l as CSSDataArena } from "./arena-DnV0a_Ne.js";
3
- import { a as is_whitespace, l as strip_vendor_prefix, o as str_equals } from "./parse-dimension-CCn_XRDe.js";
4
- import { t as CSSNode } from "./css-node-BTgoFWDU.js";
5
- import { i as trim_boundaries, n as skip_whitespace_and_comments_forward } from "./parse-utils-BxrmqJxI.js";
1
+ import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
+ import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
+ import { a as is_whitespace, l as strip_vendor_prefix, o as str_equals } from "./parse-dimension-B0AZRxxt.js";
4
+ import { t as CSSNode } from "./css-node-CuLhABl8.js";
5
+ import { i as trim_boundaries, n as skip_whitespace_and_comments_forward } from "./parse-utils-BmXnziOy.js";
6
6
  //#region src/parse-atrule-prelude.ts
7
7
  /** @internal */
8
8
  var AtRulePreludeParser = class {
@@ -538,8 +538,7 @@ var AtRulePreludeParser = class {
538
538
  if (this.lexer.pos >= this.prelude_end) return [];
539
539
  this.next_token();
540
540
  if (this.lexer.token_type !== 1) return [];
541
- nodes.push(this.create_node(10, this.lexer.token_start, this.lexer.token_end));
542
- nodes.push(...this.parse_media_query_list());
541
+ nodes.push(this.create_node(10, this.lexer.token_start, this.lexer.token_end), ...this.parse_media_query_list());
543
542
  return nodes;
544
543
  }
545
544
  parse_feature_range(feature_start, feature_end, content_start, content_end) {
@@ -1,6 +1,6 @@
1
- import { l as CSSDataArena } from "./arena-CSK5NfHq.js";
2
- import { n as Lexer } from "./tokenize-mV23Aiyb.js";
3
- import { d as Declaration } from "./node-types-mntWKkN-.js";
1
+ import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
2
+ import { n as Lexer } from "./tokenize-DeZYFa9R.js";
3
+ import { d as Declaration } from "./node-types-BrZu8T2C.js";
4
4
 
5
5
  //#region src/parse-declaration.d.ts
6
6
  /** @internal */
@@ -1,8 +1,8 @@
1
- import { t as Lexer } from "./tokenize-BxUina14.js";
2
- import { l as CSSDataArena } from "./arena-DnV0a_Ne.js";
3
- import { i as is_vendor_prefixed } from "./parse-dimension-CCn_XRDe.js";
4
- import { t as CSSNode } from "./css-node-BTgoFWDU.js";
5
- import { i as trim_boundaries } from "./parse-utils-BxrmqJxI.js";
1
+ import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
+ import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
+ import { i as is_vendor_prefixed } from "./parse-dimension-B0AZRxxt.js";
4
+ import { t as CSSNode } from "./css-node-CuLhABl8.js";
5
+ import { i as trim_boundaries } from "./parse-utils-BmXnziOy.js";
6
6
  import { ValueParser } from "./parse-value.js";
7
7
  //#region src/parse-declaration.ts
8
8
  /** @internal */
@@ -169,7 +169,7 @@ function parse_dimension(text) {
169
169
  let num_str = text.substring(0, num_end);
170
170
  let unit = text.substring(num_end);
171
171
  return {
172
- value: num_str ? parseFloat(num_str) : 0,
172
+ value: num_str ? Number.parseFloat(num_str) : 0,
173
173
  unit
174
174
  };
175
175
  }
@@ -1,2 +1,2 @@
1
- import { t as parse_dimension } from "./parse-dimension-CCn_XRDe.js";
1
+ import { t as parse_dimension } from "./parse-dimension-B0AZRxxt.js";
2
2
  export { parse_dimension };
@@ -1,5 +1,5 @@
1
- import { l as CSSDataArena } from "./arena-CSK5NfHq.js";
2
- import { F as Selector, I as SelectorList } from "./node-types-mntWKkN-.js";
1
+ import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
2
+ import { F as Selector, I as SelectorList } from "./node-types-BrZu8T2C.js";
3
3
 
4
4
  //#region src/parse-selector.d.ts
5
5
  /** @internal */
@@ -1,8 +1,8 @@
1
- import { t as Lexer } from "./tokenize-BxUina14.js";
2
- import { l as CSSDataArena } from "./arena-DnV0a_Ne.js";
3
- import { a as is_whitespace, n as is_combinator, o as str_equals } from "./parse-dimension-CCn_XRDe.js";
4
- import { t as CSSNode } from "./css-node-BTgoFWDU.js";
5
- import { n as skip_whitespace_and_comments_forward, r as skip_whitespace_forward, t as skip_whitespace_and_comments_backward } from "./parse-utils-BxrmqJxI.js";
1
+ import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
+ import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
+ import { a as is_whitespace, n as is_combinator, o as str_equals } from "./parse-dimension-B0AZRxxt.js";
4
+ import { t as CSSNode } from "./css-node-CuLhABl8.js";
5
+ import { n as skip_whitespace_and_comments_forward, r as skip_whitespace_forward, t as skip_whitespace_and_comments_backward } from "./parse-utils-BmXnziOy.js";
6
6
  import { ANplusBParser } from "./parse-anplusb.js";
7
7
  //#region src/parse-selector.ts
8
8
  /** @internal */
@@ -1,4 +1,4 @@
1
- import { a as is_whitespace } from "./parse-dimension-CCn_XRDe.js";
1
+ import { a as is_whitespace } from "./parse-dimension-B0AZRxxt.js";
2
2
  //#region src/parse-utils.ts
3
3
  /**
4
4
  * Skip whitespace forward from a position
@@ -1,5 +1,5 @@
1
- import { l as CSSDataArena } from "./arena-CSK5NfHq.js";
2
- import { q as Value } from "./node-types-mntWKkN-.js";
1
+ import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
2
+ import { q as Value } from "./node-types-BrZu8T2C.js";
3
3
 
4
4
  //#region src/parse-value.d.ts
5
5
  /** @internal */
@@ -1,7 +1,7 @@
1
- import { t as Lexer } from "./tokenize-BxUina14.js";
2
- import { l as CSSDataArena } from "./arena-DnV0a_Ne.js";
3
- import { a as is_whitespace, o as str_equals } from "./parse-dimension-CCn_XRDe.js";
4
- import { t as CSSNode } from "./css-node-BTgoFWDU.js";
1
+ import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
+ import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
+ import { a as is_whitespace, o as str_equals } from "./parse-dimension-B0AZRxxt.js";
4
+ import { t as CSSNode } from "./css-node-CuLhABl8.js";
5
5
  //#region src/parse-value.ts
6
6
  /** @internal */
7
7
  var ValueParser = class {
package/dist/parse.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { l as CSSDataArena } from "./arena-CSK5NfHq.js";
2
- import { t as CommentInfo } from "./tokenize-mV23Aiyb.js";
3
- import { z as StyleSheet } from "./node-types-mntWKkN-.js";
1
+ import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
2
+ import { t as CommentInfo } from "./tokenize-DeZYFa9R.js";
3
+ import { z as StyleSheet } from "./node-types-BrZu8T2C.js";
4
4
 
5
5
  //#region src/parse.d.ts
6
6
  interface ParserOptions {
package/dist/parse.js CHANGED
@@ -1,12 +1,12 @@
1
- import { t as Lexer } from "./tokenize-BxUina14.js";
2
- import { l as CSSDataArena } from "./arena-DnV0a_Ne.js";
3
- import { t as CSSNode } from "./css-node-BTgoFWDU.js";
4
- import { i as trim_boundaries } from "./parse-utils-BxrmqJxI.js";
1
+ import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
+ import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
+ import { t as CSSNode } from "./css-node-CuLhABl8.js";
4
+ import { i as trim_boundaries } from "./parse-utils-BmXnziOy.js";
5
5
  import { SelectorParser } from "./parse-selector.js";
6
6
  import { AtRulePreludeParser } from "./parse-atrule-prelude.js";
7
7
  import { DeclarationParser } from "./parse-declaration.js";
8
8
  //#region src/parse.ts
9
- let DECLARATION_AT_RULES = new Set([
9
+ let DECLARATION_AT_RULES = /* @__PURE__ */ new Set([
10
10
  "font-face",
11
11
  "font-feature-values",
12
12
  "page",
@@ -66,6 +66,7 @@ var Parser = class {
66
66
  else rules.push(rule);
67
67
  }
68
68
  this.arena.append_children(stylesheet, rules);
69
+ this.arena.trim();
69
70
  return new CSSNode(this.arena, this.source, stylesheet);
70
71
  }
71
72
  parse_rule() {
@@ -1,7 +1,7 @@
1
1
  //#region src/char-types.ts
2
2
  let CHAR_ALPHA = 1;
3
3
  let CHAR_HEX = 4;
4
- let char_types = new Uint8Array(128);
4
+ let char_types = /* @__PURE__ */ new Uint8Array(128);
5
5
  for (let i = 48; i <= 57; i++) char_types[i] = 2;
6
6
  for (let i = 48; i <= 57; i++) char_types[i] |= CHAR_HEX;
7
7
  for (let i = 65; i <= 70; i++) char_types[i] = CHAR_HEX;
@@ -13,7 +13,7 @@ char_types[9] = 8;
13
13
  char_types[10] = 16;
14
14
  char_types[13] = 16;
15
15
  char_types[12] = 16;
16
- for (let i = 0; i < 128; i++) if (char_types[i] & (CHAR_ALPHA | 2)) char_types[i] |= 32;
16
+ for (let i = 0; i < 128; i++) if (char_types[i] & 3) char_types[i] |= 32;
17
17
  char_types[45] |= 32;
18
18
  char_types[95] |= 32;
19
19
  function is_hex_digit(ch) {
@@ -1,2 +1,2 @@
1
- import { i as tokenize, n as Lexer, r as LexerPosition, t as CommentInfo } from "./tokenize-mV23Aiyb.js";
1
+ import { i as tokenize, n as Lexer, r as LexerPosition, t as CommentInfo } from "./tokenize-DeZYFa9R.js";
2
2
  export { CommentInfo, Lexer, LexerPosition, tokenize };
package/dist/tokenize.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as tokenize, t as Lexer } from "./tokenize-BxUina14.js";
1
+ import { n as tokenize, t as Lexer } from "./tokenize-BiRLfVbm.js";
2
2
  export { Lexer, tokenize };
package/dist/walk.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { o as CSSNode, t as AnyNode } from "./node-types-mntWKkN-.js";
1
+ import { o as CSSNode, t as AnyNode } from "./node-types-BrZu8T2C.js";
2
2
 
3
3
  //#region src/walk.d.ts
4
4
  declare const SKIP: unique symbol;
package/dist/walk.js CHANGED
@@ -1,5 +1,5 @@
1
- import "./arena-DnV0a_Ne.js";
2
- import { t as CSSNode } from "./css-node-BTgoFWDU.js";
1
+ import "./arena-CCye9VYE.js";
2
+ import { t as CSSNode } from "./css-node-CuLhABl8.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.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "High-performance CSS lexer and parser, optimized for CSS inspection and analysis",
5
5
  "keywords": [
6
6
  "ast",
@@ -75,22 +75,22 @@
75
75
  "provenance": true
76
76
  },
77
77
  "devDependencies": {
78
- "@codecov/rollup-plugin": "^2.0.1",
79
78
  "@projectwallace/preset-oxlint": "^0.0.10",
80
79
  "@types/node": "^24.10.1",
81
- "@vitest/coverage-v8": "^4.1.5",
80
+ "@vitest/coverage-v8": "^4.1.9",
82
81
  "bootstrap": "^5.3.8",
83
82
  "css-tree": "^3.1.0",
84
- "knip": "^6.11.0",
85
- "oxfmt": "^0.49.0",
86
- "oxlint": "^1.62.0",
87
- "postcss": "^8.5.6",
88
- "publint": "^0.3.18",
83
+ "knip": "^6.18.0",
84
+ "oxfmt": "^0.56.0",
85
+ "oxlint": "^1.71.0",
86
+ "postcss": "^8.5.15",
87
+ "publint": "^0.3.21",
89
88
  "tailwindcss": "^2.2.8",
90
- "tinybench": "^6.0.1",
91
- "tsdown": "^0.22.0",
89
+ "tinybench": "^6.0.2",
90
+ "tsdown": "^0.22.3",
92
91
  "typescript": "^6.0.3",
93
- "vitest": "^4.1.5"
92
+ "vite": "^8.0.16",
93
+ "vitest": "^4.1.9"
94
94
  },
95
95
  "engines": {
96
96
  "pnpm": ">=11.0.0"