API / Minn\Html / Tags

Tags final class

Minn\Html\Tags · public/minn/src/Minn/Html/Tags.php · 589 lines

A streaming HTML tokenizer with in-place edits: every token in document order, attributes decoded, edits applied to the source without reserialising the rest, bookmarks to seek back to (probe html-tag-processor).

Constants and properties

constTAG = '#tag'
constTEXT = '#text'
constCOMMENT = '#comment'
constDOCTYPE = '#doctype'
constPI = '#processing-instruction'
constFUNKY = '#funky-comment'
constCDATA = '#cdata-section'
constPRESUMPTUOUS = '#presumptuous-tag'
constCOMMENT_HTML = 'COMMENT_AS_HTML_COMMENT'
constCOMMENT_ABRUPT = 'COMMENT_AS_ABRUPTLY_CLOSED_COMMENT'
constCOMMENT_INVALID = 'COMMENT_AS_INVALID_HTML'
constCOMMENT_CDATA = 'COMMENT_AS_CDATA_LOOKALIKE'
constCOMMENT_PI = 'COMMENT_AS_PI_NODE_LOOKALIKE'
constRAW_TEXT = array ( 0 => 'script', 1 => 'style', 2 => 'textarea', 3 => 'title', 4 => 'xmp', 5 => 'iframe', 6 => 'noembed', 7 => 'noframes', )

Elements whose body is raw text up to the closer.

privateRAW_DECODED = array ( 0 => 'textarea', 1 => 'title', )
privateMAX_BOOKMARKS = 10
privatestring $html
privateint $cursor
privatebool $ended
privatebool $paused
private?string $type
private?string $name
privateint $start
privateint $end
privateint $nameEnd
privatebool $closer
privatebool $selfClosing
privatearray $attributes
privateint $textStart
privateint $textLength
private?string $commentType
private?string $commentTarget
privatestring $namespace
privatestring $tagBodies
privateint $maxBookmarks
privatebool $afterPre

Whether a text token here drops one leading line break (it follows a PRE or LISTING opener).

privatebool $textAfterPre
privateint $fullTextStart
privateint $fullTextLength
privateMinn\Html\Edits $edits
privatearray $bookmarks

Public

new__construct(string $html)#
methodnextToken(): bool#

Advances to the next token; false at the end or at an incomplete one.

methodnextTag(array $query): bool#

Advances to the next tag matching the query; false when none. @param array{tag_name?: ?string, class_name?: ?string, match_offset?: int, tag_closers?: string} $query

$queryarray{tag_name?: ?string, class_name?: ?string, match_offset?: int, tag_closers?: string}
methodpausedAtIncompleteToken(): bool#

Whether the scan stopped inside an unfinished token.

methodtokenType(): ?string#

The current token's kind.

methodtokenName(): ?string#

The current token's name.

methodtag(): ?string#

The current tag name, upper-cased; a processing instruction's target, or a PI lookalike's, as written.

methodisCloser(): bool#

Whether the current tag is a closer.

methodselfClosing(): bool#

Whether the current tag has the self-closing flag.

methodcommentType(): ?string#

The current comment's kind.

methodfullCommentText(): ?string#

The current comment's whole text (a funky comment's is its text).

methodmodifiableText(): string#

The current token's text as a reader sees it.

methoddoctype(): ?array#

Doctype pieces, or null when the token is not a doctype. @return array{name: ?string, public: ?string, system: ?string}|null

@return array{name: ?string, public: ?string, system: ?string}|null
methodattribute(string $name): string|true|null#

The decoded value, true for a bare attribute, null when absent; a pending edit answers first.

methodattributeNames(string $prefix): ?array#

The current tag's attribute names with a prefix, lower-cased, in source order; null off a tag. @return list<string>|null

@return list<string>|null
methodclasses(): array#

The current tag's classes. @return list<string> distinct class names after pending edits

@return list<string> distinct class names after pending edits
methodhasClass(string $class): bool#

Whether the current tag has a class.

methodsetAttribute(string $name, Minn\Html\Escaped|string|int|float|bool|null $value): bool#

Sets an attribute on the current tag.

methodremoveAttribute(string $name): bool#

Removes an attribute from the current tag.

methodaddClass(string $class): bool#

Adds a class to the current tag.

methodremoveClass(string $class): bool#

Removes a class from the current tag.

methodsetModifiableText(string $text): bool#

Replaces the current token's text, when its kind allows it.

methodsetBookmark(string $name): bool#

Names the current token's position.

methodreleaseBookmark(string $name): bool#

Forgets a bookmark.

methodhasBookmark(string $name): bool#

Whether a bookmark exists.

methodseek(string $name): bool#

Moves to a bookmark.

methodparseAs(string $namespace, string $tagBodies = 'html'): void#

What follows as a namespace's content: outside HTML "<![CDATA[" opens a section; tag bodies read as HTML ("html", raw text elements whole) unless foreign ("foreign").

methodallowBookmarks(int $max): void#

Raises how many bookmarks may be held at once.

methodrewind(): void#

Back to the start of the document, with every update written in and the bookmarks kept.

methodsplitText(int $length): void#

The current text token cut to its first bytes; the rest is read next.

methodtokenSpan(): array#

Where the current token sits in the document: [start, end].

methodtextSpan(): array#

Where the current text token's text sits: [start, length].

methodsource(int $start, int $length): string#

The source between two offsets, updates written in.

methodbookmarkSpan(string $name): ?array#

Where a bookmark sits: [start, end], or null when there is none of that name.

methodreplaceAfter(int $start, int $end, string $text): void#

Replaces a span at or after the current token's end, updates written in first: the new text is read next, and bookmarks past the span move with it.

methodhtml(): string#

The document with every update written in.

Internals 10

Private and protected methods: how the class does its work. Not a contract; they change whenever the code is tidied.

privatesetToken(string $type, string $name, int $start, int $end, int $textStart, int $textLength): void#
privateresetToken(): void#
privatetakeTag(int $at, bool $closer): bool#

A tag the scanner read at $at becomes the current token; a raw-text element carries its body to its closer.

privatetake(?array $found): bool#

A comment, doctype, or processing instruction the scanner read becomes the current token; null pauses.

privatebaseClassList(): array#
@return list<string>
privatebaseClassValue(): ?string#
privateflush(): void#

Writes every pending update into the source, keeping bookmarks and the current token aligned.

privateapplyReplacements(array $replacements): void#
$replacementslist<array{int, int, string}>
privaterescanCurrent(): void#

Re-reads the current token so attribute offsets match the new source.

privaterescan(): void#