[Bug]: deserializeMd keeps `\r` at the end of code-block lines for CRLF input, and serializeMd writes mixed line endings inside the fence
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 75/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
- Lĩnh vực
- backend
Hướng nghiên cứu
Bắt đầu tại packages/markdown/src/lib/rules/defaultRules.ts, ở quy tắc giải tuần tự hóa code_block, gần .split('\n') được đề cập trong báo cáo. So sánh đầu vào CRLF và LF trong bản tái hiện, đồng thời kiểm tra các bài kiểm thử Markdown hiện có cho khối mã. Hoàn tất khi đầu vào CRLF tạo ra cùng văn bản dòng mã và đầu ra đã tuần tự hóa như đầu vào LF, đồng thời giữ nguyên hành vi với LF.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Bug type
Behavior bug (incorrect output/state without crash)
Browser surface
No
Owner surface
Plate framework or plugin
Summary
For a fenced code block with CRLF line endings, deserializeMd keeps \r at the end of every code line except the last, and serializeMd then writes those lines with CRLF inside an LF fence.
Public reproduction URL
https://gist.github.com/venmakli/b48c1f9fe4cc9318e54515b5da0fcc74
Steps to reproduce
- Download the reproduction (
package.jsonandrepro.ts). - Run
bun install && bun repro.ts. - For the CRLF input the first
code_lineis"const a = 1;\r", and the serialized fence containsconst a = 1;\r\nbetween LF lines. The LF input gives clean lines.
Expected behavior
CRLF is a line ending (CommonMark spec, "Characters and lines"), so the CRLF input gives the same value as its LF version, which repro.ts prints next to it: code lines "const a = 1;" and "const b = 2;". Serialization gives the same output as for the LF version: ```js\nconst a = 1;\nconst b = 2;\n```\n.
Actual behavior
On @platejs/markdown 53.3.18 (output of repro.ts):
"```js\r\nconst a = 1;\r\nconst b = 2;\r\n```\r\n"
value: [{"children":[{"children":[{"text":"const a = 1;\r"}],"type":"code_line"},{"children":[{"text":"const b = 2;"}],"type":"code_line"}],"lang":"js","type":"code_block"}]
serialize: "```js\nconst a = 1;\r\nconst b = 2;\n```\n"
"```js\nconst a = 1;\nconst b = 2;\n```\n"
value: [{"children":[{"children":[{"text":"const a = 1;"}],"type":"code_line"},{"children":[{"text":"const b = 2;"}],"type":"code_line"}],"lang":"js","type":"code_block"}]
serialize: "```js\nconst a = 1;\nconst b = 2;\n```\n"
The \r is part of the code-line text in the editor value. The serialized fence mixes CRLF (inside) and LF (fence and last line).
Acceptance criteria
- For CRLF input, no
code_linetext contains\rfrom a line ending; the value equals the value for the LF version of the same input. serializeMdoutput for that value equals the output for the LF version: no\rinside the fence.- Output for LF input is unchanged.
Regression range
last-known-good: NOT_ENOUGH_INFO
first-known-bad: NOT_ENOUGH_INFO
evidence: >
Same value and output observed on @udecode/plate-markdown 47.0.4 (with @udecode/plate 46.0.10),
@platejs/markdown 53.1.5 and 53.3.18. The code_block rule splits `mdastNode.value` with `.split('\n')`
(v53.3.18 packages/markdown/src/lib/rules/defaultRules.ts:296; the same split is in the 47.0.4 dist).
git blame at v53.3.18 points to the lint commit d13624190 (PR #4732), so the split is older; the introducing commit was not identified.
Reproducibility
Always
Plate / Plite / React versions
plate: "@platejs/markdown 53.3.18, platejs 53.3.18 (mdast-util-from-markdown 2.1.0, mdast-util-to-markdown 2.2.1)"
plite: not used
plite-react: not used
react: not used
Operating system
macOS 15 (Darwin 24.6.0)
Install method
bun 1.4.4: bun install && bun repro.ts
Framework / app setup
Headless createSlateEditor with MarkdownPlugin only, no React.
Affected packages or entry points
@platejs/markdown: editor.api.markdown.deserialize / deserializeMd (code_block rule), editor.api.markdown.serialize.
Minimal code or config excerpt
import { MarkdownPlugin } from '@platejs/markdown';
import { createSlateEditor } from 'platejs';
const editor = createSlateEditor({ plugins: [MarkdownPlugin] });
for (const input of ['```js\r\nconst a = 1;\r\nconst b = 2;\r\n```\r\n', '```js\nconst a = 1;\nconst b = 2;\n```\n']) {
const value = editor.api.markdown.deserialize(input);
editor.tf.setValue(value);
console.log(JSON.stringify(input));
console.log(' value: ', JSON.stringify(value));
console.log(' serialize:', JSON.stringify(editor.api.markdown.serialize()));
}
Logs, screenshots, and evidence
# mdast from mdast-util-from-markdown 2.1.0 for the CRLF input: the code value keeps CRLF
"const a = 1;\r\nconst b = 2;"
# @udecode/plate-markdown 47.0.4 + @udecode/plate 46.0.10, CRLF input
[{"children":[{"children":[{"text":"const a = 1;\r"}],"type":"code_line"},{"children":[{"text":"const b = 2;"}],"type":"code_line"}],"lang":"js","type":"code_block"}]
"```js\nconst a = 1;\r\nconst b = 2;\n```\n"
Maintainer Codex context
route: N/A (headless)
local command: bun install && bun repro.ts
fixture/data: the two inputs in repro.ts
rule location: >
v53.3.18 and main (170d73db6, 2026-10-23): packages/markdown/src/lib/rules/defaultRules.ts:296 (code_block deserialize).
next: not checked; the code-block plugin lives in packages/platejs/src/features/code-block there.
known blocker: none
Impact and severity
- Affected:
@platejs/markdownusers who deserialize Markdown files with CRLF line endings that contain fenced code blocks. Observed on Windows-style input bytes; the OS running the code does not matter. - Severity: data risk inside code. Code text in the editor carries a hidden
\r, and the written file gets mixed line endings. - Frequency: always for CRLF input with a code block of two or more lines.
- Consequence: diffs of the Markdown file show changed code lines, and copied code keeps the stray
\r.
Additional information
Paragraph and blockquote text under CRLF is a separate report (lone \r and extra \ after PR #5026). This report is only about code-block lines. LF output between blocks (mdast-util-to-markdown always joins with \n) is not part of it.
- Ngôn ngữ chính
- TypeScript
- Star
- 16.6k
- Fork
- 993
- Merge trung bình
- 20 giờ 2 phút
- Pull request đã merge (30 ngày)
- 62
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của udecode/plate
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[Beta]: After Enter saves an edited link URL, the link toolbar stays hidden while the caret is in the linkCó thể đã có người làm @zbeyens đã nhận 4 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
udecode/plate#5314 · 1 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[Beta]: The docs Demo example page starts with an empty editorCó thể đã có người làm @natamox đã nhận 5 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
udecode/plate#5308 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của udecode/plate
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
components-web-app/docs#311 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
NEARBuilders/everything-dev#678 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 90/100
formbricks/formbricks#9881 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày