Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/turbohtml/treebuild.py: 100%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2turbohtml.treebuild: retarget the parser at your own tree.
4Where :func:`turbohtml.parse` builds a navigable document and :func:`turbohtml.saxparse.sax_parse` streams
5events, :func:`parse_into` runs the same WHATWG tree builder and hands the constructed tree straight to a builder
6object you supply -- one method per node kind, plus an ``append`` that links a child under its parent. The parser
7never materializes a turbohtml :class:`~turbohtml.Node` and you never walk the result a second time: a single pass
8over the spec-correct tree (implied ``<html>``/``<head>``/``<body>``, foster parenting, the adoption agency) drives
9your builder, so an index, a diff tree, or an extraction struct is populated directly from the parse.
11This is the model Rust's html5ever exposes as its ``TreeSink`` trait and Node's parse5 as its ``TreeAdapter``: the
12conformant parser is retargetable, the tree representation is yours. A builder returns an opaque *handle* for each
13node it creates -- any object at all, since turbohtml only threads it back into a later ``append`` -- and the handle
14your :meth:`TreeBuilder.create_document` returns is what :func:`parse_into` gives back.
16The methods mirror parse5's adapter: every element carries its namespace URI (``http://www.w3.org/1999/xhtml`` for
17HTML, and the SVG and MathML URIs for foreign content) and its attributes as ``(name, value)`` pairs, a valueless
18attribute pairing with None. A ``<template>``'s content is appended straight under the template handle. Processing
19instructions arrive through :meth:`TreeBuilder.create_pi` with separate target and data strings.
20"""
22from __future__ import annotations
24from typing import Protocol, TypeVar, cast
26from ._html import _parse_into
28__all__ = [
29 "TreeBuilder",
30 "parse_into",
31]
33H = TypeVar("H")
34"""The builder's node handle: whatever :class:`TreeBuilder` returns for a node and takes back in ``append``."""
37class TreeBuilder(Protocol[H]):
38 """
39 The tree-construction sink :func:`parse_into` drives, parse5's ``TreeAdapter`` in turbohtml shape.
41 Implement each method to create the matching node in your own representation and return a handle for it; the
42 handle is opaque to turbohtml, threaded back only into :meth:`append`. The protocol is structural, so any object
43 with these methods works -- no base class to inherit.
44 """
46 def create_document(self) -> H:
47 """Create the document root and return its handle; :func:`parse_into` returns this handle."""
49 def create_doctype(self, name: str, public_id: str | None, system_id: str | None) -> H:
50 """Create a doctype node; ``public_id``/``system_id`` are None when the source omits them."""
52 def create_element(self, name: str, namespace: str, attrs: tuple[tuple[str, str | None], ...]) -> H:
53 """Create an element ``name`` in ``namespace`` (a URI) with ``attrs`` (each a ``(name, value)`` pair)."""
55 def create_text(self, data: str) -> H:
56 """Create a text node holding ``data``."""
58 def create_comment(self, data: str) -> H:
59 """Create a comment node holding ``data``."""
61 def create_pi(self, target: str, data: str) -> H:
62 """Create a node for an HTML instruction whose target is not reserved for XML."""
64 def append(self, parent: H, child: H) -> None:
65 """Append the ``child`` handle under the ``parent`` handle, in document order."""
68def parse_into(html: str, builder: TreeBuilder[H]) -> H:
69 """
70 Parse ``html`` and drive ``builder`` to construct the tree, returning its document handle.
72 The document is parsed with the full WHATWG tree-construction algorithm, then its nodes are handed to
73 ``builder`` in document order: one ``create_*`` call per node followed by an :meth:`~TreeBuilder.append` linking
74 it under its parent. No navigable :class:`~turbohtml.Node` is built and the tree is walked only once.
76 :param html: the markup to parse.
77 :param builder: the :class:`TreeBuilder` (any object with its methods) that constructs your representation.
78 :returns: the handle :meth:`~TreeBuilder.create_document` returned, now populated with the parsed tree.
79 :raises TypeError: if ``html`` is not a str.
80 :raises AttributeError: if ``builder`` is missing one of the :class:`TreeBuilder` methods.
81 """
82 return cast("H", _parse_into(html, builder))