API / Minn\Html\Tree

Minn\Html\Tree

13 classes, 92 public methods and 100 internals. This page is the public surface; each class name opens the whole class.

BodyRules final class

public/minn/src/Minn/Html/Tree/BodyRules.php · 418 lines · Open the class →

The "in body" insertion mode, with select handled in body as the current spec does (no "in select" mode). The adoption agency runs its simple cases (the formatting element is closed with nothing special inside it); the reference stops on the others, and on an end tag for a formatting element that is not active.

constFORMATTING = array ( 0 => 'A', 1 => 'B', 2 => 'BIG', 3 => 'CODE', 4 => 'EM', 5 => 'FONT', 6 => 'I', 7 => 'NOBR', 8 => 'S', 9 => 'SMALL', 10 => 'STRIKE', 11 => 'STRONG', 12 => 'TT', 13 => 'U', )
constSPECIAL = array ( 0 => 'ADDRESS', 1 => 'APPLET', 2 => 'AREA', 3 => 'ARTICLE', 4 => 'ASIDE', 5 => 'BASE', 6 => 'BASEFONT', 7 => 'BGSOUND', 8 => 'BLOCKQUOTE', 9 => 'BODY', 10 => 'BR', 11 => 'BUTTON', 12 => 'CAPTION', 13 => 'CENTER', 14 => 'COL', 15 => 'COLGROUP', 16 => 'DD', 17 => 'DETAILS', 18 => 'DIR', 19 => 'DIV', 20 => 'DL', 21 => 'DT', 22 => 'EMBED', 23 => 'FIELDSET', 24 => 'FIGCAPTION', 25 => 'FIGURE', 26 => 'FOOTER', 27 => 'FORM', 28 => 'FRAME', 29 => 'FRAMESET', 30 => 'H1', 31 => 'H2', 32 => 'H3', 33 => 'H4', 34 => 'H5', 35 => 'H6', 36 => 'HEAD', 37 => 'HEADER', 38 => 'HGROUP', 39 => 'HR', 40 => 'HTML', 41 => 'IFRAME', 42 => 'IMG', 43 => 'INPUT', 44 => 'KEYGEN', 45 => 'LI', 46 => 'LINK', 47 => 'LISTING', 48 => 'MAIN', 49 => 'MARQUEE', 50 => 'MENU', 51 => 'META', 52 => 'NAV', 53 => 'NOEMBED', 54 => 'NOFRAMES', 55 => 'NOSCRIPT', 56 => 'OBJECT', 57 => 'OL', 58 => 'P', 59 => 'PARAM', 60 => 'PLAINTEXT', 61 => 'PRE', 62 => 'SCRIPT', 63 => 'SEARCH', 64 => 'SECTION', 65 => 'SELECT', 66 => 'SOURCE', 67 => 'STYLE', 68 => 'SUMMARY', 69 => 'TABLE', 70 => 'TBODY', 71 => 'TD', 72 => 'TEMPLATE', 73 => 'TEXTAREA', 74 => 'TFOOT', 75 => 'TH', 76 => 'THEAD', 77 => 'TITLE', 78 => 'TR', 79 => 'TRACK', 80 => 'UL', 81 => 'WBR', 82 => 'XMP', )
staticprocess(Minn\Html\Tree\Builder $b, Minn\Html\Tree\Token $t): void

Processes one token in the "in body" insertion mode.

staticisSpecial(Minn\Html\Tree\Node $node): bool

Whether the node is in the spec's "special" category.

insidetext(), startTag(), endTag(), outerStart(), outerEnd(), block(), heading(), pre(), form(), listItem(), button(), anchor(), nobr(), formatting(), withMarker(), table(), voidElement(), hr(), rawText(), select(), option(), ruby(), foreign(), ordinary(), closeBlock(), closeForm(), closeParagraph(), closeListItem(), closeHeading(), closeWithMarker(), adoptionAgency(), anyOtherEnd()

Builder final class

public/minn/src/Minn/Html/Tree/Builder.php · 551 lines · Open the class →

The HTML tree construction algorithm over the engine's tokenizer, as the reference's HTML processor runs it: tokens go through the insertion modes (HeadRules, BodyRules, TableRules) or the foreign content rules, and every node opened or closed becomes an Event with its breadcrumbs. Text is read one kind at a time (NUL bytes, white space, the rest). At the end of the input every open element closes; nothing implied is added. Where the reference does not build a tree (Unsupported), the walk stops with that error.

constFRAGMENT = 'fragment'
constDOCUMENT = 'document'
new__construct(Minn\Html\Tags $tags, string $kind)
methodreset(): void

Back to the state before the first token.

methodnext(): ?Minn\Html\Tree\Event

The next opened or closed node, or null at the end, at an incomplete token, or once unsupported markup stopped the walk.

methodhalt(): void

Stops the walk for good (a failed seek leaves the processor like this).

methoderror(): ?Minn\Html\Tree\Unsupported

Why the walk stopped early, if it did.

methodbreadcrumbs(): array

The breadcrumbs of the open elements now.

@return list<string>
methodtoken(): Minn\Html\Tree\Token

The token being processed.

methodstack(): Minn\Html\Tree\OpenElements

The stack of open elements.

methodformatting(): Minn\Html\Tree\Formatting

The list of active formatting elements.

methodisFragment(): bool

Whether this builder parses a fragment (in a BODY context) rather than a document.

methodmode(): string

The insertion mode.

methodswitchTo(string $mode): void

Switches the insertion mode.

methodreprocessIn(string $mode): void

Switches the insertion mode and processes the current token again under it.

methodprocess(Minn\Html\Tree\Token $token): void

Processes a token under the current insertion mode, or the foreign content rules when they apply.

methodprocessIn(string $mode, Minn\Html\Tree\Token $token): void

Processes a token using the rules of an insertion mode other than the current one.

methodframesetOk(): bool

Whether the frameset-ok flag is still set.

methodframesetNotOk(): void

Clears the frameset-ok flag.

methodcompat(): string

The document's compatibility mode ("no-quirks", "limited-quirks", "quirks").

methodsetCompat(string $compat): void

Sets the compatibility mode the doctype indicated.

methodheadPointer(): ?Minn\Html\Tree\Node

The head element pointer.

methodformPointer(): ?Minn\Html\Tree\Node

The form element pointer.

methodsetFormPointer(?Minn\Html\Tree\Node $node): void

Sets (or clears) the form element pointer.

methodtemplateModes(): array

The stack of template insertion modes.

@return list<string>
methodpushTemplateMode(string $mode): void

Pushes a template insertion mode.

methodpopTemplateMode(): void

Pops the current template insertion mode.

methodadjustedCurrent(): ?Minn\Html\Tree\Node

The adjusted current node: the context element when only the fragment's root is open.

methodinsert(string $namespace = 'html'): Minn\Html\Tree\Node

Inserts an element for the current start tag, real, in the namespace.

methodinsertImplied(string $name): Minn\Html\Tree\Node

Inserts an element the markup implied.

methodinsertLeafElement(string $namespace = 'html'): Minn\Html\Tree\Node

Inserts and at once closes an element for the current start tag: a void element, one read whole, or self-closed foreign content.

methodinsertLeaf(string $namespace = 'html'): void

Inserts a leaf (text, comment, CDATA, processing instruction) for the current token, in the namespace.

methodinsertDocumentLeaf(): void

Inserts a leaf at the top of the document (a doctype or a comment before or around the html element).

methodpop(): ?Minn\Html\Tree\Node

Closes the current node as implied.

methodpopUntil(string ...$names): void

Pops until an HTML element of one of the names closes; when the current end tag names it, that last close is real.

methodpopUntilNode(Minn\Html\Tree\Node $target): void

Pops until this very node closes.

methodgenerateImpliedEndTags(string $except = ''): void

Generates implied end tags, leaving an element of the name open.

methodgenerateAllImpliedEndTags(): void

Generates all implied end tags thoroughly (table parts as well).

methodcloseP(): void

Closes a P element: implied end tags but P's, then pops through the P.

methodclosePInButtonScope(): void

Closes a P element when one is in button scope.

methodreconstructFormatting(): void

Reconstructs the active formatting elements; the reference stops when any would have to be reopened.

methodskipNextNewline(): void

Asks the parser to drop one leading line feed from the next token (after PRE, LISTING).

methodresetInsertionMode(): void

Resets the insertion mode from the stack of open elements.

methodunsupported(string $message): void

Stops: the reference's processor does not build a tree for this markup.

methodattribute(string $name): string|true|null

The current tag's attribute, decoded; null when absent.

methoddoctype(): array

The doctype's name and identifiers, for the compatibility mode. @return array{name: ?string, public: ?string, system: ?string}

@return array{name: ?string, public: ?string, system: ?string}
insidestep(), read(), textRuns(), textValue(), usesHtmlRules(), finish(), pushNode(), event(), keptAttributes()

Compat final class

public/minn/src/Minn/Html/Tree/Compat.php · 79 lines · Open the class →

The compatibility mode a doctype indicates, by the identifier lists in the HTML standard: quirks for legacy and missing doctypes, limited quirks for the XHTML 1.0 transitional and frameset ones (and HTML 4.01's with a system identifier), no quirks otherwise.

staticof(array $doctype): string

The mode ("no-quirks", "limited-quirks", "quirks") for a doctype's pieces.

@param array{name: ?string, public: ?string, system: ?string} $doctype
staticread(string $html): ?array

A whole doctype token read: its name (lower-cased), identifiers and mode; a malformed one is quirks. Null when the text is not one doctype.

@return array{name: ?string, public: ?string, system: ?string, mode: string}|null
insidestartsWithAny()

Event final readonly class

public/minn/src/Minn/Html/Tree/Event.php · 17 lines · Open the class →

One step of the walk the HTML processor reports: a node opened (pushed) or closed (popped), the breadcrumbs at that moment, and the offset of the token behind it when the document wrote it (null when implied).

new__construct(string $op, Minn\Html\Tree\Node $node, array $breadcrumbs, ?int $offset)
@param list<string> $breadcrumbs
propreadonly string $op
propreadonly Minn\Html\Tree\Node $node
propreadonly array $breadcrumbs
propreadonly ?int $offset
methodisCloser(): bool

Whether this event closes its node.

ForeignRules final class

public/minn/src/Minn/Html/Tree/ForeignRules.php · 73 lines · Open the class →

The rules for content in SVG and MathML: text and comments stay in the foreign namespace, an HTML-only start tag (or a font with color, face or size) breaks out back to HTML, other start tags open elements in the current foreign namespace, and an end tag closes the nearest element of its name or falls through to the HTML rules.

staticprocess(Minn\Html\Tree\Builder $b, Minn\Html\Tree\Token $t): void

Processes one token by the rules for foreign content.

insidetext(), breaksOut(), breakOut(), start(), end()

Formatting final class

public/minn/src/Minn/Html/Tree/Formatting.php · 89 lines · Open the class →

The list of active formatting elements, with its markers (null): the formatting elements opened since the last marker that may need reopening, three of a kind at most (the "Noah's Ark" clause).

methodpush(Minn\Html\Tree\Node $node): void

Adds a formatting element, dropping the earliest of three identical ones since the last marker.

methodinsertMarker(): void

Adds a marker (a cell, caption, template, applet, marquee or object opened).

methodclearToLastMarker(): void

Drops entries back to and including the last marker.

methodremove(Minn\Html\Tree\Node $node): void

Drops one element from the list.

methodcontains(Minn\Html\Tree\Node $node): bool

Whether this very element is in the list.

methodlastNamed(string $name): ?Minn\Html\Tree\Node

The last HTML element of the name since the last marker.

methodneedsReconstruction(Minn\Html\Tree\OpenElements $stack): bool

Whether reopening would be needed: the last entry is an element no longer open.

methodnames(): array

The entries' names, markers left out.

@return list<string>
insidesameAttributes()

HeadRules final class

public/minn/src/Minn/Html/Tree/HeadRules.php · 276 lines · Open the class →

The insertion modes around the body: initial (doctype and the compatibility mode it indicates), before html, before head, in head, in head noscript, after head, in template, after body, the frameset modes, and after after body (where a comment would land outside the html element, which the reference does not support).

Node final class

public/minn/src/Minn/Html/Tree/Node.php · 109 lines · Open the class →

A node the tree builder places: an element (named as the HTML API reports it, upper-cased, with its namespace) or a text, comment, doctype or other leaf. Real when a token in the document made it (its offset is where that token starts), virtual when the parser implied it.

constVOID = array ( 0 => 'AREA', 1 => 'BASE', 2 => 'BASEFONT', 3 => 'BGSOUND', 4 => 'BR', 5 => 'COL', 6 => 'EMBED', 7 => 'FRAME', 8 => 'HR', 9 => 'IMG', 10 => 'INPUT', 11 => 'KEYGEN', 12 => 'LINK', 13 => 'META', 14 => 'PARAM', 15 => 'SOURCE', 16 => 'TRACK', 17 => 'WBR', )
constATOMIC = array ( 0 => 'SCRIPT', 1 => 'STYLE', 2 => 'TEXTAREA', 3 => 'TITLE', 4 => 'XMP', 5 => 'IFRAME', 6 => 'NOEMBED', 7 => 'NOFRAMES', )

Elements whose body the tokenizer reads whole, so they never take a closer.

propreadonly string $type
propreadonly string $name
propreadonly string $namespace
propreadonly ?int $offset
staticelement(string $name, string $namespace, ?int $offset, array $attributes = array ( )): self

An element; the attributes kept are the ones the builder compares.

@param array<string, string|true> $attributes
staticleaf(string $type, string $name, string $namespace, ?int $offset, string $text): self

A leaf: text, a comment, a doctype, a CDATA section, a processing instruction.

methodselfClosed(): self

The same element, marked as written with "/>".

methodisSelfClosing(): bool

Whether the element was written with "/>".

methodtext(): string

A leaf's text.

methodattributes(): array

The attributes kept for comparison.

@return array<string, string|true>
methodisHtml(string ...$names): bool

Whether this is an HTML element with one of the names.

methodisIn(string $namespace, string ...$names): bool

Whether this is an element of the namespace with one of the names.

methodexpectsCloser(): bool

Whether the element is closed by a closer of its own: not a leaf, not void, not read whole, not self-closed foreign content.

methodisHtmlIntegrationPoint(): bool

Whether this element is an HTML integration point (SVG foreignObject, desc, title; MathML annotation-xml for HTML).

methodisMathTextIntegrationPoint(): bool

Whether this element is a MathML text integration point.

OpenElements final class

public/minn/src/Minn/Html/Tree/OpenElements.php · 110 lines · Open the class →

The stack of open elements and the spec's scope tests over it: an element is in scope when it is reached walking down from the current node before any of the scope's boundary elements.

methodpush(Minn\Html\Tree\Node $node): void

Puts a node on top.

methodpop(): ?Minn\Html\Tree\Node

Takes the current node off, or null when the stack is empty.

methodcurrent(): ?Minn\Html\Tree\Node

The current (bottom-most open) node.

methodat(int $index): ?Minn\Html\Tree\Node

The node at a position, 0 being the root.

methodcount(): int

How many nodes are open.

methodall(): array

Every open node, root first.

@return list<Node>
methodcontainsNode(Minn\Html\Tree\Node $node): bool

Whether this very node is open.

methodhasHtml(string $name): bool

Whether an HTML element of the name is open anywhere.

methodinScope(string ...$names): bool

Whether one of the HTML elements is in the default scope.

methodinListItemScope(string $name): bool

Whether the HTML element is in list item scope (the default plus OL and UL).

methodinButtonScope(string $name): bool

Whether the HTML element is in button scope (the default plus BUTTON).

methodinTableScope(string ...$names): bool

Whether one of the HTML elements is in table scope (HTML, TABLE and TEMPLATE bound it).

insideinSpecificScope()

Serializer final class

public/minn/src/Minn/Html/Tree/Serializer.php · 72 lines · Open the class →

Normalized HTML for the processor's walk, token by token: tag names lower-cased (SVG's mixed-case names and attributes restored), the first of repeated attributes kept and double-quoted, text and attribute values escaped (& < > " '), RCDATA escaped and raw text left alone, a line break after the PRE, LISTING and TEXTAREA openers, self-closed foreign elements written " />", funky comments and doctypes in a body dropped.

staticqualifiedName(Minn\Html\Tree\Node $node): string

An element's name as written: lower-case, SVG's mixed-case names restored.

staticattributeName(Minn\Html\Tree\Node $node, string $name): string

An attribute's name as written on an element of the node's namespace.

staticopen(Minn\Html\Tree\Node $node, array $attributes, string $text): string

An opening tag; an element read whole (SCRIPT, TEXTAREA, ...) carries its text and closer.

@param list<array{0: string, 1: string|true}> $attributes in document order, repeats already dropped
staticclose(Minn\Html\Tree\Node $node): string

A closing tag.

staticleaf(Minn\Html\Tree\Node $node, string $fullText, string $target): string

A leaf: text escaped, a comment from its whole text, a CDATA section, a processing instruction; nothing for the rest.

insideescape()

TableRules final class

public/minn/src/Minn/Html/Tree/TableRules.php · 292 lines · Open the class →

The table insertion modes: in table (and its text), in caption, in column group, in table body, in row, in cell. Anything that would be foster-parented out of the table (text other than white space, most elements) is where the reference stops.

Token final readonly class

public/minn/src/Minn/Html/Tree/Token.php · 45 lines · Open the class →

A token as the tree builder reads it: a tag (name upper-cased), a run of text (one kind at a time: NUL bytes, white space, or anything else), a comment-like leaf, or the end of the input.

constCLOSER = 1
constSELF_CLOSING = 2
new__construct(string $type, string $name, int $flags, int $offset, string $text = '', string $kind = '')
propreadonly string $type
propreadonly string $name
propreadonly int $flags
propreadonly int $offset
propreadonly string $text
propreadonly string $kind
methodisStart(string ...$names): bool

Whether this is a start tag with one of the names (any name when none are given).

methodisEnd(string ...$names): bool

Whether this is an end tag with one of the names (any name when none are given).

methodselfClosing(): bool

Whether the tag was written with "/>".

methodisText(string $kind): bool

Whether this is a run of text of the kind ("null", "whitespace", "generic").

methodrenamed(string $name, int $flags): self

The same token under another name (an "image" start tag read as "img", "</br>" as "<br>").

Unsupported final class

public/minn/src/Minn/Html/Tree/Unsupported.php · 16 lines · implements Stringable, Throwable · extends RuntimeException · Open the class →

Where the reference's HTML processor stops: markup whose tree it does not build (foster parenting, the adoption agency's hard cases, PLAINTEXT, content after </html>), with the token it stopped at and the state then.

new__construct(string $message, Minn\Html\Tree\Token $token, string $tokenText, array $stack, array $formatting)
@param list<string> $stack the stack of open elements, root first
@param list<string> $formatting the active formatting elements
propreadonly Minn\Html\Tree\Token $token
propreadonly string $tokenText
propreadonly array $stack
propreadonly array $formatting