Skip to content

fix(frontend): preserve literal lists inside Markdown code fences - #4323

Open
Jarvis636431 wants to merge 3 commits into
Tencent:mainfrom
Jarvis636431:fix/markdown-fenced-list-enter
Open

Jarvis636431 wants to merge 3 commits into
Tencent:mainfrom
Jarvis636431:fix/markdown-fenced-list-enter

Conversation

@Jarvis636431

Copy link
Copy Markdown
Contributor

Description

Pressing Enter after - literal inside a fenced code block currently inserts another - ; an empty literal task/list marker can also be removed. Check the preceding fence state before applying list continuation, so the textarea inserts an ordinary newline inside code.

Recognize backtick and tilde fences, up to three leading spaces, matching closing delimiter types/lengths, and CRLF input. Keep list continuation after closed fences and existing Tab behavior unchanged.

Type of Change

  • 🐛 Bug fix

Related Issue

Fixes #4321

Testing

  • cd frontend && node --import tsx --test src/utils/markdownEditing.test.ts — 49 passed.
  • cd frontend && npm run type-check — passed.
  • Ran the updated test suite against the unchanged c40b33ec production module in a temporary directory: 9 regression cases fail before the fix; all pass afterward.
  • git diff --check c40b33ec...fix/markdown-fenced-list-enter — passed.
  • Full-repository Go checks were not run: this change only touches the frontend's pure editing helper and its tests. No new dependencies or documentation/API changes.

Checklist

  • Changed source follows the surrounding formatting
  • Targeted regression tests pass
  • Frontend type-check passes
  • Self-reviewed the code and verified the diff is limited to two Markdown editing files
  • Added regression coverage

Before / After

Within a fenced code block, - literal| + Enter previously produced - literal\n- |; it now produces - literal\n| through the textarea's normal Enter behavior (| denotes the caret). This is a keyboard behavior fix with no layout changes; validation uses deterministic source-level tests, not a full browser session.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-14T10:50:28.966788Z fe64599 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf2a03b344

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frontend/src/utils/markdownEditing.ts Outdated
function isInsideCodeFence(value: string, lineStart: number): boolean {
let fence = ''
for (const line of value.slice(0, lineStart).split(/\r?\n/)) {
const match = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle fences that start on list-marker lines

When a fenced block begins as the first block of a Markdown list item, the opening delimiter is on the same physical line as the list marker and this regexp ignores it, while the indented closing delimiter still matches and is recorded as a new opener. The scanner then remains "inside" a fence, so Enter stops continuing every real list that follows that valid nested code block until another matching delimiter appears; fence tracking needs to account for list-container prefixes instead of treating that closer as an opener.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe645997e0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

listIndents.push(offset)
content = line.slice(offset)
}
const match = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(content)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore fence-like lines inside raw HTML blocks

For Markdown such as <pre>\n~~~\n</pre>\n\n- next, ~~~ is literal HTML-block content, not a fenced-code opener. This match nevertheless opens a fence that </pre> cannot close, so continueListOnEnter returns null on the real list below and Enter stops continuing subsequent lists until another matching delimiter appears. Skip raw HTML blocks, including HTML comments, when tracking fences so keyboard behavior agrees with the editor's marked preview.

Useful? React with 👍 / 👎.

Comment on lines +69 to +71
while ((prefix = /^ {0,3}(?:[-*+]|\d{1,9}[.)]) {1,4}(?=\S|$)/.exec(content))) {
offset += prefix[0].length
listIndents.push(offset)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude thematic breaks from list-container tracking

For a valid document such as - - -\n ~~~\ncode\n ~~~\n- next, this loop consumes the thematic break as nested list prefixes. The top-level fence is consequently assigned fenceIndent = 2; its unindented code line incorrectly ends it, and its actual closing delimiter becomes a fresh opener. Enter on - next and subsequent lists then returns null instead of continuing the list. Recognize thematic breaks before updating list-container indentation.

Useful? React with 👍 / 👎.

let offset = listIndents.at(-1)!
let content = line.slice(offset)
let prefix: RegExpExecArray | null
while ((prefix = /^ {0,3}(?:[-*+]|\d{1,9}[.)]) {1,4}(?=\S|$)/.exec(content))) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recognize list containers opened by bare markers

With -\n ~~~\n code\n- next, the first line is a valid Markdown list-item opener, but the mandatory space after the marker makes this regex ignore it. The following fence is therefore recorded at root indentation zero rather than inside the item. Although the sibling - next ends that unclosed contained fence in Markdown, the scanner still considers it code and suppresses list continuation there. Accept an end-of-line immediately after a list marker and retain the item's normal content indentation.

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Markdown editor continues lists inside fenced code blocks

1 participant