diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7f0770de9..b7690f753 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -90,7 +90,7 @@ jobs:
test-e2e-web:
needs: [changes]
if: needs.changes.outputs.web == 'true'
- runs-on: macos-26
+ runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -98,16 +98,23 @@ jobs:
- name: Setup
uses: ./.github/actions/setup
- - name: Cache Playwright browsers
+ - name: Cache Playwright Docker image
+ id: playwright-image-cache
uses: actions/cache@v4
with:
- path: ~/Library/Caches/ms-playwright
- key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-playwright-
+ path: ${{ runner.temp }}/playwright-image.tar
+ key: ${{ runner.os }}-${{ runner.arch }}-playwright-image-${{ hashFiles('.playwright/docker-image') }}
- - name: Install Playwright browsers
- run: yarn playwright install chromium
+ - name: Load Playwright Docker image
+ if: steps.playwright-image-cache.outputs.cache-hit == 'true'
+ run: docker load -i "${{ runner.temp }}/playwright-image.tar"
+
+ - name: Pull Playwright Docker image
+ if: steps.playwright-image-cache.outputs.cache-hit != 'true'
+ run: |
+ IMAGE="$(cat .playwright/docker-image)"
+ docker pull "$IMAGE"
+ docker save "$IMAGE" -o "${{ runner.temp }}/playwright-image.tar"
- name: Run web e2e tests
run: yarn test:e2e:web
@@ -117,7 +124,9 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: playwright-report
- path: .playwright/playwright-report/
+ path: |
+ .playwright/playwright-report/
+ .playwright/test-results/
retention-days: 7
build-library:
diff --git a/.playwright/docker-image b/.playwright/docker-image
new file mode 100644
index 000000000..57877c9b8
--- /dev/null
+++ b/.playwright/docker-image
@@ -0,0 +1 @@
+mcr.microsoft.com/playwright:v1.58.2-noble
diff --git a/.playwright/fonts.conf b/.playwright/fonts.conf
new file mode 100644
index 000000000..d8f9aac15
--- /dev/null
+++ b/.playwright/fonts.conf
@@ -0,0 +1,30 @@
+
+
+
+
+
+ sans-serif
+ Liberation Sans
+
+
+ system-ui
+ Liberation Sans
+
+
+ Helvetica Neue
+ Liberation Sans
+
+
+ serif
+ Liberation Serif
+
+
+ monospace
+ Liberation Mono
+
+
\ No newline at end of file
diff --git a/.playwright/playwright.config.ts b/.playwright/playwright.config.ts
index cf2e60e7c..e7f8dda07 100644
--- a/.playwright/playwright.config.ts
+++ b/.playwright/playwright.config.ts
@@ -2,6 +2,18 @@ import { defineConfig, devices } from '@playwright/test';
const port = process.env.PW_PORT ?? '5173';
+// By default, the browser runs in the official Playwright Linux container
+// (started by scripts/run-tests.sh) so screenshots render identically on every
+// machine and in CI. Set PW_LOCAL_BROWSER=1 to use a locally installed browser
+// instead, e.g. for headed debugging - screenshot assertions won't match then.
+const connectOptions = process.env.PW_LOCAL_BROWSER
+ ? undefined
+ : {
+ wsEndpoint: process.env.PW_WS_ENDPOINT ?? 'ws://127.0.0.1:3000/',
+ // Lets the containerised browser reach the Vite server on host localhost.
+ exposeNetwork: '',
+ };
+
export default defineConfig({
testDir: './tests',
outputDir: './test-results',
@@ -27,6 +39,7 @@ export default defineConfig({
screenshot: 'only-on-failure',
video: 'retain-on-failure',
permissions: ['clipboard-read', 'clipboard-write'],
+ connectOptions,
},
webServer: {
diff --git a/.playwright/screenshots/alignment-mixed.png b/.playwright/screenshots/alignment-mixed.png
index 32dfb4888..e653e378b 100644
Binary files a/.playwright/screenshots/alignment-mixed.png and b/.playwright/screenshots/alignment-mixed.png differ
diff --git a/.playwright/screenshots/codeblock-inline-styles-paste-stripped.png b/.playwright/screenshots/codeblock-inline-styles-paste-stripped.png
index 40090966a..e8d53bd1d 100644
Binary files a/.playwright/screenshots/codeblock-inline-styles-paste-stripped.png and b/.playwright/screenshots/codeblock-inline-styles-paste-stripped.png differ
diff --git a/.playwright/screenshots/codeblock-inline-styles-setvalue-stripped.png b/.playwright/screenshots/codeblock-inline-styles-setvalue-stripped.png
index 56d2a1e6f..76aaf993b 100644
Binary files a/.playwright/screenshots/codeblock-inline-styles-setvalue-stripped.png and b/.playwright/screenshots/codeblock-inline-styles-setvalue-stripped.png differ
diff --git a/.playwright/screenshots/display-alignment-blockquotes.png b/.playwright/screenshots/display-alignment-blockquotes.png
index 220824953..6992caa7f 100644
Binary files a/.playwright/screenshots/display-alignment-blockquotes.png and b/.playwright/screenshots/display-alignment-blockquotes.png differ
diff --git a/.playwright/screenshots/display-alignment-checkbox.png b/.playwright/screenshots/display-alignment-checkbox.png
index 953b4c05d..a96371ca4 100644
Binary files a/.playwright/screenshots/display-alignment-checkbox.png and b/.playwright/screenshots/display-alignment-checkbox.png differ
diff --git a/.playwright/screenshots/display-alignment-headings.png b/.playwright/screenshots/display-alignment-headings.png
index a9879b4b7..367c9fc74 100644
Binary files a/.playwright/screenshots/display-alignment-headings.png and b/.playwright/screenshots/display-alignment-headings.png differ
diff --git a/.playwright/screenshots/display-alignment-mixed-lists.png b/.playwright/screenshots/display-alignment-mixed-lists.png
index 3a9874e6e..3a25288a0 100644
Binary files a/.playwright/screenshots/display-alignment-mixed-lists.png and b/.playwright/screenshots/display-alignment-mixed-lists.png differ
diff --git a/.playwright/screenshots/display-alignment-ol.png b/.playwright/screenshots/display-alignment-ol.png
index e28ae905d..fcac84828 100644
Binary files a/.playwright/screenshots/display-alignment-ol.png and b/.playwright/screenshots/display-alignment-ol.png differ
diff --git a/.playwright/screenshots/display-alignment-paragraphs.png b/.playwright/screenshots/display-alignment-paragraphs.png
index 654fda31a..28cfe3b4b 100644
Binary files a/.playwright/screenshots/display-alignment-paragraphs.png and b/.playwright/screenshots/display-alignment-paragraphs.png differ
diff --git a/.playwright/screenshots/display-alignment-ul.png b/.playwright/screenshots/display-alignment-ul.png
index c1f667e87..28f15140f 100644
Binary files a/.playwright/screenshots/display-alignment-ul.png and b/.playwright/screenshots/display-alignment-ul.png differ
diff --git a/.playwright/screenshots/ellipsize-between-empty-paragraphs-clip.png b/.playwright/screenshots/ellipsize-between-empty-paragraphs-clip.png
index f36c8d91c..d3f0b952e 100644
Binary files a/.playwright/screenshots/ellipsize-between-empty-paragraphs-clip.png and b/.playwright/screenshots/ellipsize-between-empty-paragraphs-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-between-empty-paragraphs-head.png b/.playwright/screenshots/ellipsize-between-empty-paragraphs-head.png
index 84b46e35f..632f73878 100644
Binary files a/.playwright/screenshots/ellipsize-between-empty-paragraphs-head.png and b/.playwright/screenshots/ellipsize-between-empty-paragraphs-head.png differ
diff --git a/.playwright/screenshots/ellipsize-between-empty-paragraphs-tail.png b/.playwright/screenshots/ellipsize-between-empty-paragraphs-tail.png
index c7640c0ad..034e3983e 100644
Binary files a/.playwright/screenshots/ellipsize-between-empty-paragraphs-tail.png and b/.playwright/screenshots/ellipsize-between-empty-paragraphs-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-between-multiple-empty-lines-head.png b/.playwright/screenshots/ellipsize-between-multiple-empty-lines-head.png
index 84b46e35f..632f73878 100644
Binary files a/.playwright/screenshots/ellipsize-between-multiple-empty-lines-head.png and b/.playwright/screenshots/ellipsize-between-multiple-empty-lines-head.png differ
diff --git a/.playwright/screenshots/ellipsize-between-multiple-empty-lines-tail.png b/.playwright/screenshots/ellipsize-between-multiple-empty-lines-tail.png
index 84b46e35f..632f73878 100644
Binary files a/.playwright/screenshots/ellipsize-between-multiple-empty-lines-tail.png and b/.playwright/screenshots/ellipsize-between-multiple-empty-lines-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-breaklines-head-fallback-middle.png b/.playwright/screenshots/ellipsize-breaklines-head-fallback-middle.png
index 3b8ad949e..011523fb2 100644
Binary files a/.playwright/screenshots/ellipsize-breaklines-head-fallback-middle.png and b/.playwright/screenshots/ellipsize-breaklines-head-fallback-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-clip.png b/.playwright/screenshots/ellipsize-checkbox-list-clip.png
index ac83dbe10..8ce3ceeb7 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-clip.png and b/.playwright/screenshots/ellipsize-checkbox-list-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-head.png b/.playwright/screenshots/ellipsize-checkbox-list-head.png
index ebb59d007..b11982356 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-head.png and b/.playwright/screenshots/ellipsize-checkbox-list-head.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-only-empty-clip.png b/.playwright/screenshots/ellipsize-checkbox-list-only-empty-clip.png
index df0892603..88a720cdf 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-only-empty-clip.png and b/.playwright/screenshots/ellipsize-checkbox-list-only-empty-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-only-empty-head.png b/.playwright/screenshots/ellipsize-checkbox-list-only-empty-head.png
index 2a36fcfc4..c00c2942e 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-only-empty-head.png and b/.playwright/screenshots/ellipsize-checkbox-list-only-empty-head.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-only-empty-tail.png b/.playwright/screenshots/ellipsize-checkbox-list-only-empty-tail.png
index 2a36fcfc4..c00c2942e 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-only-empty-tail.png and b/.playwright/screenshots/ellipsize-checkbox-list-only-empty-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-tail.png b/.playwright/screenshots/ellipsize-checkbox-list-tail.png
index c4285bc79..f4b8c7848 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-tail.png and b/.playwright/screenshots/ellipsize-checkbox-list-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-with-empty-clip.png b/.playwright/screenshots/ellipsize-checkbox-list-with-empty-clip.png
index 2fe6b126c..25ada4f23 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-with-empty-clip.png and b/.playwright/screenshots/ellipsize-checkbox-list-with-empty-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-with-empty-head.png b/.playwright/screenshots/ellipsize-checkbox-list-with-empty-head.png
index 14084c588..ab8a4bc00 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-with-empty-head.png and b/.playwright/screenshots/ellipsize-checkbox-list-with-empty-head.png differ
diff --git a/.playwright/screenshots/ellipsize-checkbox-list-with-empty-tail.png b/.playwright/screenshots/ellipsize-checkbox-list-with-empty-tail.png
index 76f5298d0..75a3f3f25 100644
Binary files a/.playwright/screenshots/ellipsize-checkbox-list-with-empty-tail.png and b/.playwright/screenshots/ellipsize-checkbox-list-with-empty-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-different-blocks-head-fallback-middle.png b/.playwright/screenshots/ellipsize-different-blocks-head-fallback-middle.png
index a20039d38..2b7adb8b9 100644
Binary files a/.playwright/screenshots/ellipsize-different-blocks-head-fallback-middle.png and b/.playwright/screenshots/ellipsize-different-blocks-head-fallback-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-different-paragraph-style-clip.png b/.playwright/screenshots/ellipsize-different-paragraph-style-clip.png
index aaa78b98d..b535a08a8 100644
Binary files a/.playwright/screenshots/ellipsize-different-paragraph-style-clip.png and b/.playwright/screenshots/ellipsize-different-paragraph-style-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-different-paragraph-style-head.png b/.playwright/screenshots/ellipsize-different-paragraph-style-head.png
index 73ab67473..69226139c 100644
Binary files a/.playwright/screenshots/ellipsize-different-paragraph-style-head.png and b/.playwright/screenshots/ellipsize-different-paragraph-style-head.png differ
diff --git a/.playwright/screenshots/ellipsize-different-paragraph-style-middle.png b/.playwright/screenshots/ellipsize-different-paragraph-style-middle.png
index b53a35bbc..4a83ccf2b 100644
Binary files a/.playwright/screenshots/ellipsize-different-paragraph-style-middle.png and b/.playwright/screenshots/ellipsize-different-paragraph-style-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-different-paragraph-style-multiple-lines-middle.png b/.playwright/screenshots/ellipsize-different-paragraph-style-multiple-lines-middle.png
index 111980d76..8309af2f4 100644
Binary files a/.playwright/screenshots/ellipsize-different-paragraph-style-multiple-lines-middle.png and b/.playwright/screenshots/ellipsize-different-paragraph-style-multiple-lines-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-different-paragraph-style-tail.png b/.playwright/screenshots/ellipsize-different-paragraph-style-tail.png
index 5db8387f1..1312839f6 100644
Binary files a/.playwright/screenshots/ellipsize-different-paragraph-style-tail.png and b/.playwright/screenshots/ellipsize-different-paragraph-style-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-clip.png b/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-clip.png
index 268d926e6..fe2fa5cab 100644
Binary files a/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-clip.png and b/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-head.png b/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-head.png
index 565421f3e..4c44cfce8 100644
Binary files a/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-head.png and b/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-head.png differ
diff --git a/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-tail.png b/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-tail.png
index 7d248d8f4..64f52e8c3 100644
Binary files a/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-tail.png and b/.playwright/screenshots/ellipsize-different-paragraph-style-with-empty-line-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-empty-in-the-middle-clip.png b/.playwright/screenshots/ellipsize-empty-in-the-middle-clip.png
index 04b9902ca..9f5ede19b 100644
Binary files a/.playwright/screenshots/ellipsize-empty-in-the-middle-clip.png and b/.playwright/screenshots/ellipsize-empty-in-the-middle-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-empty-in-the-middle-head.png b/.playwright/screenshots/ellipsize-empty-in-the-middle-head.png
index c84d280d1..c4fd38972 100644
Binary files a/.playwright/screenshots/ellipsize-empty-in-the-middle-head.png and b/.playwright/screenshots/ellipsize-empty-in-the-middle-head.png differ
diff --git a/.playwright/screenshots/ellipsize-empty-in-the-middle-tail.png b/.playwright/screenshots/ellipsize-empty-in-the-middle-tail.png
index f7894459f..e84ec1131 100644
Binary files a/.playwright/screenshots/ellipsize-empty-in-the-middle-tail.png and b/.playwright/screenshots/ellipsize-empty-in-the-middle-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-empty-lines-middle.png b/.playwright/screenshots/ellipsize-empty-lines-middle.png
index 2206b3ec4..d2ad0a27b 100644
Binary files a/.playwright/screenshots/ellipsize-empty-lines-middle.png and b/.playwright/screenshots/ellipsize-empty-lines-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-htmlstyle-blockquote-gapwidth-recompute.png b/.playwright/screenshots/ellipsize-htmlstyle-blockquote-gapwidth-recompute.png
index 9a3233583..e27e7dc8c 100644
Binary files a/.playwright/screenshots/ellipsize-htmlstyle-blockquote-gapwidth-recompute.png and b/.playwright/screenshots/ellipsize-htmlstyle-blockquote-gapwidth-recompute.png differ
diff --git a/.playwright/screenshots/ellipsize-htmlstyle-heading-fontsize-recompute.png b/.playwright/screenshots/ellipsize-htmlstyle-heading-fontsize-recompute.png
index 33f1da974..accb388c2 100644
Binary files a/.playwright/screenshots/ellipsize-htmlstyle-heading-fontsize-recompute.png and b/.playwright/screenshots/ellipsize-htmlstyle-heading-fontsize-recompute.png differ
diff --git a/.playwright/screenshots/ellipsize-htmlstyle-ol-marginleft-recompute.png b/.playwright/screenshots/ellipsize-htmlstyle-ol-marginleft-recompute.png
index 40c6b5533..da72e8abb 100644
Binary files a/.playwright/screenshots/ellipsize-htmlstyle-ol-marginleft-recompute.png and b/.playwright/screenshots/ellipsize-htmlstyle-ol-marginleft-recompute.png differ
diff --git a/.playwright/screenshots/ellipsize-inline-images-clip.png b/.playwright/screenshots/ellipsize-inline-images-clip.png
index 8b148c0a4..d77aa9177 100644
Binary files a/.playwright/screenshots/ellipsize-inline-images-clip.png and b/.playwright/screenshots/ellipsize-inline-images-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-inline-images-head.png b/.playwright/screenshots/ellipsize-inline-images-head.png
index f6c7e1870..423579c43 100644
Binary files a/.playwright/screenshots/ellipsize-inline-images-head.png and b/.playwright/screenshots/ellipsize-inline-images-head.png differ
diff --git a/.playwright/screenshots/ellipsize-inline-images-tail.png b/.playwright/screenshots/ellipsize-inline-images-tail.png
index 2bf67c328..6b605082d 100644
Binary files a/.playwright/screenshots/ellipsize-inline-images-tail.png and b/.playwright/screenshots/ellipsize-inline-images-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-clip.png b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-clip.png
index ca3b78f5f..8ed0dee1e 100644
Binary files a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-clip.png and b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-head.png b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-head.png
index da05a5261..9a21c5f5c 100644
Binary files a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-head.png and b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-head.png differ
diff --git a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-tail.png b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-tail.png
index 0b76dcb15..090426db6 100644
Binary files a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-tail.png and b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-clip.png b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-clip.png
index ca3b78f5f..8ed0dee1e 100644
Binary files a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-clip.png and b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-head.png b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-head.png
index d021554b9..203809afc 100644
Binary files a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-head.png and b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-head.png differ
diff --git a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-tail.png b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-tail.png
index 0b76dcb15..090426db6 100644
Binary files a/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-tail.png and b/.playwright/screenshots/ellipsize-multiple-short-paragraphs-with-last-overflow-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-one-paragraph-many-inline-images-middle.png b/.playwright/screenshots/ellipsize-one-paragraph-many-inline-images-middle.png
index f4d7bc56a..2997eacdb 100644
Binary files a/.playwright/screenshots/ellipsize-one-paragraph-many-inline-images-middle.png and b/.playwright/screenshots/ellipsize-one-paragraph-many-inline-images-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-one-paragraph-many-lines-overflowing-middle.png b/.playwright/screenshots/ellipsize-one-paragraph-many-lines-overflowing-middle.png
index 285ea9805..d12ffec3f 100644
Binary files a/.playwright/screenshots/ellipsize-one-paragraph-many-lines-overflowing-middle.png and b/.playwright/screenshots/ellipsize-one-paragraph-many-lines-overflowing-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-one-paragraph-one-line-overflowing-middle.png b/.playwright/screenshots/ellipsize-one-paragraph-one-line-overflowing-middle.png
index 9d7674141..02ce827c3 100644
Binary files a/.playwright/screenshots/ellipsize-one-paragraph-one-line-overflowing-middle.png and b/.playwright/screenshots/ellipsize-one-paragraph-one-line-overflowing-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-one-word-wrapping-clip.png b/.playwright/screenshots/ellipsize-one-word-wrapping-clip.png
index 32d8960fb..b9ea65b3f 100644
Binary files a/.playwright/screenshots/ellipsize-one-word-wrapping-clip.png and b/.playwright/screenshots/ellipsize-one-word-wrapping-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-one-word-wrapping-head.png b/.playwright/screenshots/ellipsize-one-word-wrapping-head.png
index 0ac20f336..4b06d5574 100644
Binary files a/.playwright/screenshots/ellipsize-one-word-wrapping-head.png and b/.playwright/screenshots/ellipsize-one-word-wrapping-head.png differ
diff --git a/.playwright/screenshots/ellipsize-one-word-wrapping-tail.png b/.playwright/screenshots/ellipsize-one-word-wrapping-tail.png
index ee119f893..83b61583e 100644
Binary files a/.playwright/screenshots/ellipsize-one-word-wrapping-tail.png and b/.playwright/screenshots/ellipsize-one-word-wrapping-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-clip.png b/.playwright/screenshots/ellipsize-ordered-list-clip.png
index 01121d7a4..9e8027d27 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-clip.png and b/.playwright/screenshots/ellipsize-ordered-list-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-head.png b/.playwright/screenshots/ellipsize-ordered-list-head.png
index 4496556e7..3b76a4029 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-head.png and b/.playwright/screenshots/ellipsize-ordered-list-head.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-only-empty-clip.png b/.playwright/screenshots/ellipsize-ordered-list-only-empty-clip.png
index aad9e2e1e..b64dce2e7 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-only-empty-clip.png and b/.playwright/screenshots/ellipsize-ordered-list-only-empty-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-only-empty-head.png b/.playwright/screenshots/ellipsize-ordered-list-only-empty-head.png
index d6052f030..5749f1f7e 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-only-empty-head.png and b/.playwright/screenshots/ellipsize-ordered-list-only-empty-head.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-only-empty-tail.png b/.playwright/screenshots/ellipsize-ordered-list-only-empty-tail.png
index d6052f030..5749f1f7e 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-only-empty-tail.png and b/.playwright/screenshots/ellipsize-ordered-list-only-empty-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-tail.png b/.playwright/screenshots/ellipsize-ordered-list-tail.png
index 3b9d38dc6..55a0a19d7 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-tail.png and b/.playwright/screenshots/ellipsize-ordered-list-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-with-empty-clip.png b/.playwright/screenshots/ellipsize-ordered-list-with-empty-clip.png
index f41b3a118..4ec4004d5 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-with-empty-clip.png and b/.playwright/screenshots/ellipsize-ordered-list-with-empty-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-with-empty-head.png b/.playwright/screenshots/ellipsize-ordered-list-with-empty-head.png
index 9a2f4e799..17680cd07 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-with-empty-head.png and b/.playwright/screenshots/ellipsize-ordered-list-with-empty-head.png differ
diff --git a/.playwright/screenshots/ellipsize-ordered-list-with-empty-tail.png b/.playwright/screenshots/ellipsize-ordered-list-with-empty-tail.png
index fe2183139..d412e4064 100644
Binary files a/.playwright/screenshots/ellipsize-ordered-list-with-empty-tail.png and b/.playwright/screenshots/ellipsize-ordered-list-with-empty-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-other-paragraphs-and-break-lines-inside-block-style-middle.png b/.playwright/screenshots/ellipsize-other-paragraphs-and-break-lines-inside-block-style-middle.png
index 5ca41106b..a3a3c34bd 100644
Binary files a/.playwright/screenshots/ellipsize-other-paragraphs-and-break-lines-inside-block-style-middle.png and b/.playwright/screenshots/ellipsize-other-paragraphs-and-break-lines-inside-block-style-middle.png differ
diff --git a/.playwright/screenshots/ellipsize-paragraph-fit-clip.png b/.playwright/screenshots/ellipsize-paragraph-fit-clip.png
index 87805c906..578244e16 100644
Binary files a/.playwright/screenshots/ellipsize-paragraph-fit-clip.png and b/.playwright/screenshots/ellipsize-paragraph-fit-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-paragraph-fit-head.png b/.playwright/screenshots/ellipsize-paragraph-fit-head.png
index 87805c906..578244e16 100644
Binary files a/.playwright/screenshots/ellipsize-paragraph-fit-head.png and b/.playwright/screenshots/ellipsize-paragraph-fit-head.png differ
diff --git a/.playwright/screenshots/ellipsize-paragraph-fit-tail.png b/.playwright/screenshots/ellipsize-paragraph-fit-tail.png
index 87805c906..578244e16 100644
Binary files a/.playwright/screenshots/ellipsize-paragraph-fit-tail.png and b/.playwright/screenshots/ellipsize-paragraph-fit-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-paragraph-styles-mix-clip.png b/.playwright/screenshots/ellipsize-paragraph-styles-mix-clip.png
index 770d71cb9..04581086e 100644
Binary files a/.playwright/screenshots/ellipsize-paragraph-styles-mix-clip.png and b/.playwright/screenshots/ellipsize-paragraph-styles-mix-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-paragraph-styles-mix-head.png b/.playwright/screenshots/ellipsize-paragraph-styles-mix-head.png
index 3299f8262..fe6841bfd 100644
Binary files a/.playwright/screenshots/ellipsize-paragraph-styles-mix-head.png and b/.playwright/screenshots/ellipsize-paragraph-styles-mix-head.png differ
diff --git a/.playwright/screenshots/ellipsize-paragraph-styles-mix-tail.png b/.playwright/screenshots/ellipsize-paragraph-styles-mix-tail.png
index 8d5bf475a..7533bf96a 100644
Binary files a/.playwright/screenshots/ellipsize-paragraph-styles-mix-tail.png and b/.playwright/screenshots/ellipsize-paragraph-styles-mix-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-single-word-clip.png b/.playwright/screenshots/ellipsize-single-word-clip.png
index d80cfbe05..176bc1133 100644
Binary files a/.playwright/screenshots/ellipsize-single-word-clip.png and b/.playwright/screenshots/ellipsize-single-word-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-single-word-head.png b/.playwright/screenshots/ellipsize-single-word-head.png
index ffb8d932e..89d446839 100644
Binary files a/.playwright/screenshots/ellipsize-single-word-head.png and b/.playwright/screenshots/ellipsize-single-word-head.png differ
diff --git a/.playwright/screenshots/ellipsize-single-word-tail.png b/.playwright/screenshots/ellipsize-single-word-tail.png
index d141cde28..e8e33fd0c 100644
Binary files a/.playwright/screenshots/ellipsize-single-word-tail.png and b/.playwright/screenshots/ellipsize-single-word-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-style-fontsize-recompute.png b/.playwright/screenshots/ellipsize-style-fontsize-recompute.png
index 090943f10..f45123f13 100644
Binary files a/.playwright/screenshots/ellipsize-style-fontsize-recompute.png and b/.playwright/screenshots/ellipsize-style-fontsize-recompute.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-clip.png b/.playwright/screenshots/ellipsize-unordered-list-clip.png
index b87657f0f..6a5464763 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-clip.png and b/.playwright/screenshots/ellipsize-unordered-list-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-head.png b/.playwright/screenshots/ellipsize-unordered-list-head.png
index c629ddb56..17d6febbe 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-head.png and b/.playwright/screenshots/ellipsize-unordered-list-head.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-only-empty-clip.png b/.playwright/screenshots/ellipsize-unordered-list-only-empty-clip.png
index 59d0ac8e4..54a53ed52 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-only-empty-clip.png and b/.playwright/screenshots/ellipsize-unordered-list-only-empty-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-only-empty-head.png b/.playwright/screenshots/ellipsize-unordered-list-only-empty-head.png
index 8cad30f0f..11f9cf6a9 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-only-empty-head.png and b/.playwright/screenshots/ellipsize-unordered-list-only-empty-head.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-only-empty-tail.png b/.playwright/screenshots/ellipsize-unordered-list-only-empty-tail.png
index 8cad30f0f..11f9cf6a9 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-only-empty-tail.png and b/.playwright/screenshots/ellipsize-unordered-list-only-empty-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-tail.png b/.playwright/screenshots/ellipsize-unordered-list-tail.png
index 84b9500ca..10210836d 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-tail.png and b/.playwright/screenshots/ellipsize-unordered-list-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-with-empty-clip.png b/.playwright/screenshots/ellipsize-unordered-list-with-empty-clip.png
index 7fdda84fc..5d84e38fa 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-with-empty-clip.png and b/.playwright/screenshots/ellipsize-unordered-list-with-empty-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-with-empty-head.png b/.playwright/screenshots/ellipsize-unordered-list-with-empty-head.png
index 5c9ee5452..c5f16e261 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-with-empty-head.png and b/.playwright/screenshots/ellipsize-unordered-list-with-empty-head.png differ
diff --git a/.playwright/screenshots/ellipsize-unordered-list-with-empty-tail.png b/.playwright/screenshots/ellipsize-unordered-list-with-empty-tail.png
index 1697290a1..01251ce09 100644
Binary files a/.playwright/screenshots/ellipsize-unordered-list-with-empty-tail.png and b/.playwright/screenshots/ellipsize-unordered-list-with-empty-tail.png differ
diff --git a/.playwright/screenshots/ellipsize-very-long-paragraph-clip.png b/.playwright/screenshots/ellipsize-very-long-paragraph-clip.png
index 963c39083..14e4d956e 100644
Binary files a/.playwright/screenshots/ellipsize-very-long-paragraph-clip.png and b/.playwright/screenshots/ellipsize-very-long-paragraph-clip.png differ
diff --git a/.playwright/screenshots/ellipsize-very-long-paragraph-head.png b/.playwright/screenshots/ellipsize-very-long-paragraph-head.png
index 50e3681ac..9dde93a6a 100644
Binary files a/.playwright/screenshots/ellipsize-very-long-paragraph-head.png and b/.playwright/screenshots/ellipsize-very-long-paragraph-head.png differ
diff --git a/.playwright/screenshots/ellipsize-very-long-paragraph-tail.png b/.playwright/screenshots/ellipsize-very-long-paragraph-tail.png
index eb2525254..92b70f9ff 100644
Binary files a/.playwright/screenshots/ellipsize-very-long-paragraph-tail.png and b/.playwright/screenshots/ellipsize-very-long-paragraph-tail.png differ
diff --git a/.playwright/screenshots/enriched-text-all-headings.png b/.playwright/screenshots/enriched-text-all-headings.png
index 39bce62c7..fed8f18fb 100644
Binary files a/.playwright/screenshots/enriched-text-all-headings.png and b/.playwright/screenshots/enriched-text-all-headings.png differ
diff --git a/.playwright/screenshots/enriched-text-all-list-types.png b/.playwright/screenshots/enriched-text-all-list-types.png
index a10a8fde5..0e0236a40 100644
Binary files a/.playwright/screenshots/enriched-text-all-list-types.png and b/.playwright/screenshots/enriched-text-all-list-types.png differ
diff --git a/.playwright/screenshots/enriched-text-blockquote-code-codeblock.png b/.playwright/screenshots/enriched-text-blockquote-code-codeblock.png
index cd7fc5f52..4c52d9f31 100644
Binary files a/.playwright/screenshots/enriched-text-blockquote-code-codeblock.png and b/.playwright/screenshots/enriched-text-blockquote-code-codeblock.png differ
diff --git a/.playwright/screenshots/enriched-text-checkbox-list-checked.png b/.playwright/screenshots/enriched-text-checkbox-list-checked.png
index ba23f891f..9edd43e79 100644
Binary files a/.playwright/screenshots/enriched-text-checkbox-list-checked.png and b/.playwright/screenshots/enriched-text-checkbox-list-checked.png differ
diff --git a/.playwright/screenshots/enriched-text-checkbox-list-empty-items.png b/.playwright/screenshots/enriched-text-checkbox-list-empty-items.png
index 40c593608..134527512 100644
Binary files a/.playwright/screenshots/enriched-text-checkbox-list-empty-items.png and b/.playwright/screenshots/enriched-text-checkbox-list-empty-items.png differ
diff --git a/.playwright/screenshots/enriched-text-checkbox-list-unchecked.png b/.playwright/screenshots/enriched-text-checkbox-list-unchecked.png
index 295f26f61..1a233b287 100644
Binary files a/.playwright/screenshots/enriched-text-checkbox-list-unchecked.png and b/.playwright/screenshots/enriched-text-checkbox-list-unchecked.png differ
diff --git a/.playwright/screenshots/enriched-text-checkbox-list-wrapped.png b/.playwright/screenshots/enriched-text-checkbox-list-wrapped.png
index acc0ea524..9380d0e80 100644
Binary files a/.playwright/screenshots/enriched-text-checkbox-list-wrapped.png and b/.playwright/screenshots/enriched-text-checkbox-list-wrapped.png differ
diff --git a/.playwright/screenshots/enriched-text-images-inline.png b/.playwright/screenshots/enriched-text-images-inline.png
index 50f458c49..6fd340fe3 100644
Binary files a/.playwright/screenshots/enriched-text-images-inline.png and b/.playwright/screenshots/enriched-text-images-inline.png differ
diff --git a/.playwright/screenshots/enriched-text-images-inside-list.png b/.playwright/screenshots/enriched-text-images-inside-list.png
index c8505081f..670373136 100644
Binary files a/.playwright/screenshots/enriched-text-images-inside-list.png and b/.playwright/screenshots/enriched-text-images-inside-list.png differ
diff --git a/.playwright/screenshots/enriched-text-images-placeholder-inline.png b/.playwright/screenshots/enriched-text-images-placeholder-inline.png
index e54cc9893..1d0c677f9 100644
Binary files a/.playwright/screenshots/enriched-text-images-placeholder-inline.png and b/.playwright/screenshots/enriched-text-images-placeholder-inline.png differ
diff --git a/.playwright/screenshots/enriched-text-images-placeholder-list.png b/.playwright/screenshots/enriched-text-images-placeholder-list.png
index 4c32283da..4228620b5 100644
Binary files a/.playwright/screenshots/enriched-text-images-placeholder-list.png and b/.playwright/screenshots/enriched-text-images-placeholder-list.png differ
diff --git a/.playwright/screenshots/enriched-text-line-wrapping.png b/.playwright/screenshots/enriched-text-line-wrapping.png
index db75829e0..1086fd87d 100644
Binary files a/.playwright/screenshots/enriched-text-line-wrapping.png and b/.playwright/screenshots/enriched-text-line-wrapping.png differ
diff --git a/.playwright/screenshots/enriched-text-mentions.png b/.playwright/screenshots/enriched-text-mentions.png
index 8f467d81e..370c94160 100644
Binary files a/.playwright/screenshots/enriched-text-mentions.png and b/.playwright/screenshots/enriched-text-mentions.png differ
diff --git a/.playwright/screenshots/enriched-text-newlines-spaces.png b/.playwright/screenshots/enriched-text-newlines-spaces.png
index 9fb1af06e..c248b61e6 100644
Binary files a/.playwright/screenshots/enriched-text-newlines-spaces.png and b/.playwright/screenshots/enriched-text-newlines-spaces.png differ
diff --git a/.playwright/screenshots/enriched-text-ordered-list-empty-items.png b/.playwright/screenshots/enriched-text-ordered-list-empty-items.png
index 2019cc9b0..c8a75de81 100644
Binary files a/.playwright/screenshots/enriched-text-ordered-list-empty-items.png and b/.playwright/screenshots/enriched-text-ordered-list-empty-items.png differ
diff --git a/.playwright/screenshots/enriched-text-ordered-list-extended-margin-after.png b/.playwright/screenshots/enriched-text-ordered-list-extended-margin-after.png
index 0f1f1fb8b..0b77344c2 100644
Binary files a/.playwright/screenshots/enriched-text-ordered-list-extended-margin-after.png and b/.playwright/screenshots/enriched-text-ordered-list-extended-margin-after.png differ
diff --git a/.playwright/screenshots/enriched-text-ordered-list-extended-margin-before.png b/.playwright/screenshots/enriched-text-ordered-list-extended-margin-before.png
index 053f4b714..f3b04bc08 100644
Binary files a/.playwright/screenshots/enriched-text-ordered-list-extended-margin-before.png and b/.playwright/screenshots/enriched-text-ordered-list-extended-margin-before.png differ
diff --git a/.playwright/screenshots/enriched-text-ordered-list-wrapped.png b/.playwright/screenshots/enriched-text-ordered-list-wrapped.png
index 55ae3652f..d299cbbd5 100644
Binary files a/.playwright/screenshots/enriched-text-ordered-list-wrapped.png and b/.playwright/screenshots/enriched-text-ordered-list-wrapped.png differ
diff --git a/.playwright/screenshots/enriched-text-ordered-list.png b/.playwright/screenshots/enriched-text-ordered-list.png
index 164425475..fc7b87ebb 100644
Binary files a/.playwright/screenshots/enriched-text-ordered-list.png and b/.playwright/screenshots/enriched-text-ordered-list.png differ
diff --git a/.playwright/screenshots/enriched-text-rich-text.png b/.playwright/screenshots/enriched-text-rich-text.png
index 44174ec48..b61dee730 100644
Binary files a/.playwright/screenshots/enriched-text-rich-text.png and b/.playwright/screenshots/enriched-text-rich-text.png differ
diff --git a/.playwright/screenshots/enriched-text-unordered-list-empty-items.png b/.playwright/screenshots/enriched-text-unordered-list-empty-items.png
index 509cf2501..c3ce2d43e 100644
Binary files a/.playwright/screenshots/enriched-text-unordered-list-empty-items.png and b/.playwright/screenshots/enriched-text-unordered-list-empty-items.png differ
diff --git a/.playwright/screenshots/enriched-text-unordered-list-wrapped.png b/.playwright/screenshots/enriched-text-unordered-list-wrapped.png
index 9f85e6c01..e77fe94cc 100644
Binary files a/.playwright/screenshots/enriched-text-unordered-list-wrapped.png and b/.playwright/screenshots/enriched-text-unordered-list-wrapped.png differ
diff --git a/.playwright/screenshots/enriched-text-unordered-list.png b/.playwright/screenshots/enriched-text-unordered-list.png
index 6d948c649..51ceab3ed 100644
Binary files a/.playwright/screenshots/enriched-text-unordered-list.png and b/.playwright/screenshots/enriched-text-unordered-list.png differ
diff --git a/.playwright/screenshots/images-blockquote-placeholder.png b/.playwright/screenshots/images-blockquote-placeholder.png
index 4112d6e27..059441b68 100644
Binary files a/.playwright/screenshots/images-blockquote-placeholder.png and b/.playwright/screenshots/images-blockquote-placeholder.png differ
diff --git a/.playwright/screenshots/images-checkbox-list-placeholder.png b/.playwright/screenshots/images-checkbox-list-placeholder.png
index e9ec213c1..7f885639b 100644
Binary files a/.playwright/screenshots/images-checkbox-list-placeholder.png and b/.playwright/screenshots/images-checkbox-list-placeholder.png differ
diff --git a/.playwright/screenshots/images-loaded-in-list.png b/.playwright/screenshots/images-loaded-in-list.png
index 0f7c10887..164f0dcb7 100644
Binary files a/.playwright/screenshots/images-loaded-in-list.png and b/.playwright/screenshots/images-loaded-in-list.png differ
diff --git a/.playwright/screenshots/images-ol-placeholder.png b/.playwright/screenshots/images-ol-placeholder.png
index f092035f2..9d0019f2c 100644
Binary files a/.playwright/screenshots/images-ol-placeholder.png and b/.playwright/screenshots/images-ol-placeholder.png differ
diff --git a/.playwright/screenshots/images-paragraph-placeholder.png b/.playwright/screenshots/images-paragraph-placeholder.png
index 30820a53a..8cc177a33 100644
Binary files a/.playwright/screenshots/images-paragraph-placeholder.png and b/.playwright/screenshots/images-paragraph-placeholder.png differ
diff --git a/.playwright/screenshots/images-placeholder-empty-src.png b/.playwright/screenshots/images-placeholder-empty-src.png
index cf95530ad..9cc519888 100644
Binary files a/.playwright/screenshots/images-placeholder-empty-src.png and b/.playwright/screenshots/images-placeholder-empty-src.png differ
diff --git a/.playwright/screenshots/images-ul-placeholder.png b/.playwright/screenshots/images-ul-placeholder.png
index d26c58919..26e22bc23 100644
Binary files a/.playwright/screenshots/images-ul-placeholder.png and b/.playwright/screenshots/images-ul-placeholder.png differ
diff --git a/.playwright/screenshots/inline-styles.png b/.playwright/screenshots/inline-styles.png
index ff7c2f693..8ca064d4c 100644
Binary files a/.playwright/screenshots/inline-styles.png and b/.playwright/screenshots/inline-styles.png differ
diff --git a/.playwright/screenshots/links-display.png b/.playwright/screenshots/links-display.png
index 4eed3f638..5876ff7ba 100644
Binary files a/.playwright/screenshots/links-display.png and b/.playwright/screenshots/links-display.png differ
diff --git a/.playwright/screenshots/list-keyboard-backspace-after-lift-bullet.png b/.playwright/screenshots/list-keyboard-backspace-after-lift-bullet.png
index ddeb3436b..6f993e674 100644
Binary files a/.playwright/screenshots/list-keyboard-backspace-after-lift-bullet.png and b/.playwright/screenshots/list-keyboard-backspace-after-lift-bullet.png differ
diff --git a/.playwright/screenshots/list-keyboard-backspace-after-lift-checkbox.png b/.playwright/screenshots/list-keyboard-backspace-after-lift-checkbox.png
index 0df2d6fb8..1a3cdd229 100644
Binary files a/.playwright/screenshots/list-keyboard-backspace-after-lift-checkbox.png and b/.playwright/screenshots/list-keyboard-backspace-after-lift-checkbox.png differ
diff --git a/.playwright/screenshots/list-keyboard-backspace-after-lift-ordered.png b/.playwright/screenshots/list-keyboard-backspace-after-lift-ordered.png
index 6dc870c51..6495c2ed4 100644
Binary files a/.playwright/screenshots/list-keyboard-backspace-after-lift-ordered.png and b/.playwright/screenshots/list-keyboard-backspace-after-lift-ordered.png differ
diff --git a/.playwright/screenshots/list-keyboard-backspace-after-merge-bullet.png b/.playwright/screenshots/list-keyboard-backspace-after-merge-bullet.png
index e6f5816b5..69460895c 100644
Binary files a/.playwright/screenshots/list-keyboard-backspace-after-merge-bullet.png and b/.playwright/screenshots/list-keyboard-backspace-after-merge-bullet.png differ
diff --git a/.playwright/screenshots/list-keyboard-backspace-after-merge-checkbox.png b/.playwright/screenshots/list-keyboard-backspace-after-merge-checkbox.png
index 1747824b6..3bed89e77 100644
Binary files a/.playwright/screenshots/list-keyboard-backspace-after-merge-checkbox.png and b/.playwright/screenshots/list-keyboard-backspace-after-merge-checkbox.png differ
diff --git a/.playwright/screenshots/list-keyboard-backspace-after-merge-ordered.png b/.playwright/screenshots/list-keyboard-backspace-after-merge-ordered.png
index 9e8a61243..413de8b33 100644
Binary files a/.playwright/screenshots/list-keyboard-backspace-after-merge-ordered.png and b/.playwright/screenshots/list-keyboard-backspace-after-merge-ordered.png differ
diff --git a/.playwright/screenshots/list-keyboard-enter-bullet.png b/.playwright/screenshots/list-keyboard-enter-bullet.png
index 5870498a1..95f214da6 100644
Binary files a/.playwright/screenshots/list-keyboard-enter-bullet.png and b/.playwright/screenshots/list-keyboard-enter-bullet.png differ
diff --git a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-bullet.png b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-bullet.png
index 012dd8c67..162a4693b 100644
Binary files a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-bullet.png and b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-bullet.png differ
diff --git a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-checkbox.png b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-checkbox.png
index f1efdb12f..4e0d1f0e2 100644
Binary files a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-checkbox.png and b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-checkbox.png differ
diff --git a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-ordered.png b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-ordered.png
index 602284858..483791ce6 100644
Binary files a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-ordered.png and b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-ordered.png differ
diff --git a/.playwright/screenshots/list-keyboard-enter-checkbox.png b/.playwright/screenshots/list-keyboard-enter-checkbox.png
index 0d1511c3d..380929782 100644
Binary files a/.playwright/screenshots/list-keyboard-enter-checkbox.png and b/.playwright/screenshots/list-keyboard-enter-checkbox.png differ
diff --git a/.playwright/screenshots/list-keyboard-enter-ordered.png b/.playwright/screenshots/list-keyboard-enter-ordered.png
index 268e4fa7e..70fc97c73 100644
Binary files a/.playwright/screenshots/list-keyboard-enter-ordered.png and b/.playwright/screenshots/list-keyboard-enter-ordered.png differ
diff --git a/.playwright/screenshots/list-nested-html-ol-in-ul.png b/.playwright/screenshots/list-nested-html-ol-in-ul.png
index 38f2bd273..b14c0aa37 100644
Binary files a/.playwright/screenshots/list-nested-html-ol-in-ul.png and b/.playwright/screenshots/list-nested-html-ol-in-ul.png differ
diff --git a/.playwright/screenshots/list-nested-html-triple-nested-ul.png b/.playwright/screenshots/list-nested-html-triple-nested-ul.png
index 76186d563..cd1e1a27d 100644
Binary files a/.playwright/screenshots/list-nested-html-triple-nested-ul.png and b/.playwright/screenshots/list-nested-html-triple-nested-ul.png differ
diff --git a/.playwright/screenshots/list-nested-html-ul-in-ol.png b/.playwright/screenshots/list-nested-html-ul-in-ol.png
index 1e38b3ccd..69c44df19 100644
Binary files a/.playwright/screenshots/list-nested-html-ul-in-ol.png and b/.playwright/screenshots/list-nested-html-ul-in-ol.png differ
diff --git a/.playwright/screenshots/list-nested-html-ul-in-ul.png b/.playwright/screenshots/list-nested-html-ul-in-ul.png
index 35f341a6b..d74ef11f8 100644
Binary files a/.playwright/screenshots/list-nested-html-ul-in-ul.png and b/.playwright/screenshots/list-nested-html-ul-in-ul.png differ
diff --git a/.playwright/screenshots/list-wrap-selection-round-trip.png b/.playwright/screenshots/list-wrap-selection-round-trip.png
index eee1124e9..e6b245779 100644
Binary files a/.playwright/screenshots/list-wrap-selection-round-trip.png and b/.playwright/screenshots/list-wrap-selection-round-trip.png differ
diff --git a/.playwright/screenshots/mention-visual.png b/.playwright/screenshots/mention-visual.png
index 2388d6438..4f99ace71 100644
Binary files a/.playwright/screenshots/mention-visual.png and b/.playwright/screenshots/mention-visual.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-blockquote.png b/.playwright/screenshots/paragraph-styles-visual-blockquote.png
index 7738d6ab2..e465d9771 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-blockquote.png and b/.playwright/screenshots/paragraph-styles-visual-blockquote.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-checkbox-list-wrapped.png b/.playwright/screenshots/paragraph-styles-visual-checkbox-list-wrapped.png
index 7ae56add0..6c504e92b 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-checkbox-list-wrapped.png and b/.playwright/screenshots/paragraph-styles-visual-checkbox-list-wrapped.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-checkbox-list.png b/.playwright/screenshots/paragraph-styles-visual-checkbox-list.png
index 769e37a94..1ee255af9 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-checkbox-list.png and b/.playwright/screenshots/paragraph-styles-visual-checkbox-list.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-codeblock.png b/.playwright/screenshots/paragraph-styles-visual-codeblock.png
index 6e01e7477..9f4ba4f0b 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-codeblock.png and b/.playwright/screenshots/paragraph-styles-visual-codeblock.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-headings.png b/.playwright/screenshots/paragraph-styles-visual-headings.png
index abc8741a7..4d5e1fd01 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-headings.png and b/.playwright/screenshots/paragraph-styles-visual-headings.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-after.png b/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-after.png
index 0da7c3ecd..b85fb27bd 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-after.png and b/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-after.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-before.png b/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-before.png
index 7ffd6e6c2..000b3cace 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-before.png and b/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-before.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-ordered-list-wrapped.png b/.playwright/screenshots/paragraph-styles-visual-ordered-list-wrapped.png
index d5c73e198..3e3b8cf79 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-ordered-list-wrapped.png and b/.playwright/screenshots/paragraph-styles-visual-ordered-list-wrapped.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-ordered-list.png b/.playwright/screenshots/paragraph-styles-visual-ordered-list.png
index 3a125b8ff..b761dec01 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-ordered-list.png and b/.playwright/screenshots/paragraph-styles-visual-ordered-list.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-unordered-list-wrapped.png b/.playwright/screenshots/paragraph-styles-visual-unordered-list-wrapped.png
index 5b5a837bb..793836d38 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-unordered-list-wrapped.png and b/.playwright/screenshots/paragraph-styles-visual-unordered-list-wrapped.png differ
diff --git a/.playwright/screenshots/paragraph-styles-visual-unordered-list.png b/.playwright/screenshots/paragraph-styles-visual-unordered-list.png
index 84a373c79..abf154210 100644
Binary files a/.playwright/screenshots/paragraph-styles-visual-unordered-list.png and b/.playwright/screenshots/paragraph-styles-visual-unordered-list.png differ
diff --git a/.playwright/screenshots/wrapped-block-keyboard-backspace-after-lift-blockquote.png b/.playwright/screenshots/wrapped-block-keyboard-backspace-after-lift-blockquote.png
index a7e7db699..ed917e0d2 100644
Binary files a/.playwright/screenshots/wrapped-block-keyboard-backspace-after-lift-blockquote.png and b/.playwright/screenshots/wrapped-block-keyboard-backspace-after-lift-blockquote.png differ
diff --git a/.playwright/screenshots/wrapped-block-keyboard-backspace-after-lift-codeblock.png b/.playwright/screenshots/wrapped-block-keyboard-backspace-after-lift-codeblock.png
index 44e5e8a95..398c0b9c0 100644
Binary files a/.playwright/screenshots/wrapped-block-keyboard-backspace-after-lift-codeblock.png and b/.playwright/screenshots/wrapped-block-keyboard-backspace-after-lift-codeblock.png differ
diff --git a/.playwright/screenshots/wrapped-block-keyboard-backspace-after-merge-blockquote.png b/.playwright/screenshots/wrapped-block-keyboard-backspace-after-merge-blockquote.png
index 6732d690f..31ff4c9ed 100644
Binary files a/.playwright/screenshots/wrapped-block-keyboard-backspace-after-merge-blockquote.png and b/.playwright/screenshots/wrapped-block-keyboard-backspace-after-merge-blockquote.png differ
diff --git a/.playwright/screenshots/wrapped-block-keyboard-backspace-after-merge-codeblock.png b/.playwright/screenshots/wrapped-block-keyboard-backspace-after-merge-codeblock.png
index 1ce18414e..481b5f086 100644
Binary files a/.playwright/screenshots/wrapped-block-keyboard-backspace-after-merge-codeblock.png and b/.playwright/screenshots/wrapped-block-keyboard-backspace-after-merge-codeblock.png differ
diff --git a/.playwright/screenshots/wrapped-block-keyboard-enter-blockquote.png b/.playwright/screenshots/wrapped-block-keyboard-enter-blockquote.png
index cb525768a..53b264961 100644
Binary files a/.playwright/screenshots/wrapped-block-keyboard-enter-blockquote.png and b/.playwright/screenshots/wrapped-block-keyboard-enter-blockquote.png differ
diff --git a/.playwright/screenshots/wrapped-block-keyboard-enter-codeblock.png b/.playwright/screenshots/wrapped-block-keyboard-enter-codeblock.png
index 2cc8b9f98..590ac373d 100644
Binary files a/.playwright/screenshots/wrapped-block-keyboard-enter-codeblock.png and b/.playwright/screenshots/wrapped-block-keyboard-enter-codeblock.png differ
diff --git a/.playwright/scripts/run-tests.sh b/.playwright/scripts/run-tests.sh
index 3a43bdd5f..446347e1c 100755
--- a/.playwright/scripts/run-tests.sh
+++ b/.playwright/scripts/run-tests.sh
@@ -1,11 +1,21 @@
#!/bin/bash
# run-tests.sh - Run Playwright tests.
#
+# The browser runs inside the official Playwright Docker image pinned in
+# .playwright/docker-image (must match the installed @playwright/test version), so screenshots are identical on macOS,
+# Linux and CI. The test runner and Vite dev server stay on the host.
+#
# Usage:
# ./run-tests.sh [--update-screenshots] [playwright-args...]
#
# Options:
# --update-screenshots Update screenshot baselines (maps to --update-snapshots).
+#
+# Environment:
+# PW_LOCAL_BROWSER=1 Use a locally installed browser instead of Docker
+# (screenshot assertions won't match the baselines).
+# PW_WS_ENDPOINT Connect to an already running Playwright server.
+# PW_SERVER_PORT Host port for the Playwright server (default: 3000).
set -euo pipefail
@@ -22,5 +32,50 @@ while [ $# -gt 0 ]; do
done
cd "$REPO_ROOT"
+
+if [ -z "${PW_LOCAL_BROWSER:-}" ] && [ -z "${PW_WS_ENDPOINT:-}" ]; then
+ if ! docker info > /dev/null 2>&1; then
+ echo "error: Docker is not running. Web e2e tests run the browser in the Playwright Docker image." >&2
+ echo "Start Docker, or set PW_LOCAL_BROWSER=1 to use a local browser (screenshots won't match)." >&2
+ exit 1
+ fi
+
+ IMAGE="$(tr -d '[:space:]' < "$REPO_ROOT/.playwright/docker-image")"
+ PW_VERSION="$(node -p "require('@playwright/test/package.json').version")"
+ PW_SERVER_PORT="${PW_SERVER_PORT:-3000}"
+
+ if [[ "$IMAGE" != *":v${PW_VERSION}-"* ]]; then
+ echo "error: .playwright/docker-image ($IMAGE) does not match @playwright/test $PW_VERSION." >&2
+ echo "Update the image tag (and the screenshot baselines) when upgrading Playwright." >&2
+ exit 1
+ fi
+
+ echo "Starting Playwright server ($IMAGE) on port $PW_SERVER_PORT..."
+ CONTAINER_ID="$(docker run -d --rm --init --ipc=host \
+ -p "127.0.0.1:${PW_SERVER_PORT}:3000" \
+ -v "$REPO_ROOT/.playwright/fonts.conf:/etc/fonts/local.conf:ro" \
+ "$IMAGE" \
+ /bin/sh -c "npx -y playwright@${PW_VERSION} run-server --port 3000 --host 0.0.0.0")"
+ trap 'docker stop "$CONTAINER_ID" > /dev/null 2>&1 || true' EXIT
+
+ for _ in $(seq 1 60); do
+ if curl -s -o /dev/null "http://127.0.0.1:${PW_SERVER_PORT}/"; then
+ break
+ fi
+ if ! docker ps -q --no-trunc | grep -q "$CONTAINER_ID"; then
+ echo "error: Playwright server container exited unexpectedly." >&2
+ exit 1
+ fi
+ sleep 1
+ done
+ if ! curl -s -o /dev/null "http://127.0.0.1:${PW_SERVER_PORT}/"; then
+ echo "error: Playwright server did not start in time." >&2
+ docker logs "$CONTAINER_ID" >&2 || true
+ exit 1
+ fi
+
+ export PW_WS_ENDPOINT="ws://127.0.0.1:${PW_SERVER_PORT}/"
+fi
+
# shellcheck disable=SC2086
playwright test --config .playwright/playwright.config.ts $EXTRA
diff --git a/.playwright/tests/applyWrappingListSelection.spec.ts b/.playwright/tests/applyWrappingListSelection.spec.ts
index 630ae1df6..075027e40 100644
--- a/.playwright/tests/applyWrappingListSelection.spec.ts
+++ b/.playwright/tests/applyWrappingListSelection.spec.ts
@@ -41,10 +41,10 @@ for (const { label, toolbarTestId } of LIST_VARIANTS) {
const editor = editorLocator(page);
await editor.click();
- await expect(editor).toHaveScreenshot(ROUND_TRIP_SNAPSHOT);
-
await selectParagraphTextInclusive(page, 1, 3);
+ await expect(editor).toHaveScreenshot(ROUND_TRIP_SNAPSHOT);
+
const listBtn = toolbarButton(page, toolbarTestId);
await listBtn.click();
await listBtn.click();
diff --git a/.playwright/tests/images.spec.ts b/.playwright/tests/images.spec.ts
index 9032d8c96..409bca5d3 100644
--- a/.playwright/tests/images.spec.ts
+++ b/.playwright/tests/images.spec.ts
@@ -169,7 +169,7 @@ test.describe('images', () => {
for (const key of toolbarOrder) {
const editor = await focusEnrichedEditable(page);
await page.waitForTimeout(10);
- await editor.press('Meta+A');
+ await editor.press('ControlOrMeta+A');
await toolbarButton(page, key).click();
await expect
.poll(
diff --git a/.playwright/tests/strictMarks.spec.ts b/.playwright/tests/strictMarks.spec.ts
index 5010ea5be..cc57082e4 100644
--- a/.playwright/tests/strictMarks.spec.ts
+++ b/.playwright/tests/strictMarks.spec.ts
@@ -81,7 +81,7 @@ test.describe('strict marks', () => {
await typeBoldText(page, 'hello world');
- await editor.press('Meta+A');
+ await editor.press('ControlOrMeta+A');
await editor.press('Backspace');
await expect(toolbarButton(page, 'bold')).not.toHaveClass(
diff --git a/.playwright/tests/undoRedo.spec.ts b/.playwright/tests/undoRedo.spec.ts
index 07ad5089c..cfdae9260 100644
--- a/.playwright/tests/undoRedo.spec.ts
+++ b/.playwright/tests/undoRedo.spec.ts
@@ -13,14 +13,12 @@ import { selectRange } from '../helpers/selection';
// entries that can be undone independently.
const HISTORY_GROUP_DELAY = 600;
-const MOD = process.platform === 'darwin' ? 'Meta' : 'Control';
-
async function pressUndo(page: Page) {
- await page.keyboard.press(`${MOD}+z`);
+ await page.keyboard.press('ControlOrMeta+z');
}
async function pressRedo(page: Page) {
- await page.keyboard.press(`${MOD}+Shift+z`);
+ await page.keyboard.press('ControlOrMeta+Shift+z');
}
test.describe('undo / redo', () => {
@@ -74,7 +72,7 @@ test.describe('undo / redo', () => {
await page.keyboard.type('Hello World');
await page.waitForTimeout(HISTORY_GROUP_DELAY);
- await page.keyboard.press(`${MOD}+a`);
+ await page.keyboard.press('ControlOrMeta+a');
await toolbarButton(page, 'bold').click();
expect(await getSerializedHtml(page)).toEqual(
@@ -93,7 +91,7 @@ test.describe('undo / redo', () => {
await page.keyboard.type('Hello World!');
await page.waitForTimeout(HISTORY_GROUP_DELAY);
- await page.keyboard.press(`${MOD}+a`);
+ await page.keyboard.press('ControlOrMeta+a');
await toolbarButton(page, 'bold').click();
await page.waitForTimeout(HISTORY_GROUP_DELAY);
await selectRange(page, 6, 11);
diff --git a/.playwright/tests/wrappedBlockKeyboard.spec.ts b/.playwright/tests/wrappedBlockKeyboard.spec.ts
index 9c8d6f51f..42e18cb0b 100644
--- a/.playwright/tests/wrappedBlockKeyboard.spec.ts
+++ b/.playwright/tests/wrappedBlockKeyboard.spec.ts
@@ -72,10 +72,7 @@ for (const { label, tag, wrapperSelector, toolbarTestId } of WRAPPED_BLOCKS) {
const secondP = paragraphsInWrapper.nth(1);
await secondP.click();
- await editor.press('End');
- for (let i = 0; i < 'second'.length; i++) {
- await editor.press('ArrowLeft', { delay: 60 });
- }
+ await editor.press('Home');
await editor.press('Backspace', { delay: 60 });
diff --git a/docs/docs/misc/contributing.md b/docs/docs/misc/contributing.md
index 3822fd201..1cd70b0b9 100644
--- a/docs/docs/misc/contributing.md
+++ b/docs/docs/misc/contributing.md
@@ -213,11 +213,11 @@ to re-enable it afterwards with `-bool NO`.
### Web (Playwright)
We use [Playwright](https://playwright.dev/) for end-to-end testing of the web
-example. Tests live in `.playwright/tests/`. Install the browser binaries once:
-
-```sh
-yarn playwright install
-```
+example. Tests live in `.playwright/tests/`. The browser runs inside the
+official [Playwright Docker image](https://playwright.dev/docs/docker), pinned
+in `.playwright/docker-image` (bump it together with `@playwright/test`), so screenshots render identically on
+every machine and in CI. Make sure [Docker](https://www.docker.com/) is running
+before you start the tests.
Run the suite from the root directory:
@@ -238,6 +238,15 @@ Append `--ui` for Playwright's
inspect traces). The Playwright config starts the Vite dev server
automatically, so you don't need to run `yarn example-web dev` separately.
+To debug in a locally installed browser (e.g. with `--headed`), install it once
+with `yarn playwright install chromium` and set `PW_LOCAL_BROWSER=1`. Screenshot
+assertions won't match the baselines in this mode, so always update baselines
+through the default Docker setup.
+
+```sh
+PW_LOCAL_BROWSER=1 yarn test:e2e:web --headed
+```
+
## Documentation
The site you're reading is built with [Docusaurus](https://docusaurus.io/) and