Make WordPress Core

Opened 33 hours ago

Last modified 15 hours ago

#66379 new defect (bug)

Classic Editor: Switching from Text to Visual mode restructures HTML lists based on cursor position

Reported by: dedri Owned by:
Priority: normal Milestone: Awaiting Review
Component: Editor Version:
Severity: normal Keywords: has-patch has-unit-tests
Cc: Focuses:

Description

Since updating to WordPress 7.1.3, I've encountered a reproducible issue with bulleted lists in the Classic Editor.

Simply placing the cursor at the end of a list item in Text mode, without making any changes to the HTML, causes WordPress to restructure the list when switching back to Visual mode.

All list items preceding the cursor position become nested inside an additional <ul>, wrapped in a new <li style="list-style-type: none;"> element.

This results in unwanted indentation and changes to otherwise valid HTML.

Steps to reproduce

1 Create a new post using Classic Editor.

2 In Visual mode, create a bulleted list containing five items: A, B, C, D and E.

3 Switch to Text mode.

4 Place the cursor at the end of the <li>D</li> line without typing or modifying anything.

5 Switch back to Visual mode.

Actual result:

Items A, B and C become indented as a nested list. The editor inserts an additional parent list item with style="list-style-type: none;" and separates the remaining items into another list.

Expected result:

The HTML and visual formatting should remain unchanged because no edits were made.

Additional observations

The point where the list splits follows the cursor position.

Switching between Text and Visual modes without repositioning the cursor does not cause the problem.

The issue is reproducible in both Chrome and Microsoft Edge.

The original HTML is valid.

The issue appeared following recent PHP and WordPress updates.

Environment

WordPress: 7.1.3

Classic Editor plugin: 1.7.0

PHP: 8.3.36

Hosting: DreamHost

Theme: Genesis child theme

Browsers tested: Chrome and Microsoft Edge

Related ticket

This behaviour appears similar to WordPress Core Trac ticket #29643, which documents unwanted nested lists and insertion of <li style="list-style-type: none;"> when switching between editing modes.

https://core.trac.wordpress.org/ticket/29643

Attachments

Three screenshots demonstrating the original list, the resulting indentation in Visual mode, and the modified HTML in Text mode.

Attachments (3)

Wordpress Text Editor 1.png​ (5.6 KB ) - added by dedri 33 hours ago.
1 List before moving cursor
Wordpress Text Editor 2.png​ (8.7 KB ) - added by dedri 33 hours ago.
2 List after moving cursor and switching views
Wordpress Text Editor 3.png​ (4.3 KB ) - added by dedri 33 hours ago.
3 Bullet Points altered by moving cursor in text view

Download all attachments as: .zip

Change History (4)

@dedri
33 hours ago

2 List after moving cursor and switching views

@dedri
33 hours ago

3 Bullet Points altered by moving cursor in text view

This ticket was mentioned in ​PR #14883 on ​WordPress/wordpress-develop by ​@sourav08.


15 hours ago
#1

  • Keywords has-patch has-unit-tests added

Description

Fixes https://core.trac.wordpress.org/ticket/66379.

Switching from Text to Visual mode in the Classic Editor with the cursor positioned immediately after a closing </li> tag causes TinyMCE to restructure the list unexpectedly.

This happens because the editor inserts a temporary selection bookmark directly inside the list, creating an invalid HTML structure. TinyMCE then normalizes the markup by nesting preceding list items inside an additional <li style="list-style-type: none;"> element, resulting in unwanted indentation and changes to the original list.

Changes

  • Adjusted both selection endpoints to ensure bookmarks positioned after </li> tags or their trailing whitespace are inserted inside the preceding list item.
  • Prevented TinyMCE from receiving invalid list structures during editor switching.
  • Preserved the original list markup and cursor selection when switching between Text and Visual modes.

Testing

  • Added regression tests covering ordered, unordered, and nested lists, whitespace variations, uppercase tags, list item attributes, and selection ranges.
  • Confirmed all 41 assertions pass with the fix, while 27 assertions fail with the original implementation.
  • Verified the behavior with WordPress's TinyMCE plugin and wpautop enabled.
  • Confirmed JavaScript lint checks pass.

Use of AI Tools

AI assistance: Yes
Tool(s): ChatGPT
Model(s): GPT-6
Used for: Assistance with investigation and implementation suggestions. Final implementation and regression tests were reviewed and verified manually.

---

This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See [https://make.wordpress.org/core/handbook/contribute/git/github-pull-requests-for-code-review/ [GitHub Pull Requests for Code Review]](​https://make.wordpress.org/core/handbook/contribute/git/github-pull-requests-for-code-review/) in the Core Handbook for more details.

Note: See TracTickets for help on using tickets.