Parsing HTML

Say you have 200 pages of hand-written HTML and want to move them to chimera. Parser reads HTML back into chimera objects, turning a <p> into a Paragraph and a rendered Menu back into a Menu. You change the objects, then render them again.

Parsing

parse returns the top-level nodes it found:

const nodes = Parser():parse([==[
<nav data-element="Menu" class="chimera-menu"><a href="/">Home</a><a href="/blog">Blog</a></nav>
<p>Hi <strong>there</strong></p>
<dialog open>Sure?</dialog>
]==])

for _, node in nodes do
    print(node)
end

Each node prints as a tree. This output comes from running the code above as the page built:

Menu<nav>.chimera-menu
├─ Link<a> href
│  └─ "Home"
└─ Link<a> href
   └─ "Blog"
Paragraph<p>
├─ "Hi "
└─ Strong
   └─ "there"
Tag<dialog> open
└─ "Sure?"

Tags that have a class become that class, and the rest become a Tag that keeps its name. Components come back from their data-element attribute.

Whole pages

To edit a whole page, Document.from_html reads it into a Document:

const page = Document.from_html(fs.readfile("out/index.html"))
page:style_every(Card, { padding = "2rem" })
fs.writefile("out/index.html", page:to_html(true))

The parser drops the stylesheet and script chimera generated because the document writes them again when it renders. Your own style_every rules come back as rules. Any page chimera rendered parses back into the objects it came from.

Problems

Bad HTML never stops the parser. It drops whatever doesn't fit and notes each drop in warnings:

const parser = Parser()
parser:parse("<ul><p>Not a list item</p></ul>")
print(parser.warnings[1])
UnorderedList can't hold Paragraph<p>; dropped it (at byte 27)

Your own components

Components you write parse back as themselves because implementing Component registers them by name. Their adopt method decides which parsed children they keep (see Custom components).

HTML that chimera didn't write, like another site's <div class="alert">, can come back as your components too when they're Shapes (see Markdown and JSON).