From cdbeb326f2831c4ee93e021eb6e05a7e5e69c473 Mon Sep 17 00:00:00 2001 From: Luffy <52o@qq52o.cn> Date: Wed, 12 Aug 2026 18:02:31 +0800 Subject: [PATCH 1/2] fix: prevent long markdown links from causing horizontal overflow --- src/themes/shared/_markdown.css | 2 + test/e2e/sidebar.test.js | 74 +++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/src/themes/shared/_markdown.css b/src/themes/shared/_markdown.css index b0ba760447..61a58897ee 100644 --- a/src/themes/shared/_markdown.css +++ b/src/themes/shared/_markdown.css @@ -30,6 +30,8 @@ } a { + overflow-wrap: anywhere; + &.anchor { color: inherit; diff --git a/test/e2e/sidebar.test.js b/test/e2e/sidebar.test.js index ff4526601b..534186afbf 100644 --- a/test/e2e/sidebar.test.js +++ b/test/e2e/sidebar.test.js @@ -70,6 +70,80 @@ test.describe('Sidebar Tests', () => { }); }); +test.describe('Mobile sidebar toggle', () => { + test('keeps the collapsed handle centered while scrolling', async ({ + page, + }) => { + await page.setViewportSize({ width: 390, height: 844 }); + + const content = Array.from( + { length: 80 }, + (_, index) => `## Section ${index + 1}\n\nLong content for scrolling.`, + ).join('\n\n'); + + await docsifyInit({ + config: { + loadSidebar: '_sidebar.md', + }, + markdown: { + homepage: `# Mobile scrolling\n\n${content}\n\nhttps://example.com/${'a'.repeat(240)}`, + sidebar: '- [Mobile scrolling](README.md)', + }, + styleURLs: ['/dist/themes/core.css'], + }); + + const toggle = page.locator('.sidebar-toggle'); + + await expect(page.locator('.sidebar')).not.toHaveClass(/show/); + await expect(toggle).toHaveCSS('position', 'fixed'); + await expect + .poll(() => page.evaluate(() => document.documentElement.scrollWidth)) + .toBe(page.viewportSize().width); + + await page.evaluate(() => { + window.__sidebarScrollIntoViewCalls = 0; + const originalScrollIntoView = Element.prototype.scrollIntoView; + + Element.prototype.scrollIntoView = function (...args) { + if (this.closest('.sidebar')) { + window.__sidebarScrollIntoViewCalls++; + } + + return originalScrollIntoView.apply(this, args); + }; + }); + + const getToggleCenter = () => + page.evaluate(() => { + const box = document + .querySelector('.sidebar-toggle-button') + .getBoundingClientRect(); + + return box.top + box.height / 2; + }); + const viewportCenter = await page.evaluate( + () => (visualViewport?.height ?? innerHeight) / 2, + ); + expect(await getToggleCenter()).toBe(viewportCenter); + + // Simulate the sticky state changing while the page is being scrolled. + await page.evaluate(() => document.body.classList.remove('sticky')); + await page.mouse.wheel(0, 1200); + await expect + .poll(() => page.evaluate(() => window.scrollY)) + .toBeGreaterThan(0); + + expect(await getToggleCenter()).toBe(viewportCenter); + expect(await page.evaluate(() => window.__sidebarScrollIntoViewCalls)).toBe( + 0, + ); + + await page.mouse.wheel(0, -1200); + await expect.poll(() => page.evaluate(() => window.scrollY)).toBe(0); + expect(await getToggleCenter()).toBe(viewportCenter); + }); +}); + test.describe('Configuration: autoHeader', () => { test('autoHeader=false', async ({ page }) => { const docsifyInitConfig = { From c1683f95b2ce139ffec4f95591bd0752fec6fac5 Mon Sep 17 00:00:00 2001 From: Luffy <52o@qq52o.cn> Date: Wed, 12 Aug 2026 18:22:58 +0800 Subject: [PATCH 2/2] fix: wrap long links in mobile sidebar test to prevent horizontal overflow --- .github/workflows/test.yml | 2 +- test/e2e/sidebar.test.js | 43 +++----------------------------------- 2 files changed, 4 insertions(+), 41 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8bb0b5348b..8019d5ce43 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -96,7 +96,7 @@ jobs: uses: actions/upload-artifact@v7 if: failure() with: - name: ${{ matrix.os }}-${{ matrix.node-version }}-artifacts + name: test-artifacts-${{ github.run_id }}-${{ github.run_attempt }} path: | _playwright-results/ _playwright-report/ diff --git a/test/e2e/sidebar.test.js b/test/e2e/sidebar.test.js index 534186afbf..88b444d9a5 100644 --- a/test/e2e/sidebar.test.js +++ b/test/e2e/sidebar.test.js @@ -71,11 +71,12 @@ test.describe('Sidebar Tests', () => { }); test.describe('Mobile sidebar toggle', () => { - test('keeps the collapsed handle centered while scrolling', async ({ + test('wraps long links without causing horizontal overflow', async ({ page, }) => { await page.setViewportSize({ width: 390, height: 844 }); + const longUrl = `https://example.com/${'a'.repeat(240)}`; const content = Array.from( { length: 80 }, (_, index) => `## Section ${index + 1}\n\nLong content for scrolling.`, @@ -86,61 +87,23 @@ test.describe('Mobile sidebar toggle', () => { loadSidebar: '_sidebar.md', }, markdown: { - homepage: `# Mobile scrolling\n\n${content}\n\nhttps://example.com/${'a'.repeat(240)}`, + homepage: `# Mobile scrolling\n\n${content}\n\n[${longUrl}](${longUrl})`, sidebar: '- [Mobile scrolling](README.md)', }, styleURLs: ['/dist/themes/core.css'], }); - const toggle = page.locator('.sidebar-toggle'); - - await expect(page.locator('.sidebar')).not.toHaveClass(/show/); - await expect(toggle).toHaveCSS('position', 'fixed'); await expect .poll(() => page.evaluate(() => document.documentElement.scrollWidth)) .toBe(page.viewportSize().width); - await page.evaluate(() => { - window.__sidebarScrollIntoViewCalls = 0; - const originalScrollIntoView = Element.prototype.scrollIntoView; - - Element.prototype.scrollIntoView = function (...args) { - if (this.closest('.sidebar')) { - window.__sidebarScrollIntoViewCalls++; - } - - return originalScrollIntoView.apply(this, args); - }; - }); - - const getToggleCenter = () => - page.evaluate(() => { - const box = document - .querySelector('.sidebar-toggle-button') - .getBoundingClientRect(); - - return box.top + box.height / 2; - }); - const viewportCenter = await page.evaluate( - () => (visualViewport?.height ?? innerHeight) / 2, - ); - expect(await getToggleCenter()).toBe(viewportCenter); - - // Simulate the sticky state changing while the page is being scrolled. - await page.evaluate(() => document.body.classList.remove('sticky')); await page.mouse.wheel(0, 1200); await expect .poll(() => page.evaluate(() => window.scrollY)) .toBeGreaterThan(0); - expect(await getToggleCenter()).toBe(viewportCenter); - expect(await page.evaluate(() => window.__sidebarScrollIntoViewCalls)).toBe( - 0, - ); - await page.mouse.wheel(0, -1200); await expect.poll(() => page.evaluate(() => window.scrollY)).toBe(0); - expect(await getToggleCenter()).toBe(viewportCenter); }); });