The template tree parser and serializer.
parser/tokenizer.js answers "where does this tag begin and end in the
source". This module answers the next question: what tree do those tags
describe. It was previously private to ComponentParser, which was fine
while the compiler had exactly one consumer for it. The render compiler
(lib/compiler/render/) is a second, and a second copy of an HTML parser is
how two halves of one compiler come to disagree about what a template says.
It is deliberately not a spec-compliant HTML parser. Avenx templates are
authored rather than scraped, and by the time a template reaches here the
declaration tags are gone and the directives have been rewritten into
ordinary elements. What it guarantees is that serializeHTML(parseHTML(x))
round-trips a template the compiler itself produced.
- Source:
Classes
Members
(static, constant) DEFAULT_VOID_TAGS :Array:.<string:>
The set of HTML tags that are void (self-closing / no children) by default.
Type:
- Source:
(inner, constant) IF_CHAIN_TAGS :Set:.<string:>
The arms of a conditional chain.
They are parsed as siblings rather than as a nest, which is what lets
</@if> terminate the chain and what lets a consumer read the arms as an
ordered list instead of unwinding a ladder.
Type:
- Source:
(inner, constant) IF_CONTINUATION_TAGS :Set:.<string:>
The arms that continue a chain, and therefore end the arm before them.
Type:
- Source:
Methods
(static) buildVoidTagsSet(customVoidTagsopt) → {Set:.<string:>}
Builds the effective set of void tags for a parse or serialize pass.
Parameters:
| Name | Type | Attributes | Description |
|---|---|---|---|
customVoidTags |
Array:.<string:> |
<optional> |
Additional void tag names (lowercase). |
- Source:
Returns:
The effective set.
(static) getLineAndColumn(source, offset) → {Object}
Calculates 1-based line and column numbers for a character offset in a source string.
Parameters:
| Name | Type | Description |
|---|---|---|
source |
string | The original source code string. |
offset |
number | The zero-based character index. |
- Source:
Returns:
- Type
- Object
(static) parseAttributes(attrStr) → {Object:.<string:, string:>}
Parses an attribute string into a key-value object.
Handles three attribute forms:
- Quoted values:
name="value"orname='value'. A backslash-escaped quote (\"or\') inside the value is preserved verbatim rather than ending the value early, so expressions containing an apostrophe or a quote character (e.g.@click='say(\'hi\')') parse correctly instead of being split into several bogus attributes. - Unquoted values:
name=value, read up to the next whitespace or>. - Valueless boolean attributes:
disabled, mapped to the string'true'(matching theattr="true"/attr="false"convention the runtime's boolean-attribute handling already expects, rather thannull).
Parameters:
| Name | Type | Description |
|---|---|---|
attrStr |
string |
- Source:
Returns:
(static) parseHTML(html, customVoidTagsopt) → {Array:.<HTMLNode:>}
Parses an HTML string into a tree of HTMLNode elements with positional metadata.
Parameters:
| Name | Type | Attributes | Description |
|---|---|---|---|
html |
string | ||
customVoidTags |
Array:.<string:> |
<optional> |
- Source:
Returns:
(static) scanTagEnd(html, start) → {number}
Finds the offset of the > that ends the tag opening at start.
Quoting is honoured for every tag, because a > inside title="a > b" has
never been the end of a tag. Bracket depth is honoured only for @-prefixed
directive tags, and that exception is the point of this function.
A directive header carries an expression rather than attributes:
<@for row in rows.filter(r => r.score > 90)>
Scanning for the first unquoted > ends that tag at r.score , which is why
the previous implementation truncated the list expression to
rows.filter(r = and reported it as a malformed template expression. The
expression is not malformed; the scan was. Inside (, [ or { a > is a
comparison or an arrow, never a tag end, so the scan tracks depth and only
accepts a > at depth zero.
The exception is deliberately not extended to ordinary elements. <div data-x=a(b>c)> is not markup anyone writes, and widening the rule would
change how existing templates parse for no gain.
Parameters:
| Name | Type | Description |
|---|---|---|
html |
string | The full template source. |
start |
number | Offset of the |
- Source:
Returns:
Offset of the closing >, or -1 when the tag is unterminated.
- Type
- number
(static) serializeHTML(nodes, customVoidTagsopt) → {string}
Serializes an HTMLNode tree back to an HTML string.
Parameters:
- Source:
Returns:
- Type
- string