diff --git a/CHANGELOG.md b/CHANGELOG.md index 3233fb62a..4b1676c71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ snippet running under file-based execution. * Fixed the snippet editor reporting a save as failed and undelivered when no response was received, which it cannot determine. +* Fixed a long unbroken line of code widening the snippet editor page and pushing the sidebar out of view. ## [3.10.2] (2026-09-01) diff --git a/src/css/edit/_form.scss b/src/css/edit/_form.scss index 99aebec60..165507559 100644 --- a/src/css/edit/_form.scss +++ b/src/css/edit/_form.scss @@ -90,7 +90,12 @@ .snippet-form { display: grid; gap: var(--cs-sidebar-gap); - grid-template-columns: 1fr var(--cs-sidebar-width); + + // The content column is bounded at zero rather than left as a bare 1fr, + // whose automatic minimum is its content width. A single long unbroken line + // of code would otherwise widen the track to fit, taking the sidebar off + // the side of the page with it. + grid-template-columns: minmax(0, 1fr) var(--cs-sidebar-width); grid-template-areas: 'upper sidebar' 'lower sidebar'; transition: all 700ms; @@ -115,6 +120,7 @@ display: flex; flex-flow: column; gap: 24px; + min-inline-size: 0; } .snippet-editor-sidebar { @@ -134,7 +140,7 @@ } @media (width <= 1024px) { - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); } h2, h3 { diff --git a/tests/e2e/code-snippets-edit.spec.ts b/tests/e2e/code-snippets-edit.spec.ts index 2257461bb..f018b055c 100644 --- a/tests/e2e/code-snippets-edit.spec.ts +++ b/tests/e2e/code-snippets-edit.spec.ts @@ -15,6 +15,43 @@ test.describe('Code Snippets Admin', () => { await helper.expectToBeOnSnippetsAdminPage() }) + test('A long unbroken line does not widen the editor page', async ({ page }) => { + const snippetName = SnippetsTestHelper.makeUniqueSnippetName() + + // Saved through the editor rather than WP-CLI. CI runs WP-CLI as root, and + // with file-based execution on, the first snippet saved that way leaves + // root-owned directories that the web server cannot write later snippets + // into, so every snippet saved after it silently never runs. + await helper.createSnippet({ + name: snippetName, + code: `// ${'a'.repeat(4000)}` + }) + + try { + await helper.openSnippet(snippetName) + + // Line wrapping is on by default, and the page widened regardless. + await expect(page.locator('.CodeMirror').first()).toHaveClass(/CodeMirror-wrap/) + + // One pixel of tolerance covers sub-pixel rounding in layout. + const pageOverflow = await page.evaluate(() => + document.documentElement.scrollWidth - document.documentElement.clientWidth) + expect(pageOverflow, 'the page should not scroll sideways').toBeLessThanOrEqual(1) + + const sidebar = await page.locator('.snippet-editor-sidebar').boundingBox() + + if (!sidebar) { + throw new Error('The editor sidebar is not laid out') + } + + const viewportWidth = page.viewportSize()?.width ?? 0 + expect(sidebar.x + sidebar.width, 'the sidebar should stay on screen') + .toBeLessThanOrEqual(viewportWidth + 1) + } finally { + await helper.cleanupSnippet(snippetName) + } + }) + test('Can add a new snippet', async () => { const snippetName = SnippetsTestHelper.makeUniqueSnippetName() await helper.createSnippet({