@@ -580,15 +580,32 @@ console.log(nodes[0].text) // "(min-width: 768px)"
580580
581581---
582582
583- ## ` walk (ast , callback )`
583+ ## ` walk (ast , callback , depth ? )`
584584
585- Walk the AST in depth-first order.
585+ Walk the AST in depth-first order, calling the callback for each node .
586586
587587` ` ` typescript
588- function walk(node : CSSNode , callback : (node : CSSNode , depth : number ) => void ): void
588+ function walk(
589+ node : CSSNode ,
590+ callback : (node : CSSNode , depth : number ) => void | typeof SKIP | typeof BREAK ,
591+ depth ? : number
592+ ): boolean
589593```
590594
591- ** Example:**
595+ ### Parameters
596+
597+ - ** `node`** - The root node to start walking from
598+ - ** `callback`** - Function to call for each node visited. Receives the node and its depth (0 for root ).
599+ - Return `SKIP` to skip children of current node
600+ - Return `BREAK` to stop traversal entirely
601+ - Return nothing to continue normal traversal
602+ - ** `depth`** - Starting depth (default : 0 )
603+
604+ ### Returns
605+
606+ `boolean` - Returns `false` if traversal was stopped with `BREAK`, otherwise `true`
607+
608+ ### Example 1: Basic Walking
592609
593610```typescript
594611import { parse , walk } from ' @projectwallace/css-parser'
@@ -607,6 +624,151 @@ walk(ast, (node, depth) => {
607624// IDENTIFIER
608625` ` `
609626
627+ ### Example 2: Skip Nested Rules
628+
629+ ` ` ` typescript
630+ import { parse , walk , SKIP , STYLE_RULE } from ' @projectwallace/css-parser'
631+
632+ const ast = parse (' .a { .b { .c { color: red; } } }' )
633+
634+ walk (ast , (node ) => {
635+ if (node .type === STYLE_RULE ) {
636+ console .log (node .text )
637+ return SKIP // Don't visit nested rules
638+ }
639+ })
640+ // Output: .a { ... }, but not .b or .c
641+ ` ` `
642+
643+ ### Example 3: Stop on First Declaration
644+
645+ ` ` ` typescript
646+ import { parse , walk , BREAK , DECLARATION } from ' @projectwallace/css-parser'
647+
648+ const ast = parse (' .a { color: red; margin: 10px; }' )
649+
650+ walk (ast , (node ) => {
651+ if (node .type === DECLARATION ) {
652+ console .log (node .name )
653+ return BREAK // Stop traversal
654+ }
655+ })
656+ // Output: "color" (stops before "margin")
657+ ` ` `
658+
659+ ---
660+
661+ ## ` traverse (ast , options ? )`
662+
663+ Walk the AST in depth-first order, calling enter before visiting children and leave after.
664+
665+ ` ` ` typescript
666+ function traverse(
667+ node : CSSNode ,
668+ options ? : {
669+ enter? : (node : CSSNode ) => void | typeof SKIP | typeof BREAK
670+ leave? : (node : CSSNode ) => void | typeof SKIP | typeof BREAK
671+ }
672+ ): boolean
673+ ```
674+
675+ ### Parameters
676+
677+ - ** `node`** - The root node to start walking from
678+ - ** `options`** - Object with optional enter and leave callback functions
679+ - ** `enter`** - Called before visiting children
680+ - Return `SKIP` to skip children (leave still called )
681+ - Return `BREAK` to stop traversal entirely (leave NOT called )
682+ - ** `leave`** - Called after visiting children
683+ - Return `BREAK` to stop traversal
684+
685+ ### Returns
686+
687+ `boolean` - Returns `false` if traversal was stopped with `BREAK`, otherwise `true`
688+
689+ ### Example 1: Track Context with Enter/Leave
690+
691+ ```typescript
692+ import { parse , traverse , AT_RULE } from ' @projectwallace/css-parser'
693+
694+ const ast = parse (' @media screen { .a { color: red; } }' )
695+
696+ let depth = 0
697+ traverse (ast , {
698+ enter(node ) {
699+ depth ++
700+ console .log (` ${' ' .repeat (depth )}Entering ${node .type_name } ` )
701+ },
702+ leave(node ) {
703+ console .log (` ${' ' .repeat (depth )}Leaving ${node .type_name } ` )
704+ depth --
705+ }
706+ })
707+ ` ` `
708+
709+ ### Example 2: Skip Media Query Contents
710+
711+ ` ` ` typescript
712+ import { parse , traverse , SKIP , AT_RULE } from ' @projectwallace/css-parser'
713+
714+ const ast = parse (' @media screen { .a { color: red; } }' )
715+
716+ let depth = 0
717+ traverse (ast , {
718+ enter(node ) {
719+ depth ++
720+ if (node .type === AT_RULE ) {
721+ console .log (' Entering media query at depth' , depth )
722+ return SKIP // Skip contents but still call leave
723+ }
724+ },
725+ leave(node ) {
726+ if (node .type === AT_RULE ) {
727+ console .log (' Leaving media query at depth' , depth )
728+ }
729+ depth --
730+ }
731+ })
732+ // Output:
733+ // Entering media query at depth 2
734+ // Leaving media query at depth 2
735+ ` ` `
736+
737+ ### Example 3: Context-Aware Processing
738+
739+ ` ` ` typescript
740+ import { parse , traverse , STYLE_RULE , AT_RULE } from ' @projectwallace/css-parser'
741+
742+ const ast = parse (`
743+ .top { color: red; }
744+ @media screen {
745+ .nested { color: blue; }
746+ }
747+ ` )
748+
749+ const context = []
750+
751+ traverse (ast , {
752+ enter(node ) {
753+ if (node .type === AT_RULE ) {
754+ context .push (` @${node .name } ` )
755+ } else if (node .type === STYLE_RULE ) {
756+ const selector = node .first_child .text
757+ const ctx = context .length ? ` in ${context .join (' ' )} ` : ' '
758+ console .log (` Rule: ${selector }${ctx } ` )
759+ }
760+ },
761+ leave(node ) {
762+ if (node .type === AT_RULE ) {
763+ context .pop ()
764+ }
765+ }
766+ })
767+ // Output:
768+ // Rule: .top
769+ // Rule: .nested in @media
770+ ` ` `
771+
610772---
611773
612774## ` tokenize (source , skip_comments ? )`
0 commit comments