Collects `` `` blocks and any external refs. The slide kind (e.g. ``data-type="cover"`` for Editorial Monocle) is extracted lazily — ``slide_kinds`` is keyed by the configured ``kind_attr``; an empty string means the slide didn't declare a kind under that attr.
| 89 | |
| 90 | |
| 91 | class _DeckParser(HTMLParser): |
| 92 | """Collects ``<section class="slide">`` blocks and any external refs. |
| 93 | |
| 94 | The slide kind (e.g. ``data-type="cover"`` for Editorial Monocle) is |
| 95 | extracted lazily — ``slide_kinds`` is keyed by the configured |
| 96 | ``kind_attr``; an empty string means the slide didn't declare a kind |
| 97 | under that attr. |
| 98 | """ |
| 99 | |
| 100 | def __init__(self, kind_attr: Optional[str] = None) -> None: |
| 101 | super().__init__() |
| 102 | self.kind_attr = kind_attr |
| 103 | self.slide_kinds: list[str] = [] |
| 104 | self.external_links: list[str] = [] |
| 105 | |
| 106 | def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: |
| 107 | a = dict(attrs) |
| 108 | if tag == "section" and "slide" in (a.get("class") or "").split(): |
| 109 | if self.kind_attr is None: |
| 110 | # Skill-agnostic: just count slides; kind is irrelevant. |
| 111 | self.slide_kinds.append("") |
| 112 | else: |
| 113 | self.slide_kinds.append((a.get(self.kind_attr) or "").strip()) |
| 114 | elif tag == "link": |
| 115 | href = (a.get("href") or "").strip() |
| 116 | if href.startswith(("http://", "https://", "//")): |
| 117 | self.external_links.append(f"<link href={href!r}>") |
| 118 | elif tag == "script": |
| 119 | src = (a.get("src") or "").strip() |
| 120 | if src.startswith(("http://", "https://", "//")): |
| 121 | self.external_links.append(f"<script src={src!r}>") |
| 122 | elif tag == "img": |
| 123 | src = (a.get("src") or "").strip() |
| 124 | if src.startswith(("http://", "https://", "//")): |
| 125 | self.external_links.append(f"<img src={src!r}>") |
| 126 | |
| 127 | |
| 128 | def validate_deck( |