diff --git a/packages/supersearch/e2e/supersearch.spec.ts b/packages/supersearch/e2e/supersearch.spec.ts index 820287a54..f075e66c1 100644 --- a/packages/supersearch/e2e/supersearch.spec.ts +++ b/packages/supersearch/e2e/supersearch.spec.ts @@ -23,3 +23,20 @@ test('submits form identified by form attribute on enter key press', async ({ pa await page.keyboard.press('Enter'); await expect(page).toHaveURL('/test2?q=hello+world'); }); + +test('prevents new line characters (e.g. when pasting multi-lined text', async ({ + page, + context +}) => { + await context.grantPermissions(['clipboard-read', 'clipboard-write']); + await page.locator('[data-test-id="test1"]').getByRole('textbox').locator('div').click(); + await page.evaluate(() => + navigator.clipboard.writeText(`One + two + three`) + ); + await page.keyboard.press(`ControlOrMeta+v`); + await expect(page.locator('[data-test-id="test1"]').getByRole('textbox').locator('div')).toHaveText( + 'One two three' + ); +}); diff --git a/packages/supersearch/src/lib/components/SuperSearch.svelte b/packages/supersearch/src/lib/components/SuperSearch.svelte index 99e2c24cf..b87128a25 100644 --- a/packages/supersearch/src/lib/components/SuperSearch.svelte +++ b/packages/supersearch/src/lib/components/SuperSearch.svelte @@ -4,6 +4,7 @@ import { Compartment } from '@codemirror/state'; import { type LRLanguage } from '@codemirror/language'; import submitFormOnEnterKey from '$lib/extensions/submitFormOnEnterKey.js'; + import preventNewLine from '$lib/extensions/preventNewLine.js'; interface Props { name: string; @@ -22,6 +23,7 @@ const extensions = [ submitFormOnEnterKey(form), + preventNewLine({ replaceWithSpace: true }), ...(language ? [language] : []), placeholderCompartment.of(placeholderExtension(placeholder)) ]; diff --git a/packages/supersearch/src/lib/extensions/preventNewLine.ts b/packages/supersearch/src/lib/extensions/preventNewLine.ts new file mode 100644 index 000000000..eaf91e12d --- /dev/null +++ b/packages/supersearch/src/lib/extensions/preventNewLine.ts @@ -0,0 +1,30 @@ +import { EditorState, Prec } from '@codemirror/state'; + +/** + * CodeMirror extension thats prevents inserted newlines (either by typing or pasting). + * + * @param {boolean} replaceWithSpace Controls if newline characters should be replaced with spaces. + */ + +const preventNewLine = ({ replaceWithSpace = false }: { replaceWithSpace: boolean }) => + Prec.highest( + EditorState.transactionFilter.of((tr) => { + if (tr.newDoc.lines > 1) { + return [ + tr, + { + changes: { + from: 0, + to: tr.newDoc.length, + insert: tr.newDoc.sliceString(0, undefined, replaceWithSpace ? ' ' : '') // flatten multi-lined text + }, + sequential: true + } + ]; + } else { + return [tr]; + } + }) + ); + +export default preventNewLine;