Shared tree-walker for HEEx token transformers.
The LV 1.2 parser produces a tree of:
{:block, type, name, attrs, children, open_meta, close_meta}wheretypeis:tag|:local_component|:remote_component|:slot{:self_close, type, name, attrs, meta}— void/self-closing tags{:body_expr, code, meta}—{...}inline expression{:eex, code, meta}—<%= ... %>expression{:eex_block, code, clauses, meta}—<%= if x do %>...<% end %>where each clause is{children, end_code, meta}{:text, content, meta}{:eex_comment, content, meta}
Every sub-transformer that wants to walk this tree needs the same
boilerplate: dispatch on the kind of node, recurse into children
for blocks, recurse into each clause for eex_block, leave
leaves alone. This module factors that out behind two callbacks.
Callbacks
walk(nodes, opts)where opts is a keyword list:
:node_callback—(node, parent, metadata) -> [node]. Receives the whole node, the parent context, and the threaded metadata. Returns a list (usually one element, sometimes more when a node expands). If omitted, defaults to[node].:attrs_callback—(name, attrs, meta, metadata) -> attrs. Receives the tag name + attrs list + opening-tag meta + threaded metadata. Returns the new attrs. The walker stitches the result back into the node. Use this when you want to inject attributes but don't need to rewrite node structure.:metadata— opaque user data threaded through every callback. Sub-transformers stash their config here.
What the walker does for you
- Recurse into children of
:blocknodes. - Recurse into each clause's children for
:eex_blocknodes. - Track the parent node ({:tag, name, attrs} for the nearest
enclosing block) so
node_callbackcan make context-dependent decisions. - Leave leaves (
:text,:eex,:eex_comment, unknown) alone unlessnode_callbackrewrites them.
Parent shape
The parent passed to node_callback is nil at the top
level, or {:tag, name, attrs} describing the immediately
enclosing block node. This is sparse on purpose — most callers
only care about the parent's tag name + attrs (e.g. "am I inside
a <textarea>?", "is my parent already a display-wrapper?").
Summary
Functions
Walks nodes applying the configured callbacks.