From 4358bd73839c7ba7d0100df2a169b5a0a75733a2 Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 4 Apr 2026 08:56:52 +0100 Subject: [PATCH 1/2] fix: consecutive numbering fails after indented sub-bullets The applyNumberList() function in renumberList() checked listType[0] === 'indent' but after regex exec, listType[0] is the full match (e.g., "indent1"), never just "indent". Changed to listType[1] which is the capture group containing just the type name. This caused indent-type lines to not be recognized during renumbering, breaking the numbering sequence when numbered lists followed indented content. Fixes #5718 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/static/js/ace2_inner.ts | 2 +- .../frontend-new/specs/ordered_list.spec.ts | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/static/js/ace2_inner.ts b/src/static/js/ace2_inner.ts index 90c17988cba..714b7f50777 100644 --- a/src/static/js/ace2_inner.ts +++ b/src/static/js/ace2_inner.ts @@ -2314,7 +2314,7 @@ function Ace2Inner(editorInfo, cssManagers) { listType = /([a-z]+)([0-9]+)/.exec(listType); curLevel = Number(listType[2]); const curType = listType[1]; - if (isNaN(curLevel) || listType[0] === 'indent') { + if (isNaN(curLevel) || listType[1] === 'indent') { return line; } else if (curLevel === level) { // Reset position when switching between list types at the same level diff --git a/src/tests/frontend-new/specs/ordered_list.spec.ts b/src/tests/frontend-new/specs/ordered_list.spec.ts index ffec6fbe39b..72530698ccd 100644 --- a/src/tests/frontend-new/specs/ordered_list.spec.ts +++ b/src/tests/frontend-new/specs/ordered_list.spec.ts @@ -92,6 +92,48 @@ test.describe('ordered_list.js', function () { await expect(fifthLine.locator('ol')).toHaveAttribute('start', '3', {timeout: 5000}); }); + // Regression test for https://github.com/ether/etherpad-lite/issues/5718 + test('issue #5718 consecutive numbering works after indented sub-bullets', async function ({page}) { + const padBody = await getPadBody(page); + await clearPadContent(page); + + // Create a bullet point + const $insertUnorderedButton = page.locator('.buttonicon-insertunorderedlist'); + await $insertUnorderedButton.click({force: true}); + await writeToPad(page, 'Bullet item'); + await page.keyboard.press('Enter'); + + // Indent to create a sub-bullet + await page.keyboard.press('Tab'); + await writeToPad(page, 'Sub-bullet'); + await page.keyboard.press('Enter'); + + // De-indent back to level 1 + await page.keyboard.press('Shift+Tab'); + + // Switch to numbered list + const $insertOrderedButton = page.locator('.buttonicon-insertorderedlist'); + await $insertOrderedButton.click({force: true}); + await writeToPad(page, 'Number 1'); + await page.keyboard.press('Enter'); + await writeToPad(page, 'Number 2'); + await page.keyboard.press('Enter'); + await writeToPad(page, 'Number 3'); + + // Wait for renumbering + await page.waitForTimeout(500); + + // Lines 3, 4, 5 should be numbered 1, 2, 3 + const line3 = padBody.locator('div').nth(2); + await expect(line3.locator('ol')).toHaveAttribute('start', '1', {timeout: 5000}); + + const line4 = padBody.locator('div').nth(3); + await expect(line4.locator('ol')).toHaveAttribute('start', '2', {timeout: 5000}); + + const line5 = padBody.locator('div').nth(4); + await expect(line5.locator('ol')).toHaveAttribute('start', '3', {timeout: 5000}); + }); + test.describe('Pressing Tab in an OL increases and decreases indentation', function () { test('indent and de-indent list item with keypress', async function ({page}) { From 726813f80be41d4dd519d0c1d6c320fbed6da6cd Mon Sep 17 00:00:00 2001 From: John McLear Date: Sat, 4 Apr 2026 09:14:44 +0100 Subject: [PATCH 2/2] test: assert sub-bullet indent and remove redundant waitForTimeout - Assert .list-bullet2 exists after Tab to verify indent precondition - Remove waitForTimeout(500) since toHaveAttribute already waits 5s Co-Authored-By: Claude Opus 4.6 (1M context) --- src/tests/frontend-new/specs/ordered_list.spec.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tests/frontend-new/specs/ordered_list.spec.ts b/src/tests/frontend-new/specs/ordered_list.spec.ts index 72530698ccd..0584acb1a34 100644 --- a/src/tests/frontend-new/specs/ordered_list.spec.ts +++ b/src/tests/frontend-new/specs/ordered_list.spec.ts @@ -106,6 +106,11 @@ test.describe('ordered_list.js', function () { // Indent to create a sub-bullet await page.keyboard.press('Tab'); await writeToPad(page, 'Sub-bullet'); + + // Verify the sub-bullet is actually indented (level 2) + const subBulletLine = padBody.locator('div').nth(1); + await expect(subBulletLine.locator('.list-bullet2')).toHaveCount(1, {timeout: 5000}); + await page.keyboard.press('Enter'); // De-indent back to level 1 @@ -120,9 +125,6 @@ test.describe('ordered_list.js', function () { await page.keyboard.press('Enter'); await writeToPad(page, 'Number 3'); - // Wait for renumbering - await page.waitForTimeout(500); - // Lines 3, 4, 5 should be numbered 1, 2, 3 const line3 = padBody.locator('div').nth(2); await expect(line3.locator('ol')).toHaveAttribute('start', '1', {timeout: 5000});