fix(lint): preserve Obsidian heading, block, and embed link syntax#180
fix(lint): preserve Obsidian heading, block, and embed link syntax#180Aldominguez12 wants to merge 2 commits into
Conversation
9d33a56 to
2775a3a
Compare
The single-capture wikilink regex treated [[page#Heading]], [[page#^block]], ![[file.png]] and [[report.pdf]] as whole page targets. None of them can ever match a known target, so lint --fix (strip_ghost_wikilinks) demoted valid Obsidian links to plain text — silently destroying hand-written notes in explorations/ on a full sweep — and find_broken_links reported them all as broken. - Parse the embed marker, target, fragment and alias as named groups. - Validate only the page target; fragments survive fuzzy canonical rewrites ([[concepts/Gist_Memory#Notes]] -> [[concepts/gist-memory#Notes]]). - Pass through attachment embeds/links (extension whitelist) and same-page [[#Heading]] links untouched. - Treat note embeds ![[concepts/x]] as regular page links: validated, rewritten keeping the embed marker, counted as incoming links for orphan detection and as graph edges in visualize. Adds regression coverage including a hand-written explorations/ note that must survive a wiki-wide lint --fix byte-for-byte. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2775a3a to
e8900ac
Compare
|
Nice fix — this closes a real data-loss path and the test coverage is thorough. One thing worth addressing before merge: Excluding |
Exclude [ from the target character class. Allowing it made the scan quadratic on long runs of unmatched brackets (20k chars took ~10s per pass, and lint scans each file twice), and also let [[[a]]] capture [a as the target instead of matching the inner [[a]]. Obsidian forbids [ in note names, so no legitimate link changes behavior. Addresses review feedback on VectifyAI#180. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Good catch — confirmed the quadratic behavior locally (20k unmatched |
Problem
The wikilink regex in
openkb/lint.pycaptured the whole[[...]]body as a single page target. Valid Obsidian syntax therefore never matched a known target:[[page#Heading]]/[[page#^block]]— heading and block links![[file.png]]/[[report.pdf]]— attachment embeds and links[[#Heading]]— same-page fragment links![[concepts/x]]— note embedsConsequences:
openkb lint --fixdestroyed valid links:strip_ghost_wikilinksdemoted them to plain text. A wiki-wide sweep silently mangled hand-written notes inexplorations/— a data-loss path.openkb lintreported them all as broken links (false positives).visualizeand could produce false orphans.Fix
[[concepts/Gist_Memory#Notes]]→[[concepts/gist-memory#Notes]]).[[#Heading]]links untouched.![[concepts/x]]as regular page links: validated, rewritten keeping the!, counted as incoming links for orphan detection, and picked up as graph edges byvisualize(which reuses_extract_wikilinks).Verification
TestObsidianSyntaxcoverage: heading/block/fragment preservation through direct and fuzzy matches, ghost demotion without!residue, attachment/note embed handling, and a regression test asserting a hand-writtenexplorations/note survives a wiki-widelint --fixbyte-for-byte.pytest tests/test_lint.py tests/test_lint_cli.py tests/test_visualize.py tests/test_chat_session.py tests/test_remove.pygreen;ruff check/formatandmypy openkb/lint.pyclean.🤖 Generated with Claude Code