Class: Lilac::CLI::TemplateAST
- Inherits:
-
Object
- Object
- Lilac::CLI::TemplateAST
- Defined in:
- lib/lilac/cli/build/template_ast.rb
Overview
Parses a template body HTML fragment with Nokogiri, walks the element tree, and:
1. Collects every `data-*` directive into a flat list of
`Directive` records (in document order) for the lint layer.
2. Assigns a synthetic `data-ref="lilN"` to any element bearing
a binding directive but no explicit `data-ref`, so the
runtime scanner can resolve it positionally at mount.
3. Builds `refs_map` keyed by ref name, recording each ref's
source line for duplicate / reserved-name lint checks.
SFC's regex-based template extraction (SFC.parse) preserves the
template body byte-for-byte. TemplateAST does NOT preserve byte
equality on the way out — Nokogiri normalizes quoting and
boolean attribute serialization. The HTML returned by parse is
round-tripped through Nokogiri::HTML5.
Directive values are NOT validated against the value grammar here
— directive attributes are left in the output HTML so the runtime
scanner sees data-component / data-ref and the directives it
binds at mount time.
Defined Under Namespace
Classes: Error, Result, WalkScopes
Constant Summary collapse
- DIRECTIVE_PATTERNS =
Maps an attribute-name regex to its directive kind. Order matters: the more specific X-family patterns (
data-on-Xetc.) must be checked before the simpler ones so thatdata-on-clickis classified as:onnot as an unknown attribute.class_trailing underscore avoids shadowing Ruby's reservedclasskeyword in pattern-match contexts; symbol-side only. [ [/\Adata-text\z/, :text, false], [/\Adata-unsafe-html\z/, :unsafe_html, false], # data-bind is the form-independent two-way binding directive # (Phase E revival/unification of data-value / data-checked). # Property auto-selected from element type: # <input type=checkbox> → :checked, others → :value. # See directive-spec §6.2 for the full grammar; runtime parity # lives in runtime/mruby-lilac-directives/. [/\Adata-bind\z/, :bind, false], [/\Adata-show\z/, :show, false], [/\Adata-hide\z/, :hide, false], [/\Adata-each\z/, :each, false], [/\Adata-key\z/, :key, false], [/\Adata-class\z/, :class_, false], # data-component is detected only so collision checks can see # it; it has no emit_* of its own (the runtime autoregister # reads the HTML attribute directly) and `walk` skips Directive # records when it appears alone, to keep the dist HTML and the # linter input unchanged for the common case. [/\Adata-component\z/, :component, false], # Form directives (mruby-lilac-form gem). Collected so scope # validation / lint can see them; the runtime form scanner wires # the actual behavior at mount (resolves scope via ancestor walk). [/\Adata-form\z/, :form, false], [/\Adata-field\z/, :field, false], [/\Adata-button\z/, :button, false], [/\Adata-on-(.+)\z/, :on, true], [/\Adata-attr-(.+)\z/, :attr, true], [/\Adata-arg-(.+)\z/, :arg, true], [/\Adata-css-(.+)\z/, :css, true], ].freeze
Instance Method Summary collapse
-
#initialize(body_html, source_path: nil) ⇒ TemplateAST
constructor
A new instance of TemplateAST.
- #parse ⇒ Object
Constructor Details
#initialize(body_html, source_path: nil) ⇒ TemplateAST
Returns a new instance of TemplateAST.
78 79 80 81 |
# File 'lib/lilac/cli/build/template_ast.rb', line 78 def initialize(body_html, source_path: nil) @body_html = body_html @source_path = source_path end |
Instance Method Details
#parse ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/lilac/cli/build/template_ast.rb', line 118 def parse fragment = Nokogiri::HTML5.fragment(@body_html) directives = [] refs_map = {} # `at_root: true` for the outermost walk — when the first # element child of the fragment carries `data-component`, it's # the component's own root (this AST run IS that component), # so its directives + body belong to this component. Any deeper # `data-component` element is a different component; we treat # those subtrees opaquely so their directives don't leak into # the current component's scope. walk(fragment, directives, refs_map, WalkScopes.new, at_root: true) Result.new( html: fragment.to_html, directives: directives, refs_map: refs_map, ) end |