Skip to content

Commit 67971dc

Browse files
making sure to strip way any html tags
1 parent 5940fae commit 67971dc

File tree

1 file changed

+46
-49
lines changed

1 file changed

+46
-49
lines changed

src/components/spellchecker/SpellChecker.tsx

+46-49
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { useLocalization } from '../../util/localization';
1919
interface Suggestion {
2020
token: string;
2121
known: boolean;
22-
sugg: Array<[string, number]>;
22+
sugg: Array<string>;
2323
}
2424

2525
// eslint-disable-next-line
@@ -64,7 +64,8 @@ const SpellCheckForm = ({
6464
}, [history, lang, text]);
6565

6666
const handleInput = (e: React.FormEvent<HTMLDivElement>) => {
67-
setText(e.currentTarget.innerText);
67+
const plainText = e.currentTarget.innerText;
68+
setText(plainText.replace(/<\/?[^>]+(>|$)/g, '')); // Strip away any HTML tags
6869
};
6970

7071
const handleSubmit = () => {
@@ -78,13 +79,13 @@ const SpellCheckForm = ({
7879
void (async () => {
7980
try {
8081
trackEvent({ category: 'spellchecker', action: 'spellcheck', name: lang, value: text.length });
81-
const [ref, request] = apyFetch('speller', { lang, q: text });
82+
const [ref, request] = apyFetch('speller/voikko', { lang, q: text });
8283
spellcheckResult.current = ref;
83-
setSuggestions((await request).data as Array<Suggestion>);
84+
const data = (await request).data as Array<Suggestion>;
85+
setSuggestions(data);
86+
renderHighlightedText(text, data);
8487
setError(null);
8588
spellcheckResult.current = null;
86-
87-
renderHighlightedText(text);
8889
setLoading(false);
8990
} catch (error) {
9091
if (!axios.isCancel(error)) {
@@ -183,40 +184,38 @@ const SpellCheckForm = ({
183184
initialRender.current = false;
184185
}
185186

186-
const renderHighlightedText = React.useCallback(
187-
(text: string) => {
188-
if (text.trim().length === 0) {
189-
return;
190-
}
187+
const renderHighlightedText = (text: string, suggestions: Suggestion[]) => {
188+
if (text.trim().length === 0) {
189+
return;
190+
}
191191

192-
const contentElement = spellcheckRef.current;
193-
if (contentElement instanceof HTMLElement) {
194-
const savedSelection = saveCaretPosition(contentElement);
195-
const parts = text
196-
.split(/(\s+)/)
197-
.map((word, index) => {
198-
const suggestion = suggestions.find((s) => s.token === word && !s.known);
199-
if (suggestion) {
200-
return `<span key=${index} class="misspelled">${word}</span>`;
201-
} else {
202-
return `<span key=${index} class="correct">${word}</span>`;
203-
}
204-
})
205-
.join('');
206-
207-
contentElement.innerHTML = parts;
208-
const misspelledElements = contentElement.querySelectorAll('.misspelled');
209-
misspelledElements.forEach((element) => {
210-
const word = element.textContent || '';
211-
const eventHandler = (e: Event) => handleWordClick(word, e as MouseEvent | TouchEvent);
212-
element.addEventListener('click', eventHandler);
213-
element.addEventListener('touchstart', eventHandler);
214-
});
215-
restoreCaretPosition(contentElement, savedSelection);
216-
}
217-
},
218-
[suggestions, handleWordClick],
219-
);
192+
const contentElement = spellcheckRef.current;
193+
if (contentElement instanceof HTMLElement) {
194+
const savedSelection = saveCaretPosition(contentElement);
195+
196+
const parts = text
197+
.split(/(\s+)/)
198+
.map((word, index) => {
199+
const suggestion = suggestions.find((s) => s.token === word && !s.known);
200+
if (suggestion) {
201+
return `<span key=${index} class="misspelled">${word}</span>`;
202+
} else {
203+
return `<span key=${index} class="correct">${word}</span>`;
204+
}
205+
})
206+
.join('');
207+
208+
contentElement.innerHTML = parts;
209+
const misspelledElements = contentElement.querySelectorAll('.misspelled');
210+
misspelledElements.forEach((element) => {
211+
const word = element.textContent || '';
212+
const eventHandler = (e: Event) => handleWordClick(word, e as MouseEvent | TouchEvent);
213+
element.addEventListener('click', eventHandler);
214+
element.addEventListener('touchstart', eventHandler);
215+
});
216+
restoreCaretPosition(contentElement, savedSelection);
217+
}
218+
};
220219

221220
const applySuggestion = (suggestion: string) => {
222221
if (!selectedWord) return;
@@ -227,8 +226,8 @@ const SpellCheckForm = ({
227226

228227
setText(updatedText);
229228
setSelectedWord(null);
230-
console.log(updatedText);
231-
renderHighlightedText(updatedText);
229+
setSuggestionPosition(null);
230+
renderHighlightedText(updatedText, suggestions);
232231
};
233232

234233
return (
@@ -252,19 +251,16 @@ const SpellCheckForm = ({
252251
<Form.Label className="col-md-2 col-lg-1 col-form-label text-md-right">{t('Input_Text')}</Form.Label>
253252
<Col md="10">
254253
<div
254+
aria-label="Enter text for spell checking"
255255
className="content-editable"
256256
contentEditable
257257
onInput={handleInput}
258258
onKeyDown={(event: React.KeyboardEvent<HTMLDivElement>) => {
259259
if (event.code === 'Enter' && !event.shiftKey) {
260260
event.preventDefault();
261261
handleSubmit();
262-
}
263-
else if (event.code === 'Tab' || event.code === ' ') {
264-
event.preventDefault();
265262
}
266263
}}
267-
placeholder={t('Spell_Checking_Help')}
268264
ref={spellcheckRef}
269265
role="textbox"
270266
tabIndex={0}
@@ -285,18 +281,19 @@ const SpellCheckForm = ({
285281
>
286282
{suggestions
287283
.find((s) => s.token === selectedWord)
288-
?.sugg.map(([sugg], index) => (
284+
?.sugg.map((suggestion, index) => (
289285
<div
286+
className="suggestion"
290287
key={index}
291-
onClick={() => applySuggestion(sugg)}
288+
onClick={() => applySuggestion(suggestion)}
292289
onKeyDown={(event) => {
293290
if (event.key === 'Enter') {
294-
applySuggestion(sugg);
291+
applySuggestion(suggestion);
295292
}
296293
}}
297294
role="presentation"
298295
>
299-
{sugg}
296+
{suggestion}
300297
</div>
301298
))}
302299
</div>

0 commit comments

Comments
 (0)