PERF: Use insertText more efficiently in `replaceText` (#28880)

Followup to e25578d702

Using execCommand to replace the entire contents of the textarea is very slow for larger posts (it seems the browser does a reflow after every 'virtual keypress'.

This commit updates the `replaceText` function to be more surgical with its `insertAt` calls. Now it only selects & replaces the characters which are actually being replaced.
This commit is contained in:
David Taylor 2024-09-12 16:11:39 +01:00 committed by GitHub
parent 600801f194
commit a7cd220704
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 18 additions and 9 deletions

View File

@ -149,16 +149,21 @@ export default Mixin.create({
}); });
if (opts.index && opts.regex) { if (opts.index && opts.regex) {
let i = -1; if (!opts.regex.global) {
const newValue = val.replace(opts.regex, (match) => { throw new Error("Regex must be global");
i++; }
return i === opts.index ? newVal : match;
});
this._insertAt(0, val.length, newValue); const regex = new RegExp(opts.regex);
let match;
for (let i = 0; i <= opts.index; i++) {
match = regex.exec(val);
}
if (match) {
this._insertAt(match.index, match.index + match[0].length, newVal);
}
} else { } else {
const replacedValue = val.replace(oldVal, newVal); this._insertAt(needleStart, needleStart + oldVal.length, newVal);
this._insertAt(0, val.length, replacedValue);
} }
if ( if (
@ -332,7 +337,11 @@ export default Mixin.create({
_insertAt(start, end, text) { _insertAt(start, end, text) {
this._textarea.setSelectionRange(start, end); this._textarea.setSelectionRange(start, end);
this._textarea.focus(); this._textarea.focus();
document.execCommand("insertText", false, text); if (start !== end && text === "") {
document.execCommand("delete", false);
} else {
document.execCommand("insertText", false, text);
}
}, },
extractTable(text) { extractTable(text) {