Skip to content

Commit

Permalink
fix: do not use Selection to remove content
Browse files Browse the repository at this point in the history
Related to: #104
  • Loading branch information
BearToCode committed Jul 25, 2024
1 parent b02792a commit c341598
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 43 deletions.
18 changes: 5 additions & 13 deletions packages/carta-md/src/lib/internal/components/Input.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -112,21 +112,13 @@
}, 300);
const onValueChange = (value: string) => {
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
if (isMobile) {
// On mobile, highlight immediately as using the debounced version
// causes issues with the keyboard and focus.
highlight(value);
} else {
if (highlightElem) {
speculativeHighlightUpdate(highlightElem, prevValue, value);
requestAnimationFrame(resize);
}
debouncedHighlight(value);
if (highlightElem) {
speculativeHighlightUpdate(highlightElem, prevValue, value);
requestAnimationFrame(resize);
}
debouncedHighlight(value);
highlightNestedLanguages(value);
};
Expand Down
47 changes: 17 additions & 30 deletions packages/carta-md/src/lib/internal/speculative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ export function speculativeHighlightUpdate(container: HTMLDivElement, from: stri
advance(change.value.length);
};
const addedCallback = (change: Change) => {
const node = textNodes[currentNodeIdx] ?? createTemporaryNode(container);
const node = textNodes.at(currentNodeIdx) ?? createTemporaryNode(container);
if (!node) return; // Could not create a temporary node

const text = node.textContent ?? '';
const pre = text.slice(0, currentNodeCharIdx);
Expand All @@ -54,40 +55,26 @@ export function speculativeHighlightUpdate(container: HTMLDivElement, from: stri
advance(change.value.length);
};
const removedCallback = (change: Change) => {
// Use the Selection object to delete removed text
const startNodeIdx = currentNodeIdx;
const startNodeCharIdx = currentNodeCharIdx;
advance(change.value.length);
const endNodeIdx = currentNodeIdx;
let endNodeCharIdx = currentNodeCharIdx;

const startNode = textNodes[startNodeIdx];
let endNode = textNodes[endNodeIdx];

if (!endNode) {
// Remove everything
endNode = textNodes.at(-1)!;
endNodeCharIdx = endNode.textContent?.length ?? 0;
}

const range = new Range();
range.setStart(startNode, startNodeCharIdx);
range.setEnd(endNode, endNodeCharIdx);
let charsToRemove = change.value.length;

const selection = window.getSelection();
if (!selection) return;
while (charsToRemove > 0) {
const node = textNodes.at(currentNodeIdx);
if (!node) return; // Could not find a node

const initialRanges = new Array(selection.rangeCount).map((_, i) => selection.getRangeAt(i));
selection.removeAllRanges();
const text = node.textContent ?? '';
const availableNodeChars = text.length - currentNodeCharIdx;

selection.addRange(range);
selection.deleteFromDocument();
const stepsTaken = Math.min(availableNodeChars, charsToRemove);

initialRanges.forEach(selection.addRange);
node.textContent =
text.slice(0, currentNodeCharIdx) + text.slice(currentNodeCharIdx + stepsTaken);

// Go back to start
currentNodeIdx = startNodeIdx;
currentNodeCharIdx = startNodeCharIdx;
charsToRemove -= stepsTaken;
if (stepsTaken == availableNodeChars) {
currentNodeIdx++;
currentNodeCharIdx = 0;
}
}
};

for (const change of diff) {
Expand Down

0 comments on commit c341598

Please sign in to comment.