@@ -32,11 +32,13 @@ function parse(source: string, options?: ParserOptions): CSSNode
3232` CSSNode ` - Root stylesheet node with the following properties :
3333
3434** Core Properties :**
35+
3536- ` type ` - Node type constant (e.g., `STYLESHEET`, `STYLE_RULE`)
3637- `type_name` - CSSTree-compatible type name (e.g., `'StyleSheet'`, `'Rule'`)
3738- `text` - Full text of the node from source
3839
3940** Content Properties :**
41+
4042- ` name ` - Property name for declarations , at - rule name for at - rules , layer name for import layers
4143- ` property ` - Alias for ` name ` (for declarations , more semantic )
4244- ` value ` - Value text (for declarations ), numeric value (for NUMBER /DIMENSION ), string content without quotes (for STRING ), URL content (for URL ), or ` null `
@@ -45,13 +47,15 @@ function parse(source: string, options?: ParserOptions): CSSNode
4547- ` prelude ` - At -rule prelude text or ` null `
4648
4749** Location Properties :**
50+
4851- ` line ` - Starting line number (1-based )
4952- ` column ` - Starting column number (1-based )
5053- ` start ` - Starting offset in source (0-based )
5154- ` length ` - Length in source
5255- ` end ` - End offset in source (calculated as `start + length` )
5356
5457** Flags :**
58+
5559- ` is_important ` - Whether declaration has ` !important ` (DECLARATION only )
5660- ` is_vendor_prefixed ` - Whether node has vendor prefix (checks name /text based on type )
5761- ` has_error ` - Whether node has syntax error
@@ -62,34 +66,40 @@ function parse(source: string, options?: ParserOptions): CSSNode
6266- ` has_next ` - Whether node has a next sibling
6367
6468** Tree Structure :**
69+
6570- ` first_child ` - First child node or ` null `
6671- ` next_sibling ` - Next sibling node or ` null `
6772- ` children ` - Array of all child nodes
6873- ` block ` - Block node containing declarations /nested rules (for style rules and at -rules with blocks )
6974- ` is_empty ` - Whether block has no declarations or rules (only comments allowed )
7075
7176** Value Access (Declarations ):**
77+
7278- ` values ` - Array of value nodes (for declarations )
7379
7480** Selector Properties :**
81+
7582- ` selector_list ` - Selector list from pseudo -classes like ` :is() ` , ` :not() ` , ` :has() ` , ` :where() ` , or ` :nth-child(of) `
7683- ` nth ` - An + B formula node from ` :nth-child(of) ` wrapper (for NTH_OF_SELECTOR nodes )
7784- ` selector ` - Selector list from ` :nth-child(of) ` wrapper (for NTH_OF_SELECTOR nodes )
7885- ` nth_a ` - The ' a' coefficient from An + B expressions like ` "2n" ` from ` :nth-child(2n+1) ` (for NTH_SELECTOR )
7986- ` nth_b ` - The ' b' coefficient from An + B expressions like ` "+1" ` from ` :nth-child(2n+1) ` (for NTH_SELECTOR )
8087
8188** Attribute Selector Properties :**
89+
8290- ` attr_operator ` - Attribute operator constant (for ATTRIBUTE_SELECTOR ): ` ATTR_OPERATOR_NONE ` , ` ATTR_OPERATOR_EQUAL ` , etc .
8391- ` attr_flags ` - Attribute flags constant (for ATTRIBUTE_SELECTOR ): ` ATTR_FLAG_NONE ` , ` ATTR_FLAG_CASE_INSENSITIVE ` , ` ATTR_FLAG_CASE_SENSITIVE `
8492
8593** Compound Selector Helpers (SELECTOR nodes ):**
94+
8695- ` compound_parts() ` - Iterator over first compound selector parts (zero allocation )
8796- ` first_compound ` - Array of parts before first combinator
8897- ` all_compounds ` - Array of compound arrays split by combinators
8998- ` is_compound ` - Whether selector has no combinators
9099- ` first_compound_text ` - Text of first compound selector (no node allocation )
91100
92101** Methods :**
102+
93103- ` clone(options?) ` - Clone node as a mutable plain object with children as arrays
94104
95105### Example 1 : Basic Parsing
@@ -613,11 +623,7 @@ console.log(nodes[0].text) // "(min-width: 768px)"
613623Walk the AST in depth - first order , calling the callback for each node .
614624
615625` ` ` typescript
616- function walk(
617- node: CSSNode,
618- callback: (node: CSSNode, depth: number) => void | typeof SKIP | typeof BREAK,
619- depth?: number
620- ): boolean
626+ function walk(node: CSSNode, callback: (node: CSSNode, depth: number) => void | typeof SKIP | typeof BREAK, depth?: number): boolean
621627` ` `
622628
623629### Parameters
@@ -696,7 +702,7 @@ function traverse(
696702 options?: {
697703 enter?: (node: CSSNode) => void | typeof SKIP | typeof BREAK
698704 leave?: (node: CSSNode) => void | typeof SKIP | typeof BREAK
699- }
705+ },
700706): boolean
701707` ` `
702708
@@ -730,7 +736,7 @@ traverse(ast, {
730736 leave(node) {
731737 console.log( ` $ {' ' .repeat (depth )}Leaving $ {node .type_name }` )
732738 depth--
733- }
739+ },
734740})
735741` ` `
736742
@@ -755,7 +761,7 @@ traverse(ast, {
755761 console.log('Leaving media query at depth', depth)
756762 }
757763 depth--
758- }
764+ },
759765})
760766// Output:
761767// Entering media query at depth 2
@@ -790,7 +796,7 @@ traverse(ast, {
790796 if (node.type === AT_RULE) {
791797 context.pop()
792798 }
793- }
799+ },
794800})
795801// Output:
796802// Rule: .top
@@ -962,3 +968,91 @@ for (let node of ast) {
962968 }
963969}
964970```
971+
972+ ---
973+
974+ ## ` @projectwallace/css-parser/string-utils `
975+
976+ ### ` is_custom(str) `
977+
978+ Check if a string is a CSS custom property (starts with ` -- ` ).
979+
980+ ``` typescript
981+ import { parse } from ' @projectwallace/css-parser'
982+ import { is_custom } from ' @projectwallace/css-parser/string-utils'
983+
984+ const ast = parse (' :root { --primary: blue; color: red; }' )
985+ const block = ast .first_child .block
986+
987+ for (const decl of block .children ) {
988+ if (is_custom (decl .name )) {
989+ console .log (' Custom property:' , decl .name ) // Logs: "--primary"
990+ }
991+ }
992+
993+ // Direct usage
994+ is_custom (' --primary-color' ) // true
995+ is_custom (' --my-var' ) // true
996+ is_custom (' color' ) // false
997+ is_custom (' -webkit-transform' ) // false (vendor prefix, not custom)
998+ ```
999+
1000+ ### ` is_vendor_prefixed(str) `
1001+
1002+ Check if a string has a vendor prefix (` -webkit- ` , ` -moz- ` , ` -ms- ` , ` -o- ` ).
1003+
1004+ ``` typescript
1005+ import { is_vendor_prefixed } from ' @projectwallace/css-parser/string-utils'
1006+
1007+ // Detect vendor prefixes
1008+ is_vendor_prefixed (' -webkit-transform' ) // true
1009+ is_vendor_prefixed (' -moz-appearance' ) // true
1010+ is_vendor_prefixed (' -ms-filter' ) // true
1011+ is_vendor_prefixed (' -o-border-image' ) // true
1012+
1013+ // Not vendor prefixes
1014+ is_vendor_prefixed (' --custom-property' ) // false (custom property)
1015+ is_vendor_prefixed (' border-radius' ) // false (standard property)
1016+ is_vendor_prefixed (' transform' ) // false (no prefix)
1017+ ```
1018+
1019+ ### ` str_equals(a, b) `
1020+
1021+ Case-insensitive string equality check without allocations. The first parameter must be lowercase.
1022+
1023+ ``` typescript
1024+ import { str_equals } from ' @projectwallace/css-parser/string-utils'
1025+
1026+ // First parameter MUST be lowercase
1027+ str_equals (' media' , ' MEDIA' ) // true
1028+ str_equals (' media' , ' Media' ) // true
1029+ str_equals (' media' , ' media' ) // true
1030+ str_equals (' media' , ' print' ) // false
1031+ ```
1032+
1033+ ### ` str_starts_with(str, prefix) `
1034+
1035+ Case-insensitive prefix check without allocations. The prefix parameter must be lowercase.
1036+
1037+ ``` typescript
1038+ import { str_starts_with } from ' @projectwallace/css-parser/string-utils'
1039+
1040+ // prefix MUST be lowercase
1041+ str_starts_with (' WEBKIT-transform' , ' webkit' ) // true
1042+ str_starts_with (' Mozilla' , ' moz' ) // true
1043+ str_starts_with (' transform' , ' trans' ) // true
1044+ str_starts_with (' color' , ' border' ) // false
1045+ ```
1046+
1047+ ### ` str_index_of(str, search) `
1048+
1049+ Case-insensitive substring search without allocations. Returns the index of the first occurrence. The search parameter must be lowercase.
1050+
1051+ ``` typescript
1052+ import { str_index_of } from ' @projectwallace/css-parser/string-utils'
1053+
1054+ // search MUST be lowercase
1055+ str_index_of (' background-COLOR' , ' color' ) // 11
1056+ str_index_of (' HELLO' , ' e' ) // 1
1057+ str_index_of (' transform' , ' x' ) // -1 (not found)
1058+ ```
0 commit comments