diff --git a/packages/carta-md/src/lib/internal/components/Input.svelte b/packages/carta-md/src/lib/internal/components/Input.svelte index f6037a6a..87257f52 100644 --- a/packages/carta-md/src/lib/internal/components/Input.svelte +++ b/packages/carta-md/src/lib/internal/components/Input.svelte @@ -146,6 +146,11 @@ return { html, timestamp }; } catch (e) { console.error(`Error executing speculative update: ${e}.`); + // The overlay still holds the previous text, but the debounced highlight is already + // on its way and will render `value`. Keep the baseline in sync with it, otherwise it + // stays at the pre-change text and the next patch sees the whole document as added, + // replaying it into the overlay (the text is duplicated until the debounce lands). + currentlyHighlightedValue = value; } } diff --git a/packages/carta-md/src/lib/internal/speculative.ts b/packages/carta-md/src/lib/internal/speculative.ts index 5102f272..fd1f5a07 100644 --- a/packages/carta-md/src/lib/internal/speculative.ts +++ b/packages/carta-md/src/lib/internal/speculative.ts @@ -223,7 +223,12 @@ function checkPosition(position: Position, lines: Element[]): Position { if (nextPosition.span >= lineElement.children.length) { nextPosition.char = 0; nextPosition.span = 0; - nextPosition.line = line + 1; + // Only advance to the next line if there is one. The overlay of an empty document is a + // single line without spans (``), so wrapping past it would + // leave `line` at `lines.length`; writing there reads `children` of `undefined`. + if (line + 1 < lines.length) { + nextPosition.line = line + 1; + } } return nextPosition;