fix: Obsidian table paste crash and glued-prose stray row (#16)#17
Conversation
Pasting an Obsidian table followed by a paragraph threw "TypeError: Cannot read properties of null" from ProseMirror's slice fitter. Foundry treats any table with a <thead> (every GFM table from marked) as an isolating "complex" table; fitting an open slice of [isolating table, paragraph] past the isolating boundary dereferences null. insertHtml now tries the open-slice replaceSelection first (preserving inline-merge behavior) and, only on a fitter crash, falls back to parsing a full document and inserting fully-closed content via replaceWith. Building the transform does not mutate state, so the try/catch is safe. Adds tests/insert.test.js (first unit test for insert.js) with a happy-path and an issue #16 regression test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GFM and marked absorb a pipe-less line directly after table rows as a trailing single-cell row, so a note like "*Digested from ...*" placed right under a table became a stray table cell. Obsidian and Typora end the table at that line instead. Add isolateTables() to the Obsidian layer: when a table's last row is immediately followed by a non-blank, pipe-less line, insert a blank line so it parses as its own block. Wired into convert() after stripWikiLinks (so wikilink pipes are already gone) and gated by the existing obsidian option. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 57 minutes and 32 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (4)
📒 Files selected for processing (3)
✨ Finishing Touches🧪 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 |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes #16.
Pasting an Obsidian table into a Foundry journal threw
TypeError: Cannot read properties of nulland, separately, glued a following note line into the table as a stray cell. Two distinct root causes, two commits.1. The crash —
insert.jsconvert()produced valid HTML; the exception came from ProseMirror's slice fitter ininsertHtml. Foundry classifies any table with a<thead>(every GFM table frommarked) as anisolating"complex" table. When the parsed slice is[isolating table, paragraph]— a table followed by a paragraph — fitting the open slice end past the isolating boundary dereferences null and throws.insertHtmlnow tries the open-slicereplaceSelectionfirst (open ends let pasted inline content merge with surrounding text — the nicer result for most pastes) and, only on a fitter crash, falls back to parsing a full document and inserting fully-closed content viareplaceWith. Building a transform doesn't mutate state — onlydispatchdoes — so thetry/catchis safe.Reproduced and verified against the real
prosemirror-tablesfitter driven by Foundry v13's actual table schema: every currently-working case keeps the original slice path; only the crashing cases take the fallback.2. Stray row —
obsidian.jsGFM and
markedabsorb a pipe-less line directly after table rows as a trailing single-cell row, so*Digested from LoDP pg. 39.*placed right under the table became a stray<td>. Obsidian and Typora end the table there instead.New
isolateTables()in the Obsidian layer inserts a blank line between a table's last row and a following non-blank, pipe-less line so it parses as its own block. Wired intoconvert()afterstripWikiLinks(wikilink pipes are already gone) and gated by the existingobsidianoption.Tests
tests/insert.test.js(first unit test forinsert.js): happy-path + Cannot Parse Error When Pasting from Obsidian #16 regression for the fitter-crash fallback.isolateTablesunit tests + 1convertintegration test asserting the note renders as<p>, not<td>.Test plan
npm testgreen (108 tests)eslintclean on changed files🤖 Generated with Claude Code