refactor(md/parse): parse HTML into one single node#10848
Conversation
✅ Organic activityNo automation signals detected in the analyzed events. This is an automated analysis by AgentScan |
|
Parser conformance results onjs/262
jsx/babel
markdown/commonmark
symbols/microsoft
ts/babel
ts/microsoft
|
Merging this PR will improve performance by 18.13%
Performance Changes
Tip Curious why this is faster? Comment Comparing Footnotes
|
WalkthroughThis PR adds Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/biome_markdown_parser/src/syntax/html_block.rs (1)
337-347: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winStop on container-prefixed blank lines.
For type 6/7 blocks inside quotes/lists, a blank continuation line looks like
NEWLINE + prefix + NEWLINE. Afterskip_container_prefixes(p), the parser can be sitting on that blank line’sNEWLINE, but the loop continues and absorbs following content into the HTML block.Suggested fix
if at_container_boundary(p) { break; } skip_container_prefixes(p); + if p.at(NEWLINE) { + break; + } continue;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_markdown_parser/src/syntax/html_block.rs` around lines 337 - 347, The HTML block continuation logic in html_block should stop when a blank continuation line is encountered after container prefixes, not keep consuming the next line. In the loop around at_container_boundary and skip_container_prefixes, detect the pattern where a NEWLINE is followed by a container prefix and then another NEWLINE, and break before continuing so the parser does not absorb following content into the block. Use the existing helpers at_container_boundary(p), skip_container_prefixes(p), and the html block parsing loop in the relevant block type handling to place the early exit in the right spot.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/biome_markdown_parser/src/syntax/html_block.rs`:
- Around line 301-313: The HTML block tokenization in html_block.rs is currently
including container prefixes in MD_HTML_LITERAL, which causes raw quote/list
markers to be treated as HTML content. Update the html block parsing path around
p.lookahead, p.re_lex_html_content, and the MD_HTML_CONTENT/MD_HTML_LITERAL
construction so container prefixes remain separate CST nodes or are stripped
before storing the raw literal. Make sure MdHtmlContent.value_token() only
returns actual HTML source, not leading container prefix text.
- Around line 305-308: The lookahead in html_block parsing is mutating parser
state through advance_until_terminator/advance_until_blank_line, which can leak
virtual_line_start changes past the checkpoint. Update the logic around the
p.lookahead call in html_block.rs to keep the measuring pass side-effect free by
saving and restoring the relevant parser state (especially
state.virtual_line_start), or refactor the container-prefix scan used by
skip_container_prefixes to be pure.
---
Outside diff comments:
In `@crates/biome_markdown_parser/src/syntax/html_block.rs`:
- Around line 337-347: The HTML block continuation logic in html_block should
stop when a blank continuation line is encountered after container prefixes, not
keep consuming the next line. In the loop around at_container_boundary and
skip_container_prefixes, detect the pattern where a NEWLINE is followed by a
container prefix and then another NEWLINE, and break before continuing so the
parser does not absorb following content into the block. Use the existing
helpers at_container_boundary(p), skip_container_prefixes(p), and the html block
parsing loop in the relevant block type handling to place the early exit in the
right spot.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 73075030-b646-4d0f-8b7e-71a84a86a880
⛔ Files ignored due to path filters (15)
crates/biome_markdown_factory/src/generated/node_factory.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_factory/src/generated/syntax_factory.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/code/additional-space.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/list/issue-17652.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/markdown/test-case.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-223.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-278.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-281.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_parser/tests/md_test_suite/ok/html_block.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_parser/tests/md_test_suite/ok/html_block_in_list.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_parser/tests/md_test_suite/ok/html_block_in_list_continuation.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_syntax/src/generated/kind.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_syntax/src/generated/macros.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_syntax/src/generated/nodes.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_syntax/src/generated/nodes_mut.rsis excluded by!**/generated/**,!**/generated/**and included by**
📒 Files selected for processing (14)
crates/biome_markdown_formatter/src/bullet_list.rscrates/biome_markdown_formatter/src/generated.rscrates/biome_markdown_formatter/src/markdown/auxiliary/html_content.rscrates/biome_markdown_formatter/src/markdown/auxiliary/mod.rscrates/biome_markdown_formatter/src/markdown/auxiliary/newline.rscrates/biome_markdown_formatter/src/markdown/lists/block_list.rscrates/biome_markdown_parser/src/lexer/mod.rscrates/biome_markdown_parser/src/parser.rscrates/biome_markdown_parser/src/syntax/html_block.rscrates/biome_markdown_parser/src/to_html.rscrates/biome_markdown_parser/src/token_source.rscrates/biome_markdown_syntax/src/block_ext.rsxtask/codegen/markdown.ungramxtask/codegen/src/markdown_kinds_src.rs
6cffc5f to
b80ff6c
Compare
b80ff6c to
5819bde
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/biome_markdown_formatter/src/markdown/lists/block_list.rs (2)
460-486: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDuplicate lookahead helpers.
next_content_block_is_thematic_breakandnext_content_block_is_link_reference_definitionare identical except for the final predicate. Consider merging into one generic helper taking a predicate closure.♻️ Suggested consolidation
-fn next_content_block_is_thematic_break( - block_list: &MdBlockList, - start: usize, - content_count: usize, -) -> bool { - block_list - .iter() - .enumerate() - .skip(start) - .take_while(|(index, _)| *index < content_count) - .find(|(_, block)| !block.is_newline()) - .is_some_and(|(_, block)| block.is_thematic_break()) -} - -fn next_content_block_is_link_reference_definition( - block_list: &MdBlockList, - start: usize, - content_count: usize, -) -> bool { - block_list - .iter() - .enumerate() - .skip(start) - .take_while(|(index, _)| *index < content_count) - .find(|(_, block)| !block.is_newline()) - .is_some_and(|(_, block)| block.is_link_reference_definition()) -} +fn next_content_block_matches( + block_list: &MdBlockList, + start: usize, + content_count: usize, + predicate: impl Fn(&AnyMdBlock) -> bool, +) -> bool { + block_list + .iter() + .enumerate() + .skip(start) + .take_while(|(index, _)| *index < content_count) + .find(|(_, block)| !block.is_newline()) + .is_some_and(|(_, block)| predicate(&block)) +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_markdown_formatter/src/markdown/lists/block_list.rs` around lines 460 - 486, The two lookahead helpers in block_list are duplicated except for the final predicate, so consolidate them into a single reusable helper that accepts a predicate closure. Refactor next_content_block_is_thematic_break and next_content_block_is_link_reference_definition to delegate to the shared helper, keeping the existing iteration logic over MdBlockList and preserving their current behavior.
279-296: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRepeated "collect and remove extra newlines" loop.
The pattern of pushing the current newline with
print_mode: Removethen draining subsequent newline siblings the same way is duplicated between the link-reference-definition branch and the thematic-break branch. A small helper (e.g.drain_extra_newlines(&mut iter, &mut joiner, content_count)) would remove the repetition.Also applies to: 301-318
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_markdown_formatter/src/markdown/lists/block_list.rs` around lines 279 - 296, The newline-collection logic in the block list formatter is duplicated across the link-reference-definition and thematic-break branches in `block_list.rs`. Extract the repeated “emit current newline with TextPrintMode::Remove, then drain consecutive MdNewline siblings while tracking content_count” sequence into a small helper such as `drain_extra_newlines`, and reuse it from the relevant match branches to keep `iter`, `joiner`, and `content_count` handling consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@crates/biome_markdown_formatter/src/markdown/lists/block_list.rs`:
- Around line 460-486: The two lookahead helpers in block_list are duplicated
except for the final predicate, so consolidate them into a single reusable
helper that accepts a predicate closure. Refactor
next_content_block_is_thematic_break and
next_content_block_is_link_reference_definition to delegate to the shared
helper, keeping the existing iteration logic over MdBlockList and preserving
their current behavior.
- Around line 279-296: The newline-collection logic in the block list formatter
is duplicated across the link-reference-definition and thematic-break branches
in `block_list.rs`. Extract the repeated “emit current newline with
TextPrintMode::Remove, then drain consecutive MdNewline siblings while tracking
content_count” sequence into a small helper such as `drain_extra_newlines`, and
reuse it from the relevant match branches to keep `iter`, `joiner`, and
`content_count` handling consistent.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 68fbb845-4870-4760-8b4c-682fed1eceb8
⛔ Files ignored due to path filters (15)
crates/biome_markdown_factory/src/generated/node_factory.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_factory/src/generated/syntax_factory.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/code/additional-space.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/list/issue-17652.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/markdown/test-case.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-223.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-278.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-281.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_parser/tests/md_test_suite/ok/html_block.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_parser/tests/md_test_suite/ok/html_block_in_list.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_parser/tests/md_test_suite/ok/html_block_in_list_continuation.md.snapis excluded by!**/*.snapand included by**crates/biome_markdown_syntax/src/generated/kind.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_syntax/src/generated/macros.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_syntax/src/generated/nodes.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_markdown_syntax/src/generated/nodes_mut.rsis excluded by!**/generated/**,!**/generated/**and included by**
📒 Files selected for processing (15)
crates/biome_markdown_formatter/src/bullet_list.rscrates/biome_markdown_formatter/src/generated.rscrates/biome_markdown_formatter/src/markdown/auxiliary/html_content.rscrates/biome_markdown_formatter/src/markdown/auxiliary/mod.rscrates/biome_markdown_formatter/src/markdown/auxiliary/newline.rscrates/biome_markdown_formatter/src/markdown/lists/block_list.rscrates/biome_markdown_formatter/src/shared.rscrates/biome_markdown_parser/src/lexer/mod.rscrates/biome_markdown_parser/src/parser.rscrates/biome_markdown_parser/src/syntax/html_block.rscrates/biome_markdown_parser/src/to_html.rscrates/biome_markdown_parser/src/token_source.rscrates/biome_markdown_syntax/src/block_ext.rsxtask/codegen/markdown.ungramxtask/codegen/src/markdown_kinds_src.rs
🚧 Files skipped from review as they are similar to previous changes (13)
- xtask/codegen/markdown.ungram
- xtask/codegen/src/markdown_kinds_src.rs
- crates/biome_markdown_formatter/src/markdown/auxiliary/mod.rs
- crates/biome_markdown_syntax/src/block_ext.rs
- crates/biome_markdown_parser/src/parser.rs
- crates/biome_markdown_formatter/src/markdown/auxiliary/html_content.rs
- crates/biome_markdown_formatter/src/markdown/auxiliary/newline.rs
- crates/biome_markdown_formatter/src/generated.rs
- crates/biome_markdown_formatter/src/bullet_list.rs
- crates/biome_markdown_parser/src/to_html.rs
- crates/biome_markdown_parser/src/token_source.rs
- crates/biome_markdown_parser/src/lexer/mod.rs
- crates/biome_markdown_parser/src/syntax/html_block.rs
Summary
Implemented with a coding agent.
The HTML was being parsed as normal markdown text. This is incorrect because it prevents us from enabling embedding.
This PR changes its parsing by storing all content inside one single literal token. That's what we do in the HTML parser, so it's a solution that works for us.
It required some tuning. I left comments where it required an explanation.
Test Plan
Updated tests
Docs
N/A