Source code for anza.engine.slot.parse

"""Template parsing: ``{{slot}}`` and ``{{{raw}}}`` placeholders."""

from dataclasses import dataclass
from typing import Literal
from ...errors import AnzaError


[docs] @dataclass(frozen=True) class Chunk: """One piece of a parsed template. ``static`` text, a ``slot`` (``{{name}}``, escaped when the engine runs with ``escape=True``) or a ``raw`` slot (``{{{name}}}``, never escaped). Example: >>> from anza import Chunk >>> Chunk(kind="slot", value="title") Chunk(kind='slot', value='title') """ #: ``"static"``, ``"slot"`` or ``"raw"``. kind: Literal["static", "slot", "raw"] #: The static text, or the slot name (whitespace stripped). value: str
[docs] def extract(template: str) -> list[Chunk]: """Split a template into static text and ``{{slot}}`` / ``{{{raw}}}`` chunks. Whitespace around a slot name is ignored (``{{ title }}`` is ``title``). Args: template: The template source. Returns: list[Chunk]: The chunks in order. Raises: AnzaError: ``TEMPLATE`` for an unclosed ``{{`` or ``{{{``, or an empty placeholder. Example: >>> from anza import extract >>> extract("<p>{{ name }} {{{html}}}</p>") # doctest: +NORMALIZE_WHITESPACE [Chunk(kind='static', value='<p>'), Chunk(kind='slot', value='name'), Chunk(kind='static', value=' '), Chunk(kind='raw', value='html'), Chunk(kind='static', value='</p>')] >>> extract("<p>{{name</p>") Traceback (most recent call last): ... anza.errors.AnzaError: [Anza:TEMPLATE] Unclosed slot placeholder '{{' in template """ chunks: list[Chunk] = [] cursor = 0 length = len(template) while cursor < length: open_idx = template.find("{{", cursor) if open_idx == -1: chunks.append(Chunk(kind="static", value=template[cursor:])) break if open_idx > cursor: chunks.append(Chunk(kind="static", value=template[cursor:open_idx])) raw = template.startswith("{", open_idx + 2) start = open_idx + (3 if raw else 2) close = "}}}" if raw else "}}" close_idx = template.find(close, start) if close_idx == -1: if raw: raise AnzaError.template("Unclosed raw slot placeholder '{{{' in template") raise AnzaError.template("Unclosed slot placeholder '{{' in template") slot_name = template[start:close_idx].strip() if not slot_name: raise AnzaError.template("Empty slot placeholder {{}} in template") chunks.append(Chunk(kind="raw" if raw else "slot", value=slot_name)) cursor = close_idx + len(close) return chunks