Return ``(slug, remaining_sources)`` for pages under ``pages_dir`` whose frontmatter ``sources:`` list contains ``source_file_marker``. Used by the ``openkb remove`` dry-run preview. Lives here, beside ``remove_doc_from_concept_pages`` / ``remove_doc_from_entity_pages`` and sharing
(pages_dir: Path, source_file_marker: str)
| 1379 | |
| 1380 | |
| 1381 | def scan_affected_pages(pages_dir: Path, source_file_marker: str) -> list[tuple[str, int]]: |
| 1382 | """Return ``(slug, remaining_sources)`` for pages under ``pages_dir`` whose |
| 1383 | frontmatter ``sources:`` list contains ``source_file_marker``. |
| 1384 | |
| 1385 | Used by the ``openkb remove`` dry-run preview. Lives here, beside |
| 1386 | ``remove_doc_from_concept_pages`` / ``remove_doc_from_entity_pages`` and |
| 1387 | sharing ``_parse_yaml_list_value`` with them, so the preview and the |
| 1388 | executor can't drift apart on how the sources list is parsed (a hand-rolled |
| 1389 | comma-split here once kept the JSON quotes and matched nothing). |
| 1390 | """ |
| 1391 | affected: list[tuple[str, int]] = [] |
| 1392 | if not pages_dir.is_dir(): |
| 1393 | return affected |
| 1394 | for path in sorted(pages_dir.glob("*.md")): |
| 1395 | text = path.read_text(encoding="utf-8") |
| 1396 | fm_dict = frontmatter.parse(text) |
| 1397 | if not fm_dict: |
| 1398 | continue |
| 1399 | sources = fm_dict.get("sources") |
| 1400 | if not isinstance(sources, list): |
| 1401 | continue |
| 1402 | items = [str(x) for x in sources] |
| 1403 | if source_file_marker in items: |
| 1404 | affected.append((path.stem, max(len(items) - 1, 0))) |
| 1405 | return affected |
| 1406 | |
| 1407 | |
| 1408 | def remove_doc_from_concept_pages( |