41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
"""Markdown bible -> raw yaml-block entries. Knows only fences + YAML; nothing
|
|
about the schema's meaning. A block is opened by a line that is exactly ```yaml
|
|
(after strip) and closed by a line that is exactly ```."""
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
from .errors import BuildError
|
|
|
|
|
|
@dataclass
|
|
class RawEntry:
|
|
data: dict
|
|
source: str # "duncarrow.md:53"
|
|
|
|
|
|
def parse_bible(path: Path) -> list[RawEntry]:
|
|
lines = path.read_text().splitlines()
|
|
entries: list[RawEntry] = []
|
|
i, n = 0, len(lines)
|
|
while i < n:
|
|
if lines[i].strip() == "```yaml":
|
|
fence_line = i + 1 # 1-based line of the opening fence
|
|
i += 1
|
|
block: list[str] = []
|
|
while i < n and lines[i].strip() != "```":
|
|
block.append(lines[i])
|
|
i += 1
|
|
if i >= n:
|
|
raise BuildError("unterminated ```yaml block",
|
|
source=f"{path.name}:{fence_line}")
|
|
data = yaml.safe_load("\n".join(block))
|
|
if not isinstance(data, dict):
|
|
raise BuildError("yaml block is not a mapping",
|
|
source=f"{path.name}:{fence_line}")
|
|
entries.append(RawEntry(data=data, source=f"{path.name}:{fence_line}"))
|
|
i += 1
|
|
return entries
|