diff --git a/src/static/js/ace2_inner.ts b/src/static/js/ace2_inner.ts index 654042d6963..00f436186ae 100644 --- a/src/static/js/ace2_inner.ts +++ b/src/static/js/ace2_inner.ts @@ -2307,14 +2307,23 @@ function Ace2Inner(editorInfo, cssManagers) { let position = 1; let curLevel = level; let listType; + let prevType = ''; // loop over the lines while ((listType = getLineListType(line))) { // apply new num listType = /([a-z]+)([0-9]+)/.exec(listType); curLevel = Number(listType[2]); + const curType = listType[1]; if (isNaN(curLevel) || listType[0] === 'indent') { return line; } else if (curLevel === level) { + // Reset position when switching between list types at the same level + // (e.g., bullet -> number). See https://github.com/ether/etherpad-lite/issues/5160 + if (prevType && prevType !== curType) { + position = 1; + } + prevType = curType; + buildKeepRange(rep, builder, loc, (loc = [line, 0])); buildKeepRange(rep, builder, loc, (loc = [line, 1]), [ ['start', position], diff --git a/src/tests/frontend-new/specs/ordered_list.spec.ts b/src/tests/frontend-new/specs/ordered_list.spec.ts index 04e996e666f..ffec6fbe39b 100644 --- a/src/tests/frontend-new/specs/ordered_list.spec.ts +++ b/src/tests/frontend-new/specs/ordered_list.spec.ts @@ -54,6 +54,44 @@ test.describe('ordered_list.js', function () { }); }); + // Regression test for https://github.com/ether/etherpad-lite/issues/5160 + test('issue #5160 ordered list increments correctly after unordered list', async function ({page}) { + const padBody = await getPadBody(page); + await clearPadContent(page); + + // Create two unordered list items + const $insertUnorderedButton = page.locator('.buttonicon-insertunorderedlist'); + await $insertUnorderedButton.click({force: true}); + await writeToPad(page, 'bullet a'); + await page.keyboard.press('Enter'); + await writeToPad(page, 'bullet b'); + await page.keyboard.press('Enter'); + + // Now switch to ordered list for the next items + 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); + + // The first ordered list item (line 3) should have start=1 + const thirdLine = padBody.locator('div').nth(2); + await expect(thirdLine.locator('ol')).toHaveAttribute('start', '1', {timeout: 5000}); + + // The second ordered list item (line 4) should have start=2 + const fourthLine = padBody.locator('div').nth(3); + await expect(fourthLine.locator('ol')).toHaveAttribute('start', '2', {timeout: 5000}); + + // The third ordered list item (line 5) should have start=3 + const fifthLine = padBody.locator('div').nth(4); + await expect(fifthLine.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}) {