diff --git a/packages/core/src/editor/Block.css b/packages/core/src/editor/Block.css index ac367ea619..f528c99f7a 100644 --- a/packages/core/src/editor/Block.css +++ b/packages/core/src/editor/Block.css @@ -42,6 +42,12 @@ BASIC STYLES .bn-inline-content { width: 100%; + /* Ensure pre-wrap even when a parent node view wrapper (e.g. tiptap's + NodeViewWrapper) resets white-space to "normal". Without this, browsers + normalize trailing spaces to NBSP on input, which causes ProseMirror to + compute a replacement instead of a pure insertion and breaks the + suggestion-menu trigger detection (issue #2531). */ + white-space: pre-wrap; } /* diff --git a/tests/src/end-to-end/slashmenu/slashmenu-customblock.test.ts b/tests/src/end-to-end/slashmenu/slashmenu-customblock.test.ts new file mode 100644 index 0000000000..55aef164bc --- /dev/null +++ b/tests/src/end-to-end/slashmenu/slashmenu-customblock.test.ts @@ -0,0 +1,46 @@ +import { expect } from "@playwright/test"; +import { test } from "../../setup/setupScript.js"; +import { ALERT_BLOCK_URL, SLASH_MENU_SELECTOR } from "../../utils/const.js"; + +// Regression test for https://github.com/TypeCellOS/BlockNote/issues/2531 +// The slash menu should open when "/" is typed after a space inside a custom +// block (isolating: true, separate contentDOM). Previously the menu failed to +// open in this scenario. +test.describe("Slash menu in custom (alert) block – issue #2531", () => { + test.beforeEach(async ({ page }) => { + await page.goto(ALERT_BLOCK_URL); + await page.waitForSelector(".bn-editor"); + }); + + test("opens slash menu when / is typed at end of alert block content (no preceding space)", async ({ + page, + }) => { + // Click into the editable content area of the alert block + const alertContent = page + .locator('[data-content-type="alert"]') + .first() + .locator(".bn-inline-content"); + await alertContent.click(); + await page.keyboard.press("End"); + + await page.keyboard.type("/"); + await expect(page.locator(SLASH_MENU_SELECTOR)).toBeVisible(); + }); + + test("opens slash menu when / is typed after a space inside alert block (the regression)", async ({ + page, + }) => { + // Click into the editable content area of the alert block + const alertContent = page + .locator('[data-content-type="alert"]') + .first() + .locator(".bn-inline-content"); + await alertContent.click(); + await page.keyboard.press("End"); + + // Type a space first — this is the scenario that broke the menu + await page.keyboard.type(" "); + await page.keyboard.type("/"); + await expect(page.locator(SLASH_MENU_SELECTOR)).toBeVisible(); + }); +}); diff --git a/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-chromium-linux.png b/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-chromium-linux.png index 4c78e5e1c0..d471faef1c 100644 Binary files a/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-chromium-linux.png and b/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-chromium-linux.png differ diff --git a/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-firefox-linux.png b/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-firefox-linux.png index 9cd4c44704..7fba12d8d6 100644 Binary files a/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-firefox-linux.png and b/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-firefox-linux.png differ diff --git a/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-webkit-linux.png b/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-webkit-linux.png index fdece429b8..68c749782b 100644 Binary files a/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-webkit-linux.png and b/tests/src/end-to-end/static/static.test.ts-snapshots/static-rendering-webkit-linux.png differ diff --git a/tests/src/utils/const.ts b/tests/src/utils/const.ts index 04cca1cee6..61cedc194d 100644 --- a/tests/src/utils/const.ts +++ b/tests/src/utils/const.ts @@ -39,6 +39,10 @@ export const CUSTOM_BLOCKS_REACT_URL = !process.env.RUN_IN_DOCKER ? `http://localhost:${PORT}/custom-schema/react-custom-blocks?hideMenu` : `http://host.docker.internal:${PORT}/custom-schema/react-custom-blocks?hideMenu`; +export const ALERT_BLOCK_URL = !process.env.RUN_IN_DOCKER + ? `http://localhost:${PORT}/custom-schema/alert-block?hideMenu` + : `http://host.docker.internal:${PORT}/custom-schema/alert-block?hideMenu`; + export const PASTE_ZONE_SELECTOR = "#pasteZone"; export const EDITOR_SELECTOR = `.bn-editor`;