fix(capture): match multi-line "Insert after" on the inline path (#468)#1370
Conversation
…d of silently missing (#468) Issue #468 asked for multi-line "Insert after" matching. The default (block) path was already fixed in #1333; the inline insert-after path was the remaining gap. It skipped escape expansion, so a multi-line `\n` target silently never matched (Create line if not found off) or wrote a literal backslash-n into the note (Create line if not found on) — while the settings preview expanded `\n` and made the target look valid. - Expand `\n` escapes on the inline target before searching, symmetric with the block path, so a multi-line target trips the existing single-line guard. - That guard now throws ChoiceAbortError (parity with the block path's not-found abort) instead of logging and returning unchanged content, which previously produced a contradictory "Captured" success notice. - Warn in the Capture builder when inline mode has a target that resolves to more than one line, computed with the same FormatDisplayFormatter the live preview uses (no raw-regex drift on escaped `\\n` or token/global expansions). - Tests: new captureChoiceFormatter-468-inline-multiline.test.ts (RED without the fix) plus a backslash-semantics boundary control; update the one frontmatter test that asserted the old log-and-continue behavior. - Docs: note that Inline insertion is single-line by design.
Deploying quickadd with
|
| Latest commit: |
97228d1
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e49a132a.quickadd.pages.dev |
| Branch Preview URL: | https://chhoumann-468-multiline-inse.quickadd.pages.dev |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughInline insert-after now rejects multi-line targets by throwing a ChangesInline insert-after multi-line guard (issue
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Closes #468.
TL;DR
Issue #468 ("Multiline match for Insert After") asked for an Insert-after target spanning multiple lines to match. The default (block) placement already does this — it was fixed by #1333 (it expands
\nescapes and matches a multi-line block viafindMultiLineRange). This PR closes the one remaining gap: the inline insertion path reproduced the exact #468 symptom (and worse).The bug (inline insert-after + multi-line target)
With Inline insertion toggled on and a
\ntarget (e.g.**Today**\n***), the inline branch resolved the target without expanding escapes (captureChoiceFormatter.ts— the block path right below it does expand). So:hasInlineTargetLinebreak, which checks for a real newline) never fired;fileContent.indexOf("**Today**\n***")searched for the literal backslash-n → never present → silent never-match (Create line if not found off), or a garbage line containing a literal\nwritten into the note (Create line if not found on);\n, so the UI showed a valid multi-line block while runtime silently failed — precisely "rendered multi-line in the preview… the match is never successful."Fix
expandFormatTemplateEscapes(after)before searching, symmetric with the block path. A\ntarget becomes a real newline and trips the existing single-line guard.ChoiceAbortError(parity with the block path's not-found abort) instead ofreportError()+ returning unchanged content. The old path let the engine write the (unchanged) file and show a "Captured to X" success notice alongside the error — contradictory. Now the capture aborts cleanly with one clear message and nothing is written.FormatDisplayFormatterthe live preview uses (not a raw regex), so it doesn't false-warn on an escaped\\nand doesn't miss a token/global-var that expands to a newline.\nanchors are for the default placement).Inline insertion is single-line by definition (it inserts mid-line, immediately after the matched substring), so this is an honest error, not a regression — there is no sensible "insert after a multi-line anchor, on the same line." Escapes are now consistent across both insert-after paths:
\nmeans newline; a literal backslash is\\.Tests
src/formatters/captureChoiceFormatter-468-inline-multiline.test.ts— 7 tests. The two core ones are RED without the engine fix (the create-on case writes the literal-\ngarbage; the no-create case throws "not found"). Boundary controls pin the escape semantics: an escaped\\stays a literal backslash and still inserts; aC:\notes-style target aborts (because\nis a newline by QuickAdd convention); a global-var that expands to a newline aborts (guard runs after expansion).tsc,esbuild,svelte-check,eslintall clean.Verified end-to-end
In an isolated Obsidian vault (
provision:e2e-vault+obsidian:e2e):**Today**\n***, block present, no-create → abortsok:falsewith "must be a single line", note unchanged.\nleakage).ok:true) — fix(capture): find multi-line insert-after/before targets instead of duplicating them #1333 behavior preserved.Review
Ultracode design review (3 lenses) + 2 adversarial Codex reviewers (Skeptic + Architect). Their main actionable point — the builder warning's raw-regex drifting from the runtime semantic — is addressed in (3) above. The "literal-backslash reinterpretation" they flagged is the intentional, now-tested consistent semantic (the block path has treated
\nas a newline since #1333; no escape pattern can distinguish**Today**\n***fromC:\notes, so matching the block behavior is the correct choice).Summary by CodeRabbit
Release Notes
Bug Fixes
Documentation
Tests