diff --git a/resources/js/app.js b/resources/js/app.js
index 665388e..1de366e 100644
--- a/resources/js/app.js
+++ b/resources/js/app.js
@@ -196,6 +196,31 @@ function scheduleSpellcheck() {
spellDebounce = setTimeout(runSpellcheck, 600);
}
+ // Returns the token of the word currently being composed
+ function getActiveWordToken() {
+ const sel = window.getSelection();
+ if (!sel || sel.rangeCount === 0) return null;
+
+ const range = sel.getRangeAt(0);
+ if (!range.collapsed) return null;
+ if (!editor.contains(range.startContainer)) return null;
+
+ const container = range.startContainer;
+ if (container.nodeType !== Node.TEXT_NODE) return null;
+
+ const text = container.textContent;
+ const offset = range.startOffset;
+
+ if (offset === 0) return null;
+ const charBefore = text[offset - 1];
+ if (!/[A-Za-z0-9\u00C0-\u024F'\u2019\-]/.test(charBefore)) return null;
+
+ let start = offset - 1;
+ while (start > 0 && /[A-Za-z0-9\u00C0-\u024F'\u2019\-]/.test(text[start - 1])) start--;
+
+ return text.slice(start, offset);
+ }
+
// Canvas drawing
function runSpellcheck() {
if (!spellReady || !spell) {
@@ -205,12 +230,19 @@ function runSpellcheck() {
const text = getEditorText();
+ // Red squiggles only after a word is committed by space, punctuation, newline.
+ const activeToken = getActiveWordToken();
+
// Find misspelled tokens (and hyphen segments)
const misspelled = new Set();
let m;
TOKEN_RE.lastIndex = 0;
while ((m = TOKEN_RE.exec(text)) !== null) {
const { word: token } = getCheckableSpan(m[0]);
+
+ // Suppress the word currently being composed at the caret
+ if (activeToken && token === activeToken) continue;
+
if (isCorrect(token)) continue;
if (token.includes('-')) {