#!/usr/bin/env python3 """Structured opening-focus fence for the full-data report. The engine writes one ``jyotish-focus`` JSON fence. The report page renders that fence; it does not recompute dasha lords or house lords. """ from __future__ import annotations import json import re from typing import Any FOCUS_FENCE_RE = re.compile(r"```jyotish-focus\n(.*?)\n```", re.DOTALL) _FOCUS_BLOCK_RE = re.compile(r"```jyotish-focus\n.*?\n```", re.DOTALL) _HOLD_TOKEN = "JYOTISHFOCUSHOLD{index}END" def build_focus_fence(payload: dict[str, Any]) -> str: """Return a one-line JSON fence. Values are already public words.""" body = json.dumps(payload, ensure_ascii=False, separators=(",", ":")) return f"```jyotish-focus\n{body}\n```" def parse_focus_fence(markdown: str) -> dict[str, Any] | None: match = FOCUS_FENCE_RE.search(markdown or "") if not match: return None try: value = json.loads(match.group(1)) except json.JSONDecodeError: return None return value if isinstance(value, dict) else None def hold_focus_fences(markdown: str) -> tuple[str, list[str]]: """Lift fences out of the glossary pass so planet words stay valid JSON.""" slots: list[str] = [] def repl(match: re.Match[str]) -> str: slots.append(match.group(0)) return _HOLD_TOKEN.format(index=len(slots) - 1) return _FOCUS_BLOCK_RE.sub(repl, markdown or ""), slots def restore_focus_fences(markdown: str, slots: list[str]) -> str: text = markdown for index, slot in enumerate(slots): text = text.replace(_HOLD_TOKEN.format(index=index), slot) return text