feat: inline cross-reference hyperlinks in law reader#20
feat: inline cross-reference hyperlinks in law reader#20daffaromero wants to merge 19 commits intoilhamfp:mainfrom
Conversation
630f402 to
b826e33
Compare
The usePagination flag was based solely on pasal count (>= 100), but client-side infinite scroll doesn't work when pasals are rendered per-BAB server-side — only the initial 30 SSR pasals were ever shown under their BABs, leaving all subsequent BABs empty. Fix: skip client pagination when the law has BABs/aturan/lampiran structure nodes, and always fetch the full pasal set SSR instead. Flat laws (no BABs) with 100+ pasals still use infinite scroll. Co-authored-by: Claude <noreply@anthropic.com>
…types The original hasBABs check only tested for bab/aturan/lampiran, but the BAB rendering path fires on any structural node (babNodes.length > 0 includes bagian and paragraf nodes too). A law with bagian-only structure and 100+ pasals would still regress under the previous check. Replace hasBABs with hasStructure = structure.length > 0 — aligns the pagination guard directly with the rendering condition. Co-authored-by: Claude <noreply@anthropic.com>
PR Description AuditWent through the description against the actual code. A few things to correct: 1. Test count is wrong — 20, not 31The description says "31/31 Vitest tests passing". The test file ( 2. Cross-document UU links are actually still broken (slug format mismatch)This is the most significant issue. The "Bugs fixed" table says:
This is inverted. The DB trigger ( e.g. The But The tests pass because they construct the The actual correct fix would be to change 3. Bug fix description for the
|
| Claim | Status |
|---|---|
| 31 Vitest tests | Incorrect — 20 tests |
| Cross-UU slug bug "fixed" | Incorrect — still broken (format mismatch between citationToSlugKey and DB slugs) |
i flag added to "all inner regexes" |
Inaccurate — added to outer CROSSREF_RE only |
worksLookup ISR 24h |
Slightly misleading framing |
4c7bf91 to
97842ee
Compare
Laws like UU 6/2023 (Ciptaker) wrap a full law as LAMPIRAN. The parser picks up the LAMPIRAN's table of contents as real BAB nodes, producing heading-only sections with no Pasal content in the reader. Add a lightweight parallel query fetching all parent_id values for pasals of the current work. Build structuralIdsWithPasals Set. Filter babNodes so only top-level structural nodes (BAB/aturan/lampiran) with at least one pasal directly or via a direct child section are rendered. Sub-sections (Bagian/Paragraf, parent_id != null) are kept unconditionally. Co-authored-by: Claude <noreply@anthropic.com>
The previous filter only checked direct children of each top-level BAB node when determining whether it had pasal content. This missed the BAB → Bagian → Paragraf → Pasal nesting depth documented in the schema, causing those BABs to be silently filtered out. Replace with a parent→children map + recursive hasDescendantPasal() that walks the full subtree at any depth, so a BAB is only filtered if no structural node in its entire subtree is a direct parent of a pasal. Co-authored-by: Claude <noreply@anthropic.com>
…l to all structural nodes Remove the unconditional short-circuit that passed any structural node with a non-null parent_id through the babNodes filter. Phantom TOC-BABs inside a LAMPIRAN have parent_id = lampiran_db_id (non-null), so the guard was letting them through despite having zero pasal descendants. Applying hasDescendantPasal() to every structural node regardless of depth fixes UU 6/2023 (Cipta Kerja): the duplicated TOC BABs parsed from the LAMPIRAN TOC pages are now correctly filtered out while real BABs and their Bagian/Paragraf sub-sections remain (they ARE in structuralIdsWithPasals). Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
…ichPasalContent Co-authored-by: Claude <noreply@anthropic.com>
…eference links Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Improves discoverability of cross-reference hyperlinks in pasal body text — always-dotted underline at rest makes links visible without the heavy weight of a permanent solid underline on dense legal prose. Co-authored-by: Claude <noreply@anthropic.com>
Add tests for Perpres/Perda citations, optional Nomor keyword, mixed Pasal+UU in one string, trailing text after last reference, and unknown regulation types falling back to plain text. Co-authored-by: Claude <noreply@anthropic.com>
- Match both 'ayat' and 'Ayat' in the Pasal regex — scanned PDFs vary in capitalization (e.g. 'Pasal 90 Ayat (3)' was not linked before) - citationToSlugKey now produces 'uu-no-13-tahun-2003' format to match the slug column generated by the DB trigger (was producing 'uu-13-2003') - Update all test fixtures and add new Ayat capital-case test Co-authored-by: Claude <noreply@anthropic.com>
Scanned PDFs frequently use all-caps UNDANG-UNDANG, PASAL, PERATURAN etc. Add 'i' flag to CROSSREF_RE so all capitalisation variants are matched. Also adds two new tests covering UNDANG-UNDANG and PASAL all-caps forms. Co-authored-by: Claude <noreply@anthropic.com>
citationToSlugKey() was returning 'uu-no-13-tahun-2003' but the DB
trigger generate_work_slug() (migration 053) produces 'uu-13-2003'.
The worksLookup map is keyed by raw DB slugs, so every cross-document
citation was silently falling back to plain text — never resolving to
a link.
Fix: remove '-no-' and '-tahun-' from the returned key format so it
matches {type}-{number}-{year}.
Update tests to use the correct slug fixtures.
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
97842ee to
3fa3aaa
Compare
Summary
Changes
Bugs fixed
Test Plan