BlockStream final class
Minn\Blocks\BlockStream · public/minn/src/Minn/Blocks/BlockStream.php · 285 lines
Block markup read one token at a time, as the reference's streaming block processor reads it (probe block-processor). A delimiter is an HTML comment: whitespace after "<!--", an optional "/" (the closing flag), "wp:", a name (lowercase, an optional namespace), whitespace, optional JSON object attributes followed by whitespace, then "-->" or "/-->" (void). Any other comment is HTML. The HTML between delimiters comes out as its own token, reported as void (freeform at the top, inner HTML in a block) before the delimiter that ends it, which is already read, so the closing flag shows that delimiter's. Quirks kept on purpose: - trailing HTML after the last delimiter is dropped when it holds a comment; - an unterminated comment is incomplete input only when it could still become a delimiter, otherwise reading just stops; - attributes are parsed only when asked, and only that sets the JSON error.
Constants and properties
| const | CLOSER = 'closer' | |
| const | OPENER = 'opener' | |
| const | VOID = 'void' | |
| const | READY = 'processor-ready' | |
| const | MATCHED = 'processor-matched' | |
| const | HTML_SPAN = 'processor-html-span' | |
| const | INCOMPLETE_INPUT = 'incomplete-input' | |
| const | COMPLETE = 'processor-complete' | |
| private | WHITESPACE = '
' | |
| private | DELIMITER = '#^[ \\t\\n\\r\\f]+(/)?wp:([a-z][a-z0-9_-]*(?:/[a-z][a-z0-9_-]*)?)[ \\t\\n\\r\\f]+(?:(\\{.*\\})[ \\t\\n\\r\\f]+)?(/)?$#s' | |
| private | string $state | |
| private | ?string $error | |
| private | int $jsonError | |
| private | int $cursor | |
| private | array $delimiter | |
| private | array $html | |
| private | bool $delimiterWaiting | |
| private | bool $popNext | |
| private | array $open | |
| private | readonly string $text | Promoted from the constructor. |
Public
| new | __construct(string $text)# | A stream over block markup, before its first token. |
| static | normalize(string $name): string# | The name with core/ in front when it has no namespace. |
| method | next(): bool# | Moves to the next token, HTML or delimiter; false at the end or on incomplete input. |
| method | state(): string# | The current token's state: one of the class constants. |
| method | error(): ?string# | incomplete-input when the text ran out inside what could be a delimiter, else null. |
| method | jsonError(): int# | The JSON error from the last time attributes were asked for. |
| method | delimiterType(): ?string# | opener, closer or void for a delimiter, void for HTML, null otherwise. |
| method | closing(): bool# | The last delimiter read had the closing flag. |
| method | blockType(): ?string# | The delimiter's block type, null for anything else. |
| method | printableType(): ?string# | The block type, or core/freeform for top-level HTML and #innerHTML for HTML inside a block. |
| method | isHtml(): bool# | Whether the token is HTML between delimiters. |
| method | htmlContent(): ?string# | The HTML span's text, null for anything else. |
| method | nonWhitespaceHtml(): bool# | Whether the token is HTML with something other than whitespace in it. |
| method | breadcrumbs(): array# | The open block types, outermost first, with #html for an HTML span. @return list<string> @return list<string> |
| method | opens(?string $type): bool# | Whether this token opens a block (of the type, when given): never after a closer, and HTML only at the top. |
| method | isType(string $type): bool# | Whether the token is of the type; * matches anything. |
| method | span(): ?array# | The token's start and length in the text, null when there is no token. @return array{0: int, 1: int}|null @return array{0: int, 1: int}|null |
| method | attributes(): ?array# | The delimiter's attributes, parsed now (setting the JSON error), or null. @return array<mixed>|null @return array<mixed>|null |
Internals 7
Private and protected methods: how the class does its work. Not a contract; they change whenever the code is tidied.
| private | scan(): bool# | From where the last token ended: the HTML before the next delimiter, the delimiter, or the end. |
| private | emitHtml(int $at, int $length): bool# | |
| private | matchDelimiter(): bool# | |
| private | finish(?string $error): bool# | |
| private | nextDelimiter(int $from): array|false|null# | The next delimiter from a position; null when there is none and no comment came first (the rest is HTML), false when reading stops there (a comment came first, or one is cut off; cut off where a delimiter could still begin is incomplete input). @return array{at: int, length: int, type: string, closing: bool, name: string, json: ?string}|false|null |
| private | commentEnd(int $at): ?int# | Where a comment starting here ends (just past it), or null when it never does. |
| private | couldBeDelimiter(int $at): bool# | Whether a comment cut off by the end of the text could still have become a delimiter. |
Nothing matches.