"""Reader-only vocabulary projection; calculation packets and CLI stay untouched.""" from __future__ import annotations import json from pathlib import Path import re # Both runtimes consume this file. ASCII regex semantics deliberately match JS: # Python's default Unicode \b would leave Chinese page references untranslated. _RULES = json.loads(Path(__file__).with_suffix(".rules.json").read_text(encoding="utf-8")) _CHART_FENCE = re.compile(_RULES["chartFencePattern"], re.MULTILINE | re.ASCII) _REPLACEMENTS = [ (re.compile(rule["pattern"], re.ASCII | (re.IGNORECASE if rule.get("ignoreCase") else 0)), rule) for rule in _RULES["rules"] ] def _replace(match: re.Match[str], rule: dict) -> str: if "replacement" in rule: return rule["replacement"] return ( rule.get("prefix", "") + "".join(match[group] for group in rule.get("beforeGroups", [])) + rule["labels"][match[rule["labelGroup"]]] + "".join(match[group] for group in rule.get("afterGroups", [])) ) def clean_reader_appendix_markdown(markdown: str) -> str: """Translate copy without dropping lines, field names, or numeric cells. Ambiguous English words are changed only as complete pipe-table cells. Chart fences are immutable: their JSON is a separate renderer contract. """ parts = _CHART_FENCE.split(markdown) for index in range(0, len(parts), 2): value = parts[index] for pattern, rule in _REPLACEMENTS: value = pattern.sub(lambda match: _replace(match, rule), value) parts[index] = value return "".join(parts)