diff --git a/src/Memoizer.ts b/src/Memoizer.ts index 0ace2982418b420bd56fdc07195cbf9b1f5a687e..81c2adfc023760a02149c449b4080a0273da37e0 100644 --- a/src/Memoizer.ts +++ b/src/Memoizer.ts @@ -100,6 +100,9 @@ export class Memoizer { // much effort), but any extra re-renders get eliminated with AST diffing. const processor = UNWRAP(this.#astProcessor); const parsed = this.#parsed; + const replacedTailAffectedDocument = parsed + .slice(blockStart) + .some((block) => block.some(nodeAffectsDocument)); let parsedTree = processor.parse(content.slice(parseOffset)); let newPositions = parsedTree.children.map( (child) => UNWRAP(UNWRAP(child.position).start.offset) + parseOffset, @@ -118,7 +121,7 @@ export class Memoizer { // If a reflink is involved, fall back to a full reparse. Rehydrating a // synthetic root from cached blocks can lose source offsets on transformed // top-level nodes, which would scramble block bucketing and key identity. - if (nodeAffectsDocument(parsedTree)) { + if (replacedTailAffectedDocument || nodeAffectsDocument(parsedTree)) { blockStart = 0; parseOffset = 0; parsedTree = processor.parse(content); diff --git a/tests/Memoizer.test.tsx b/tests/Memoizer.test.tsx index 0e3df355c15afa3d828131e6aa77ff685d56a532..f34696681e9f4e1329d2a4240ffa9d63bf2bd721 100644 --- a/tests/Memoizer.test.tsx +++ b/tests/Memoizer.test.tsx @@ -140,6 +140,20 @@ describe("Memoizer incremental rendering", () => { expect(after).toContain('href="/two"'); }); + it("keeps earlier gfm footnotes rendered when a later footnote definition is removed", () => { + const incremental = createMemoizer(gfmProcessor); + + incremental.update("a[^b]\n\n[^b]: bee\n\nc"); + incremental.update("a[^b]\n\n[^b]: bee\n\nc[^d]\n\n[^d]: dee"); + const after = renderNodes(incremental.update("a[^b]\n\n[^b]: bee\n\nc[^d]")); + + const fresh = createMemoizer(gfmProcessor); + const expected = renderNodes(fresh.update("a[^b]\n\n[^b]: bee\n\nc[^d]")); + + expect(after).toBe(expected); + expect(after).toContain('id="user-content-fn-b"'); + }); + it.each([ { content: ["alpha\n\nbeta", "alpha\nbeta", "alpha\n\nbeta\n\ngamma", "alpha\n\nbeta"],