diff --git a/crates/biome_markdown_factory/src/generated/node_factory.rs b/crates/biome_markdown_factory/src/generated/node_factory.rs index df5cc3ea0525..d4a7776fa04b 100644 --- a/crates/biome_markdown_factory/src/generated/node_factory.rs +++ b/crates/biome_markdown_factory/src/generated/node_factory.rs @@ -70,17 +70,21 @@ pub fn md_entity_reference(value_token: SyntaxToken) -> MdEntityReference { )) } pub fn md_fenced_code_block( + indent: MdIndentTokenList, l_fence_token: SyntaxToken, code_list: MdCodeNameList, content: MdInlineItemList, + r_fence_indent: MdIndentTokenList, r_fence_token: SyntaxToken, ) -> MdFencedCodeBlock { MdFencedCodeBlock::unwrap_cast(SyntaxNode::new_detached( MarkdownSyntaxKind::MD_FENCED_CODE_BLOCK, [ + Some(SyntaxElement::Node(indent.into_syntax())), Some(SyntaxElement::Token(l_fence_token)), Some(SyntaxElement::Node(code_list.into_syntax())), Some(SyntaxElement::Node(content.into_syntax())), + Some(SyntaxElement::Node(r_fence_indent.into_syntax())), Some(SyntaxElement::Token(r_fence_token)), ], )) @@ -97,14 +101,20 @@ pub fn md_hash(hash_token: SyntaxToken) -> MdHash { [Some(SyntaxElement::Token(hash_token))], )) } -pub fn md_header(before: MdHashList, after: MdHashList) -> MdHeaderBuilder { +pub fn md_header( + indent: MdIndentTokenList, + before: MdHashList, + after: MdHashList, +) -> MdHeaderBuilder { MdHeaderBuilder { + indent, before, after, content: None, } } pub struct MdHeaderBuilder { + indent: MdIndentTokenList, before: MdHashList, after: MdHashList, content: Option, @@ -118,6 +128,7 @@ impl MdHeaderBuilder { MdHeader::unwrap_cast(SyntaxNode::new_detached( MarkdownSyntaxKind::MD_HEADER, [ + Some(SyntaxElement::Node(self.indent.into_syntax())), Some(SyntaxElement::Node(self.before.into_syntax())), self.content .map(|token| SyntaxElement::Node(token.into_syntax())), @@ -126,10 +137,13 @@ impl MdHeaderBuilder { )) } } -pub fn md_html_block(content: MdInlineItemList) -> MdHtmlBlock { +pub fn md_html_block(indent: MdIndentTokenList, content: MdInlineItemList) -> MdHtmlBlock { MdHtmlBlock::unwrap_cast(SyntaxNode::new_detached( MarkdownSyntaxKind::MD_HTML_BLOCK, - [Some(SyntaxElement::Node(content.into_syntax()))], + [ + Some(SyntaxElement::Node(indent.into_syntax())), + Some(SyntaxElement::Node(content.into_syntax())), + ], )) } pub fn md_indent(value_token: SyntaxToken) -> MdIndent { @@ -340,6 +354,7 @@ pub fn md_link_label(content: MdInlineItemList) -> MdLinkLabel { )) } pub fn md_link_reference_definition( + indent: MdIndentTokenList, l_brack_token: SyntaxToken, label: MdLinkLabel, r_brack_token: SyntaxToken, @@ -347,6 +362,7 @@ pub fn md_link_reference_definition( destination: MdLinkDestination, ) -> MdLinkReferenceDefinitionBuilder { MdLinkReferenceDefinitionBuilder { + indent, l_brack_token, label, r_brack_token, @@ -356,6 +372,7 @@ pub fn md_link_reference_definition( } } pub struct MdLinkReferenceDefinitionBuilder { + indent: MdIndentTokenList, l_brack_token: SyntaxToken, label: MdLinkLabel, r_brack_token: SyntaxToken, @@ -372,6 +389,7 @@ impl MdLinkReferenceDefinitionBuilder { MdLinkReferenceDefinition::unwrap_cast(SyntaxNode::new_detached( MarkdownSyntaxKind::MD_LINK_REFERENCE_DEFINITION, [ + Some(SyntaxElement::Node(self.indent.into_syntax())), Some(SyntaxElement::Token(self.l_brack_token)), Some(SyntaxElement::Node(self.label.into_syntax())), Some(SyntaxElement::Token(self.r_brack_token)), diff --git a/crates/biome_markdown_factory/src/generated/syntax_factory.rs b/crates/biome_markdown_factory/src/generated/syntax_factory.rs index b71f352884e5..95671fdc7eff 100644 --- a/crates/biome_markdown_factory/src/generated/syntax_factory.rs +++ b/crates/biome_markdown_factory/src/generated/syntax_factory.rs @@ -147,8 +147,15 @@ impl SyntaxFactory for MarkdownSyntaxFactory { } MD_FENCED_CODE_BLOCK => { let mut elements = (&children).into_iter(); - let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); + let mut slots: RawNodeSlots<6usize> = RawNodeSlots::default(); let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && MdIndentTokenList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); if let Some(element) = ¤t_element && matches!(element.kind(), T!["```"] | T ! [~~~]) { @@ -170,6 +177,13 @@ impl SyntaxFactory for MarkdownSyntaxFactory { current_element = elements.next(); } slots.next_slot(); + if let Some(element) = ¤t_element + && MdIndentTokenList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); if let Some(element) = ¤t_element && matches!(element.kind(), T!["```"] | T ! [~~~]) { @@ -222,8 +236,15 @@ impl SyntaxFactory for MarkdownSyntaxFactory { } MD_HEADER => { let mut elements = (&children).into_iter(); - let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); + let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && MdIndentTokenList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); if let Some(element) = ¤t_element && MdHashList::can_cast(element.kind()) { @@ -255,8 +276,15 @@ impl SyntaxFactory for MarkdownSyntaxFactory { } MD_HTML_BLOCK => { let mut elements = (&children).into_iter(); - let mut slots: RawNodeSlots<1usize> = RawNodeSlots::default(); + let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && MdIndentTokenList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); if let Some(element) = ¤t_element && MdInlineItemList::can_cast(element.kind()) { @@ -649,8 +677,15 @@ impl SyntaxFactory for MarkdownSyntaxFactory { } MD_LINK_REFERENCE_DEFINITION => { let mut elements = (&children).into_iter(); - let mut slots: RawNodeSlots<6usize> = RawNodeSlots::default(); + let mut slots: RawNodeSlots<7usize> = RawNodeSlots::default(); let mut current_element = elements.next(); + if let Some(element) = ¤t_element + && MdIndentTokenList::can_cast(element.kind()) + { + slots.mark_present(); + current_element = elements.next(); + } + slots.next_slot(); if let Some(element) = ¤t_element && element.kind() == T!['['] { diff --git a/crates/biome_markdown_formatter/src/markdown/auxiliary/header.rs b/crates/biome_markdown_formatter/src/markdown/auxiliary/header.rs index 6fd3f8421096..5871988e1d34 100644 --- a/crates/biome_markdown_formatter/src/markdown/auxiliary/header.rs +++ b/crates/biome_markdown_formatter/src/markdown/auxiliary/header.rs @@ -1,5 +1,6 @@ use crate::markdown::auxiliary::paragraph::FormatMdParagraphOptions; use crate::prelude::*; +use crate::verbatim::format_verbatim_node; use biome_formatter::write; use biome_markdown_syntax::{MdHeader, MdHeaderFields}; @@ -8,11 +9,14 @@ pub(crate) struct FormatMdHeader; impl FormatNodeRule for FormatMdHeader { fn fmt_fields(&self, node: &MdHeader, f: &mut MarkdownFormatter) -> FormatResult<()> { let MdHeaderFields { + indent, before, content, after, } = node.as_fields(); + write!(f, [format_verbatim_node(indent.syntax())])?; + write!(f, [before.format()])?; if let Some(content) = content { diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/footnoteDefinition/long.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/footnoteDefinition/long.md.snap index 665740c515f9..57b69c149b54 100644 --- a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/footnoteDefinition/long.md.snap +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/footnoteDefinition/long.md.snap @@ -25,7 +25,7 @@ info: markdown/footnoteDefinition/long.md - this is a long long long long long long long long long long long long long paragraph. - this is a long long long long long long long long long long long long long paragraph. +[^world]: this is a long long long long long long long long long long long long long paragraph. -+this is a long long long long long long long long long long long long long paragraph. ++ this is a long long long long long long long long long long long long long paragraph. ``` # Output @@ -33,12 +33,12 @@ info: markdown/footnoteDefinition/long.md ```md [^hello]: this is a long long long long long long long long long long long long long paragraph. [^world]: this is a long long long long long long long long long long long long long paragraph. -this is a long long long long long long long long long long long long long paragraph. + this is a long long long long long long long long long long long long long paragraph. ``` # Lines exceeding max width of 80 characters ``` 1: [^hello]: this is a long long long long long long long long long long long long long paragraph. 2: [^world]: this is a long long long long long long long long long long long long long paragraph. - 3: this is a long long long long long long long long long long long long long paragraph. + 3: this is a long long long long long long long long long long long long long paragraph. ``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/math/remark-math.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/math/remark-math.md.snap index 46cba992886c..4ec6e6da315c 100644 --- a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/math/remark-math.md.snap +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/math/remark-math.md.snap @@ -123,8 +123,8 @@ code fence - \alpha -$$ + $$$ -+\alpha -+$$$ ++ \alpha ++ $$$ --- @@ -214,8 +214,8 @@ $$ --- $$$ -\alpha -$$$ + \alpha + $$$ --- diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-17.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-17.md.snap index 6a059a4b5ad8..0427b04984cf 100644 --- a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-17.md.snap +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-17.md.snap @@ -20,12 +20,12 @@ Foo @@ -1,2 +1,2 @@ Foo -\*\*\* -+*** ++ *** ``` # Output ```md Foo -*** + *** ``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-182.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-182.md.snap index 626a67fade5a..90a1fdf03928 100644 --- a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-182.md.snap +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-182.md.snap @@ -19,13 +19,14 @@ info: markdown/spec/example-182.md +++ Biome @@ -1,2 +1,2 @@ -aaa +-bbb + aaa - bbb ++ bbb ``` # Output ```md aaa -bbb + bbb ``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-183.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-183.md.snap new file mode 100644 index 000000000000..4c82074daf96 --- /dev/null +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-183.md.snap @@ -0,0 +1,35 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: markdown/spec/example-183.md +--- + +# Input + +```md +aaa + bbb + ccc + +``` + + +# Prettier differences + +```diff +--- Prettier ++++ Biome +@@ -1,3 +1,3 @@ + aaa +-bbb +-ccc ++ bbb ++ ccc +``` + +# Output + +```md +aaa + bbb + ccc +``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-37.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-37.md.snap index 6e9b921af6b2..69f054a3d148 100644 --- a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-37.md.snap +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-37.md.snap @@ -19,17 +19,20 @@ info: markdown/spec/example-37.md --- Prettier +++ Biome @@ -1,5 +1,3 @@ - ### foo +-### foo - - ## foo +-## foo - - # foo +-# foo ++ ### foo ++ ## foo ++ # foo ``` # Output ```md -### foo -## foo -# foo + ### foo + ## foo + # foo ``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-39.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-39.md.snap index 57531a172edb..d386f77a4753 100644 --- a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-39.md.snap +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-39.md.snap @@ -20,12 +20,12 @@ foo @@ -1 +1,2 @@ -foo # bar +foo -+# bar ++ # bar ``` # Output ```md foo -# bar + # bar ``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-40.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-40.md.snap index a82bc9b00bdb..694e4e3a1b30 100644 --- a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-40.md.snap +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-40.md.snap @@ -20,12 +20,13 @@ info: markdown/spec/example-40.md @@ -1,3 +1,2 @@ ## foo - - ### bar +-### bar ++ ### bar ``` # Output ```md ## foo -### bar + ### bar ``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-55.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-55.md.snap new file mode 100644 index 000000000000..8de580516bac --- /dev/null +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-55.md.snap @@ -0,0 +1,31 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: markdown/spec/example-55.md +--- + +# Input + +```md +Foo + --- + +``` + + +# Prettier differences + +```diff +--- Prettier ++++ Biome +@@ -1,2 +1,2 @@ + Foo +---- ++ --- +``` + +# Output + +```md +Foo + --- +``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-613.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-613.md.snap index a6f1331e1611..d0d05252e601 100644 --- a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-613.md.snap +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-613.md.snap @@ -19,13 +19,14 @@ foo +++ Biome @@ -1,2 +1,2 @@ -foo +-baz +foo - baz ++ baz ``` # Output ```md foo -baz + baz ``` diff --git a/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-81.md.snap b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-81.md.snap new file mode 100644 index 000000000000..f0496a511182 --- /dev/null +++ b/crates/biome_markdown_formatter/tests/specs/prettier/markdown/spec/example-81.md.snap @@ -0,0 +1,31 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: markdown/spec/example-81.md +--- + +# Input + +```md +Foo + bar + +``` + + +# Prettier differences + +```diff +--- Prettier ++++ Biome +@@ -1,2 +1,2 @@ + Foo +-bar ++ bar +``` + +# Output + +```md +Foo + bar +``` diff --git a/crates/biome_markdown_parser/src/parser.rs b/crates/biome_markdown_parser/src/parser.rs index 040ba7efa812..9d90991803ae 100644 --- a/crates/biome_markdown_parser/src/parser.rs +++ b/crates/biome_markdown_parser/src/parser.rs @@ -312,6 +312,68 @@ impl<'source> MarkdownParser<'source> { self.state.virtual_line_start = Some(self.cur_range().start()); } + /// Emit an MdIndentTokenList for optional block prefix indentation at line start. + /// + /// Like `skip_line_indent()` but emits real CST nodes (`MdIndentToken` / + /// `MdIndentTokenList`) instead of skipped trivia. Use this for non-lookahead, + /// non-error-recovery paths where the indent tokens should be visible in the tree. + pub fn emit_line_indent(&mut self, max_indent: usize) -> bool { + if !self.at_line_start() { + let list_m = self.start(); + list_m.complete(self, MarkdownSyntaxKind::MD_INDENT_TOKEN_LIST); + return false; + } + + let list_m = self.start(); + let did_emit = self.emit_indent_tokens_core(max_indent); + list_m.complete(self, MarkdownSyntaxKind::MD_INDENT_TOKEN_LIST); + did_emit + } + + /// Emit individual `MdIndentToken` nodes (no list wrapper) for indentation. + /// + /// Use this inside inline item lists or content lists where `MdIndentToken` + /// is already a valid child (via `AnyMdInline`). Unlike `emit_line_indent()`, + /// this does NOT wrap tokens in an `MdIndentTokenList`. + pub fn emit_indent_tokens(&mut self, max_indent: usize) -> bool { + if !self.at_line_start() { + return false; + } + + self.emit_indent_tokens_core(max_indent) + } + + /// Shared core loop: emit `MdIndentToken` nodes for whitespace-only tokens + /// up to `max_indent` columns. + fn emit_indent_tokens_core(&mut self, max_indent: usize) -> bool { + let mut consumed = 0usize; + let mut did_emit = false; + + while self.at(MarkdownSyntaxKind::MD_TEXTUAL_LITERAL) { + let text = self.cur_text(); + if text.is_empty() || !text.chars().all(|c| c == ' ' || c == '\t') { + break; + } + + let indent = text + .chars() + .map(|c| if c == '\t' { TAB_STOP_SPACES } else { 1 }) + .sum::(); + + if consumed + indent > max_indent { + break; + } + + consumed += indent; + did_emit = true; + let token_m = self.start(); + self.bump_remap(MarkdownSyntaxKind::MD_INDENT_CHAR); + token_m.complete(self, MarkdownSyntaxKind::MD_INDENT_TOKEN); + } + + did_emit + } + /// Skip an optional indentation token at line start if it is whitespace-only /// and does not exceed `max_indent` columns. pub fn skip_line_indent(&mut self, max_indent: usize) -> bool { diff --git a/crates/biome_markdown_parser/src/syntax/fenced_code_block.rs b/crates/biome_markdown_parser/src/syntax/fenced_code_block.rs index 6cedce534bfc..e36ee79f2b99 100644 --- a/crates/biome_markdown_parser/src/syntax/fenced_code_block.rs +++ b/crates/biome_markdown_parser/src/syntax/fenced_code_block.rs @@ -175,9 +175,11 @@ pub(crate) fn at_fenced_code_block(p: &mut MarkdownParser) -> bool { /// /// Grammar: /// MdFencedCodeBlock = +/// indent: MdIndentTokenList /// l_fence: ('```' | '~~~') /// code_list: MdCodeNameList /// content: MdInlineItemList +/// r_fence_indent: MdIndentTokenList /// r_fence: ('```' | '~~~') pub(crate) fn parse_fenced_code_block(p: &mut MarkdownParser) -> ParsedSyntax { parse_fenced_code_block_impl(p, false) @@ -200,7 +202,7 @@ fn parse_fenced_code_block_impl(p: &mut MarkdownParser, force: bool) -> ParsedSy { fence_indent += p.state().list_item_required_indent; } - p.skip_line_indent(MAX_BLOCK_PREFIX_INDENT); + p.emit_line_indent(MAX_BLOCK_PREFIX_INDENT); // Detect fence type and length (must close with same type and >= length per CommonMark §4.5) let text = p.cur_text(); @@ -225,14 +227,21 @@ fn parse_fenced_code_block_impl(p: &mut MarkdownParser, force: bool) -> ParsedSy let has_closing = at_closing_fence(p, is_tilde_fence, fence_len); if has_closing { - if p.state().list_item_required_indent > 0 && p.at_line_start() { - p.skip_line_indent(p.state().list_item_required_indent); - } - p.skip_line_indent(MAX_BLOCK_PREFIX_INDENT); + // Closing fence indent: in a list context, strip up to list_item_required_indent; + // otherwise strip up to MAX_BLOCK_PREFIX_INDENT (0-3 spaces). + let max = if p.state().list_item_required_indent > 0 { + p.state().list_item_required_indent + } else { + MAX_BLOCK_PREFIX_INDENT + }; + p.emit_line_indent(max); bump_fence(p, is_tilde_fence); } else { // Emit diagnostic for unterminated code block p.error(unterminated_fenced_code(p, opening_range, fence_type)); + // Emit empty r_fence_indent list to satisfy grammar slot + let empty_m = p.start(); + empty_m.complete(p, MD_INDENT_TOKEN_LIST); } Present(m.complete(p, MD_FENCED_CODE_BLOCK)) @@ -388,7 +397,7 @@ fn consume_quote_prefixes_in_code_content(p: &mut MarkdownParser, quote_depth: u let prev_virtual = p.state().virtual_line_start; p.state_mut().virtual_line_start = Some(p.cur_range().start()); - p.skip_line_indent(MAX_BLOCK_PREFIX_INDENT); + p.emit_indent_tokens(MAX_BLOCK_PREFIX_INDENT); p.state_mut().virtual_line_start = prev_virtual; for _ in 0..quote_depth { diff --git a/crates/biome_markdown_parser/src/syntax/header.rs b/crates/biome_markdown_parser/src/syntax/header.rs index bd67595fcefa..16326ed9139b 100644 --- a/crates/biome_markdown_parser/src/syntax/header.rs +++ b/crates/biome_markdown_parser/src/syntax/header.rs @@ -52,7 +52,7 @@ pub(crate) fn at_header(p: &mut MarkdownParser) -> bool { /// Parse an ATX header. /// -/// Grammar: MdHeader = before: MdHashList content: MdParagraph? after: MdHashList +/// Grammar: MdHeader = indent: MdIndentTokenList before: MdHashList content: MdParagraph? after: MdHashList /// /// ATX headers start with 1-6 `#` characters followed by space or end of line. /// More than 6 `#` characters is not a valid header. @@ -80,7 +80,7 @@ pub(crate) fn parse_header(p: &mut MarkdownParser) -> ParsedSyntax { let m = p.start(); - p.skip_line_indent(MAX_BLOCK_PREFIX_INDENT); + p.emit_line_indent(MAX_BLOCK_PREFIX_INDENT); // Parse opening hashes (MdHashList containing MdHash nodes) parse_hash_list(p); diff --git a/crates/biome_markdown_parser/src/syntax/html_block.rs b/crates/biome_markdown_parser/src/syntax/html_block.rs index 2791fdfd5239..26a95e00730c 100644 --- a/crates/biome_markdown_parser/src/syntax/html_block.rs +++ b/crates/biome_markdown_parser/src/syntax/html_block.rs @@ -272,17 +272,19 @@ pub(crate) fn at_html_block_interrupt(p: &mut MarkdownParser) -> bool { /// Parse HTML block as raw text until blank line. pub(crate) fn parse_html_block(p: &mut MarkdownParser) -> ParsedSyntax { - p.skip_line_indent(MAX_BLOCK_PREFIX_INDENT); + let m = p.start(); + p.emit_line_indent(MAX_BLOCK_PREFIX_INDENT); if !p.at(L_ANGLE) { + m.abandon(p); return Absent; } let Some(kind) = html_block_kind(p) else { + m.abandon(p); return Absent; }; - let m = p.start(); let content_m = p.start(); match kind { @@ -397,7 +399,7 @@ fn skip_container_prefixes(p: &mut MarkdownParser) { let required_indent = p.state().list_item_required_indent; if required_indent > 0 { - p.skip_line_indent(required_indent); + p.emit_indent_tokens(required_indent); p.state_mut().virtual_line_start = Some(p.cur_range().start()); } } diff --git a/crates/biome_markdown_parser/src/syntax/link_block.rs b/crates/biome_markdown_parser/src/syntax/link_block.rs index b46990f8ce11..00bd7b36b398 100644 --- a/crates/biome_markdown_parser/src/syntax/link_block.rs +++ b/crates/biome_markdown_parser/src/syntax/link_block.rs @@ -396,7 +396,7 @@ pub(crate) fn parse_link_block(p: &mut MarkdownParser) -> ParsedSyntax { let m = p.start(); - p.skip_line_indent(MAX_BLOCK_PREFIX_INDENT); + p.emit_line_indent(MAX_BLOCK_PREFIX_INDENT); // [ - opening bracket p.expect(L_BRACK); diff --git a/crates/biome_markdown_parser/src/syntax/list.rs b/crates/biome_markdown_parser/src/syntax/list.rs index 40da4b9f22c5..0c97dabbf811 100644 --- a/crates/biome_markdown_parser/src/syntax/list.rs +++ b/crates/biome_markdown_parser/src/syntax/list.rs @@ -50,7 +50,7 @@ use crate::syntax::parse_any_block_with_indent_code_policy; use crate::syntax::parse_error::list_nesting_too_deep; use crate::syntax::quote::{ at_quote_indented_code_start, consume_quote_prefix, consume_quote_prefix_without_virtual, - has_quote_prefix, parse_quote, parse_quote_block_list, skip_optional_marker_space, + emit_optional_marker_space, has_quote_prefix, parse_quote, parse_quote_block_list, }; use crate::syntax::thematic_break_block::parse_thematic_break_block; use crate::syntax::with_virtual_line_start; @@ -1832,11 +1832,17 @@ fn parse_first_line_blockquote(p: &mut MarkdownParser, state: &mut ListItemLoopS let parsed = if p.at(MD_TEXTUAL_LITERAL) && p.cur_text() == ">" { let quote_m = p.start(); + + // Wrap `>` and optional space in a proper MdQuotePrefix node + let prefix_m = p.start(); + let indent_m = p.start(); + indent_m.complete(p, MD_QUOTE_INDENT_LIST); p.bump_remap(T![>]); p.state_mut().block_quote_depth += 1; let has_indented_code = at_quote_indented_code_start(p); - let marker_space = skip_optional_marker_space(p, has_indented_code); + let marker_space = emit_optional_marker_space(p, has_indented_code); + prefix_m.complete(p, MD_QUOTE_PREFIX); p.set_virtual_line_start(); parse_quote_block_list(p); @@ -1900,6 +1906,8 @@ fn check_continuation_indent( allow_indent_code_block && indent >= state.required_indent + INDENT_CODE_BLOCK_SPACES; if !is_indent_code_block { // Sufficient indentation - skip it and continue + // (emitting indent tokens here is not possible because MdIndentToken + // is not a valid child of MdBlockList — leave as trivia) p.skip_line_indent(state.required_indent); let prev_virtual = p.state().virtual_line_start; p.state_mut().virtual_line_start = Some(p.cur_range().start()); diff --git a/crates/biome_markdown_parser/src/syntax/mod.rs b/crates/biome_markdown_parser/src/syntax/mod.rs index 251f159a1de0..773e7580ef89 100644 --- a/crates/biome_markdown_parser/src/syntax/mod.rs +++ b/crates/biome_markdown_parser/src/syntax/mod.rs @@ -539,7 +539,9 @@ fn consume_indent_prefix(p: &mut MarkdownParser, indent: usize) { break; } - p.parse_as_skipped_trivia_tokens(|p| p.bump(MD_TEXTUAL_LITERAL)); + let token_m = p.start(); + p.bump_remap(MD_INDENT_CHAR); + token_m.complete(p, MD_INDENT_TOKEN); } } @@ -899,8 +901,8 @@ fn handle_inline_newline(p: &mut MarkdownParser, has_content: bool) -> InlineNew if has_content && p.state().list_item_required_indent == 0 && allow_setext_heading(p) { let is_setext = p.lookahead(|p| at_setext_underline_after_newline(p).is_some()); if is_setext { - // Skip the indent so parse_paragraph sees the underline - p.skip_line_indent(INDENT_CODE_BLOCK_SPACES); + // Emit the indent so parse_paragraph sees the underline + p.emit_indent_tokens(INDENT_CODE_BLOCK_SPACES); return InlineNewlineAction::Break; } } @@ -921,8 +923,8 @@ fn handle_inline_newline(p: &mut MarkdownParser, has_content: bool) -> InlineNew || (p.at(MD_THEMATIC_BREAK_LITERAL) && is_dash_only_thematic_break(p)) }); if is_setext && has_content { - // Skip the indent so parse_paragraph sees the underline - p.skip_line_indent(required_indent); + // Emit the indent so parse_paragraph sees the underline + p.emit_indent_tokens(required_indent); return InlineNewlineAction::Break; } } @@ -965,17 +967,17 @@ fn handle_inline_newline(p: &mut MarkdownParser, has_content: bool) -> InlineNew if required_indent > 0 { let indent = p.line_start_leading_indent(); if indent >= required_indent { - // Sufficient indentation - skip it - p.skip_line_indent(required_indent); + // Sufficient indentation - emit it as real nodes + p.emit_indent_tokens(required_indent); } - // else: Lazy continuation - don't break, don't skip indent. + // else: Lazy continuation - don't break, don't emit indent. // The at_block_interrupt check above handles real interruptions. // Content continues at its actual position. } // For plain paragraphs, strip up to 4 leading spaces on continuation lines. if required_indent == 0 { - p.skip_line_indent(INDENT_CODE_BLOCK_SPACES); + p.emit_indent_tokens(INDENT_CODE_BLOCK_SPACES); } InlineNewlineAction::Continue @@ -1297,13 +1299,25 @@ fn line_starts_with_fence(p: &mut MarkdownParser) -> bool { fn consume_partial_quote_prefix(p: &mut MarkdownParser, depth: usize) -> bool { let mut consumed = 0usize; while consumed < depth && p.at(R_ANGLE) { - p.parse_as_skipped_trivia_tokens(|p| p.bump(R_ANGLE)); + // Emit as MdQuotePrefix (same structure as Phase 1 full quote prefixes) + let prefix_m = p.start(); + + // Empty pre-marker indent list + let indent_list_m = p.start(); + indent_list_m.complete(p, MD_QUOTE_INDENT_LIST); + + // The `>` marker + p.bump(R_ANGLE); + + // Optional post-marker space if p.at(MD_TEXTUAL_LITERAL) { let text = p.cur_text(); if text == " " || text == "\t" { - p.parse_as_skipped_trivia_tokens(|p| p.bump(MD_TEXTUAL_LITERAL)); + p.bump_remap(MD_QUOTE_POST_MARKER_SPACE); } } + + prefix_m.complete(p, MD_QUOTE_PREFIX); consumed += 1; } consumed > 0 diff --git a/crates/biome_markdown_parser/src/syntax/quote.rs b/crates/biome_markdown_parser/src/syntax/quote.rs index b7c270307807..7a9f9ff54b3c 100644 --- a/crates/biome_markdown_parser/src/syntax/quote.rs +++ b/crates/biome_markdown_parser/src/syntax/quote.rs @@ -574,6 +574,26 @@ pub(crate) fn skip_optional_marker_space(p: &mut MarkdownParser, preserve_tab: b false } +/// Emit the optional space/tab after a `>` quote marker as an explicit CST node. +pub(crate) fn emit_optional_marker_space(p: &mut MarkdownParser, preserve_tab: bool) -> bool { + if !p.at(MD_TEXTUAL_LITERAL) { + return false; + } + + let text = p.cur_text(); + if text == " " { + p.bump_remap(MD_QUOTE_POST_MARKER_SPACE); + return true; + } + if text == "\t" { + if !preserve_tab { + p.bump_remap(MD_QUOTE_POST_MARKER_SPACE); + } + return true; + } + false +} + pub(crate) fn has_quote_prefix(p: &mut MarkdownParser, depth: usize) -> bool { if depth == 0 { return false; diff --git a/crates/biome_markdown_parser/src/syntax/thematic_break_block.rs b/crates/biome_markdown_parser/src/syntax/thematic_break_block.rs index 978491f508b4..89d3bce075d7 100644 --- a/crates/biome_markdown_parser/src/syntax/thematic_break_block.rs +++ b/crates/biome_markdown_parser/src/syntax/thematic_break_block.rs @@ -157,9 +157,6 @@ pub(crate) fn parse_thematic_break_block(p: &mut MarkdownParser) -> ParsedSyntax } let m = p.start(); - // skip_line_indent unchanged — deferred to Phase 5 - p.skip_line_indent(MAX_BLOCK_PREFIX_INDENT); - parse_thematic_break_parts(p); Present(m.complete(p, MD_THEMATIC_BREAK_BLOCK)) @@ -175,6 +172,10 @@ pub(crate) fn parse_thematic_break_block(p: &mut MarkdownParser) -> ParsedSyntax fn parse_thematic_break_parts(p: &mut MarkdownParser) { let list_m = p.start(); + // Emit block prefix indent (0-3 spaces) as MdIndentToken nodes inside the + // parts list. MdIndentToken is a valid AnyMdThematicBreakPart variant. + p.emit_indent_tokens(MAX_BLOCK_PREFIX_INDENT); + // If lexer produced a single literal, decompose it via re-lex. // Track this so all subsequent bumps use parts-mode context. // Mutable: fallback MD_TEXTUAL_LITERAL tokens also trigger re-lex (see below). diff --git a/crates/biome_markdown_parser/src/to_html.rs b/crates/biome_markdown_parser/src/to_html.rs index 10aa9d72994d..a82099d1130f 100644 --- a/crates/biome_markdown_parser/src/to_html.rs +++ b/crates/biome_markdown_parser/src/to_html.rs @@ -59,6 +59,34 @@ use crate::parser::{ListItemIndent, ListTightness, QuoteIndent}; use crate::syntax::reference::normalize_reference_label; use crate::syntax::{INDENT_CODE_BLOCK_SPACES, MAX_BLOCK_PREFIX_INDENT, TAB_STOP_SPACES}; +/// Compute the column width of an `MdIndentTokenList`. +fn indent_list_width(list: &biome_markdown_syntax::MdIndentTokenList) -> usize { + let mut width = 0usize; + for c in indent_list_text(list).chars() { + match c { + ' ' => width += 1, + '\t' => width += TAB_STOP_SPACES - (width % TAB_STOP_SPACES), + _ => {} + } + } + width +} + +/// Collect the raw text of an `MdIndentTokenList`. +fn indent_list_text(list: &biome_markdown_syntax::MdIndentTokenList) -> String { + let mut text = String::new(); + for token in list.iter() { + for tok in token + .syntax() + .descendants_with_tokens(Direction::Next) + .filter_map(|el| el.into_token()) + { + text.push_str(tok.text()); + } + } + text +} + // ============================================================================ // Line Handling Utilities // ============================================================================ @@ -1147,24 +1175,8 @@ fn render_fenced_code_block( ) { out.push_str("
 indent += 1,
-                    '\t' => indent += TAB_STOP_SPACES - (indent % TAB_STOP_SPACES),
-                    '\n' | '\r' => indent = 0, // Reset at newlines
-                    _ => {}
-                }
-            }
-        }
-        indent
-    });
+    // Determine the fence indentation from the explicit indent slot
+    let fence_leading_indent = indent_list_width(&code.indent());
     let container_indent = list_indent + quote_indent;
     let fence_indent = fence_leading_indent
         .saturating_sub(container_indent)
@@ -1275,7 +1287,9 @@ fn render_html_block(
     list_indent: usize,
     quote_indent: usize,
 ) {
-    let mut content = collect_raw_inline_text(&html.content());
+    // Prepend the block prefix indent (now in explicit slot, not trivia)
+    let mut content = indent_list_text(&html.indent());
+    content.push_str(&collect_raw_inline_text(&html.content()));
     if list_indent > 0 {
         content = strip_indent_preserve_tabs(&content, list_indent);
     }
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/error/fenced_code_blockquote_eof_after_prefix.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/error/fenced_code_blockquote_eof_after_prefix.md.snap
index 588569e8f135..fce9c1d7904e 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/error/fenced_code_blockquote_eof_after_prefix.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/error/fenced_code_blockquote_eof_after_prefix.md.snap
@@ -25,6 +25,7 @@ MdDocument {
             },
             content: MdBlockList [
                 MdFencedCodeBlock {
+                    indent: MdIndentTokenList [],
                     l_fence: TRIPLE_BACKTICK@2..5 "```" [] [],
                     code_list: MdCodeNameList [],
                     content: MdInlineItemList [
@@ -37,6 +38,7 @@ MdDocument {
                             post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@7..8 " " [] [],
                         },
                     ],
+                    r_fence_indent: MdIndentTokenList [],
                     r_fence: missing (required),
                 },
             ],
@@ -59,16 +61,18 @@ MdDocument {
         2: MD_QUOTE_POST_MARKER_SPACE@1..2 " " [] []
       1: MD_BLOCK_LIST@2..8
         0: MD_FENCED_CODE_BLOCK@2..8
-          0: TRIPLE_BACKTICK@2..5 "```" [] []
-          1: MD_CODE_NAME_LIST@5..5
-          2: MD_INLINE_ITEM_LIST@5..8
+          0: MD_INDENT_TOKEN_LIST@2..2
+          1: TRIPLE_BACKTICK@2..5 "```" [] []
+          2: MD_CODE_NAME_LIST@5..5
+          3: MD_INLINE_ITEM_LIST@5..8
             0: MD_TEXTUAL@5..6
               0: MD_TEXTUAL_LITERAL@5..6 "\n" [] []
             1: MD_QUOTE_PREFIX@6..8
               0: MD_QUOTE_INDENT_LIST@6..6
               1: R_ANGLE@6..7 ">" [] []
               2: MD_QUOTE_POST_MARKER_SPACE@7..8 " " [] []
-          3: (empty)
+          4: MD_INDENT_TOKEN_LIST@8..8
+          5: (empty)
   2: EOF@8..8 "" [] []
 
 ```
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/error/unterminated_code_fence.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/error/unterminated_code_fence.md.snap
index 89a7c3bf6d4c..17ed5edeba98 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/error/unterminated_code_fence.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/error/unterminated_code_fence.md.snap
@@ -21,6 +21,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@0..3 "```" [] [],
             code_list: MdCodeNameList [
                 MdTextual {
@@ -86,6 +87,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@44..45 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: missing (required),
         },
     ],
@@ -100,11 +102,12 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..45
     0: MD_FENCED_CODE_BLOCK@0..45
-      0: TRIPLE_BACKTICK@0..3 "```" [] []
-      1: MD_CODE_NAME_LIST@3..7
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: TRIPLE_BACKTICK@0..3 "```" [] []
+      2: MD_CODE_NAME_LIST@3..7
         0: MD_TEXTUAL@3..7
           0: MD_TEXTUAL_LITERAL@3..7 "rust" [] []
-      2: MD_INLINE_ITEM_LIST@7..45
+      3: MD_INLINE_ITEM_LIST@7..45
         0: MD_TEXTUAL@7..8
           0: MD_TEXTUAL_LITERAL@7..8 "\n" [] []
         1: MD_TEXTUAL@8..15
@@ -143,7 +146,8 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@43..44 "}" [] []
         18: MD_TEXTUAL@44..45
           0: MD_TEXTUAL_LITERAL@44..45 "\n" [] []
-      3: (empty)
+      4: MD_INDENT_TOKEN_LIST@45..45
+      5: (empty)
   2: EOF@45..45 "" [] []
 
 ```
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/atx_heading_trailing_hash.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/atx_heading_trailing_hash.md.snap
index 864437546029..ff18318f06eb 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/atx_heading_trailing_hash.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/atx_heading_trailing_hash.md.snap
@@ -21,6 +21,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@0..1 "#" [] [],
@@ -43,6 +44,7 @@ MdDocument {
             value_token: NEWLINE@6..7 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@7..8 "#" [] [],
@@ -66,6 +68,7 @@ MdDocument {
             value_token: NEWLINE@14..15 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@15..16 "#" [] [],
@@ -114,43 +117,46 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..32
     0: MD_HEADER@0..6
-      0: MD_HASH_LIST@0..1
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: MD_HASH_LIST@0..1
         0: MD_HASH@0..1
           0: HASH@0..1 "#" [] []
-      1: MD_PARAGRAPH@1..6
+      2: MD_PARAGRAPH@1..6
         0: MD_INLINE_ITEM_LIST@1..6
           0: MD_TEXTUAL@1..5
             0: MD_TEXTUAL_LITERAL@1..5 " foo" [] []
           1: MD_TEXTUAL@5..6
             0: MD_TEXTUAL_LITERAL@5..6 "#" [] []
         1: (empty)
-      2: MD_HASH_LIST@6..6
+      3: MD_HASH_LIST@6..6
     1: MD_NEWLINE@6..7
       0: NEWLINE@6..7 "\n" [] []
     2: MD_HEADER@7..14
-      0: MD_HASH_LIST@7..8
+      0: MD_INDENT_TOKEN_LIST@7..7
+      1: MD_HASH_LIST@7..8
         0: MD_HASH@7..8
           0: HASH@7..8 "#" [] []
-      1: MD_PARAGRAPH@8..12
+      2: MD_PARAGRAPH@8..12
         0: MD_INLINE_ITEM_LIST@8..12
           0: MD_TEXTUAL@8..12
             0: MD_TEXTUAL_LITERAL@8..12 " foo" [] []
         1: (empty)
-      2: MD_HASH_LIST@12..14
+      3: MD_HASH_LIST@12..14
         0: MD_HASH@12..14
           0: HASH@12..14 "#" [Skipped(" ")] []
     3: MD_NEWLINE@14..15
       0: NEWLINE@14..15 "\n" [] []
     4: MD_HEADER@15..26
-      0: MD_HASH_LIST@15..16
+      0: MD_INDENT_TOKEN_LIST@15..15
+      1: MD_HASH_LIST@15..16
         0: MD_HASH@15..16
           0: HASH@15..16 "#" [] []
-      1: MD_PARAGRAPH@16..22
+      2: MD_PARAGRAPH@16..22
         0: MD_INLINE_ITEM_LIST@16..22
           0: MD_TEXTUAL@16..22
             0: MD_TEXTUAL_LITERAL@16..22 "   foo" [] []
         1: (empty)
-      2: MD_HASH_LIST@22..26
+      3: MD_HASH_LIST@22..26
         0: MD_HASH@22..26
           0: HASH@22..26 "#" [Skipped(" "), Skipped(" "), Skipped(" ")] []
     5: MD_NEWLINE@26..27
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/edge_cases.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/edge_cases.md.snap
index cde8ba7c6e29..0d5fc352b5c7 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/edge_cases.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/edge_cases.md.snap
@@ -128,8 +128,20 @@ MdDocument {
         },
         MdIndentCodeBlock {
             content: MdInlineItemList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@102..103 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@103..104 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@104..105 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@105..106 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@102..107 "*" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@106..107 "*" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@107..116 "code with" [] [],
@@ -146,8 +158,20 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@133..134 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@134..135 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@135..136 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@136..137 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@137..138 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@134..148 "more code " [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@138..148 "more code " [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@148..150 "**" [] [],
@@ -170,6 +194,7 @@ MdDocument {
             value_token: NEWLINE@161..162 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@162..163 "#" [] [],
@@ -192,6 +217,7 @@ MdDocument {
             value_token: NEWLINE@196..197 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@197..199 "##" [] [],
@@ -221,8 +247,20 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@240..241 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@241..242 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@242..243 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@243..244 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@244..245 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@241..246 "#" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@245..246 "#" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@246..267 " not heading due to 4" [] [],
@@ -236,8 +274,20 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@275..276 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@276..277 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@277..278 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@278..279 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@279..280 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@276..281 "-" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@280..281 "-" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@281..299 " not list due to 4" [] [],
@@ -251,8 +301,20 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@307..308 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@308..309 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@309..310 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@310..311 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@311..312 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@308..313 ">" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@312..313 ">" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@313..332 " not quote due to 4" [] [],
@@ -290,9 +352,20 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdHeader {
+            indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@378..379 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@379..380 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@380..381 " " [] [],
+                },
+            ],
             before: MdHashList [
                 MdHash {
-                    hash_token: HASH@378..382 "#" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    hash_token: HASH@381..382 "#" [] [],
                 },
             ],
             content: MdParagraph {
@@ -328,8 +401,20 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@442..443 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@443..444 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@444..445 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@445..446 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@446..447 " " [] [],
+                },
                 MdInlineCode {
-                    l_tick_token: BACKTICK@443..450 "```" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    l_tick_token: BACKTICK@447..450 "```" [] [],
                     content: MdInlineItemList [
                         MdTextual {
                             value_token: MD_TEXTUAL_LITERAL@450..451 "\n" [] [],
@@ -423,56 +508,74 @@ MdDocument {
       0: NEWLINE@101..102 "\n" [] []
     8: MD_INDENT_CODE_BLOCK@102..161
       0: MD_INLINE_ITEM_LIST@102..161
-        0: MD_TEXTUAL@102..107
-          0: MD_TEXTUAL_LITERAL@102..107 "*" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        1: MD_TEXTUAL@107..116
+        0: MD_INDENT_TOKEN@102..103
+          0: MD_INDENT_CHAR@102..103 " " [] []
+        1: MD_INDENT_TOKEN@103..104
+          0: MD_INDENT_CHAR@103..104 " " [] []
+        2: MD_INDENT_TOKEN@104..105
+          0: MD_INDENT_CHAR@104..105 " " [] []
+        3: MD_INDENT_TOKEN@105..106
+          0: MD_INDENT_CHAR@105..106 " " [] []
+        4: MD_TEXTUAL@106..107
+          0: MD_TEXTUAL_LITERAL@106..107 "*" [] []
+        5: MD_TEXTUAL@107..116
           0: MD_TEXTUAL_LITERAL@107..116 "code with" [] []
-        2: MD_TEXTUAL@116..117
+        6: MD_TEXTUAL@116..117
           0: MD_TEXTUAL_LITERAL@116..117 "*" [] []
-        3: MD_TEXTUAL@117..132
+        7: MD_TEXTUAL@117..132
           0: MD_TEXTUAL_LITERAL@117..132 " inline markers" [] []
-        4: MD_TEXTUAL@132..133
+        8: MD_TEXTUAL@132..133
           0: MD_TEXTUAL_LITERAL@132..133 "\n" [] []
-        5: MD_TEXTUAL@133..134
+        9: MD_TEXTUAL@133..134
           0: MD_TEXTUAL_LITERAL@133..134 "\n" [] []
-        6: MD_TEXTUAL@134..148
-          0: MD_TEXTUAL_LITERAL@134..148 "more code " [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        7: MD_TEXTUAL@148..150
+        10: MD_INDENT_TOKEN@134..135
+          0: MD_INDENT_CHAR@134..135 " " [] []
+        11: MD_INDENT_TOKEN@135..136
+          0: MD_INDENT_CHAR@135..136 " " [] []
+        12: MD_INDENT_TOKEN@136..137
+          0: MD_INDENT_CHAR@136..137 " " [] []
+        13: MD_INDENT_TOKEN@137..138
+          0: MD_INDENT_CHAR@137..138 " " [] []
+        14: MD_TEXTUAL@138..148
+          0: MD_TEXTUAL_LITERAL@138..148 "more code " [] []
+        15: MD_TEXTUAL@148..150
           0: MD_TEXTUAL_LITERAL@148..150 "**" [] []
-        8: MD_TEXTUAL@150..154
+        16: MD_TEXTUAL@150..154
           0: MD_TEXTUAL_LITERAL@150..154 "here" [] []
-        9: MD_TEXTUAL@154..156
+        17: MD_TEXTUAL@154..156
           0: MD_TEXTUAL_LITERAL@154..156 "**" [] []
-        10: MD_TEXTUAL@156..160
+        18: MD_TEXTUAL@156..160
           0: MD_TEXTUAL_LITERAL@156..160 " too" [] []
-        11: MD_TEXTUAL@160..161
+        19: MD_TEXTUAL@160..161
           0: MD_TEXTUAL_LITERAL@160..161 "\n" [] []
     9: MD_NEWLINE@161..162
       0: NEWLINE@161..162 "\n" [] []
     10: MD_HEADER@162..195
-      0: MD_HASH_LIST@162..163
+      0: MD_INDENT_TOKEN_LIST@162..162
+      1: MD_HASH_LIST@162..163
         0: MD_HASH@162..163
           0: HASH@162..163 "#" [] []
-      1: MD_PARAGRAPH@163..195
+      2: MD_PARAGRAPH@163..195
         0: MD_INLINE_ITEM_LIST@163..195
           0: MD_TEXTUAL@163..195
             0: MD_TEXTUAL_LITERAL@163..195 "\tTab after hash is valid heading" [] []
         1: (empty)
-      2: MD_HASH_LIST@195..195
+      3: MD_HASH_LIST@195..195
     11: MD_NEWLINE@195..196
       0: NEWLINE@195..196 "\n" [] []
     12: MD_NEWLINE@196..197
       0: NEWLINE@196..197 "\n" [] []
     13: MD_HEADER@197..224
-      0: MD_HASH_LIST@197..199
+      0: MD_INDENT_TOKEN_LIST@197..197
+      1: MD_HASH_LIST@197..199
         0: MD_HASH@197..199
           0: HASH@197..199 "##" [] []
-      1: MD_PARAGRAPH@199..224
+      2: MD_PARAGRAPH@199..224
         0: MD_INLINE_ITEM_LIST@199..224
           0: MD_TEXTUAL@199..224
             0: MD_TEXTUAL_LITERAL@199..224 "\tMultiple hashes with tab" [] []
         1: (empty)
-      2: MD_HASH_LIST@224..224
+      3: MD_HASH_LIST@224..224
     14: MD_NEWLINE@224..225
       0: NEWLINE@224..225 "\n" [] []
     15: MD_NEWLINE@225..226
@@ -483,39 +586,63 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@226..240 "Paragraph here" [] []
         1: MD_TEXTUAL@240..241
           0: MD_TEXTUAL_LITERAL@240..241 "\n" [] []
-        2: MD_TEXTUAL@241..246
-          0: MD_TEXTUAL_LITERAL@241..246 "#" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        3: MD_TEXTUAL@246..267
+        2: MD_INDENT_TOKEN@241..242
+          0: MD_INDENT_CHAR@241..242 " " [] []
+        3: MD_INDENT_TOKEN@242..243
+          0: MD_INDENT_CHAR@242..243 " " [] []
+        4: MD_INDENT_TOKEN@243..244
+          0: MD_INDENT_CHAR@243..244 " " [] []
+        5: MD_INDENT_TOKEN@244..245
+          0: MD_INDENT_CHAR@244..245 " " [] []
+        6: MD_TEXTUAL@245..246
+          0: MD_TEXTUAL_LITERAL@245..246 "#" [] []
+        7: MD_TEXTUAL@246..267
           0: MD_TEXTUAL_LITERAL@246..267 " not heading due to 4" [] []
-        4: MD_TEXTUAL@267..268
+        8: MD_TEXTUAL@267..268
           0: MD_TEXTUAL_LITERAL@267..268 "+" [] []
-        5: MD_TEXTUAL@268..275
+        9: MD_TEXTUAL@268..275
           0: MD_TEXTUAL_LITERAL@268..275 " spaces" [] []
-        6: MD_TEXTUAL@275..276
+        10: MD_TEXTUAL@275..276
           0: MD_TEXTUAL_LITERAL@275..276 "\n" [] []
-        7: MD_TEXTUAL@276..281
-          0: MD_TEXTUAL_LITERAL@276..281 "-" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        8: MD_TEXTUAL@281..299
+        11: MD_INDENT_TOKEN@276..277
+          0: MD_INDENT_CHAR@276..277 " " [] []
+        12: MD_INDENT_TOKEN@277..278
+          0: MD_INDENT_CHAR@277..278 " " [] []
+        13: MD_INDENT_TOKEN@278..279
+          0: MD_INDENT_CHAR@278..279 " " [] []
+        14: MD_INDENT_TOKEN@279..280
+          0: MD_INDENT_CHAR@279..280 " " [] []
+        15: MD_TEXTUAL@280..281
+          0: MD_TEXTUAL_LITERAL@280..281 "-" [] []
+        16: MD_TEXTUAL@281..299
           0: MD_TEXTUAL_LITERAL@281..299 " not list due to 4" [] []
-        9: MD_TEXTUAL@299..300
+        17: MD_TEXTUAL@299..300
           0: MD_TEXTUAL_LITERAL@299..300 "+" [] []
-        10: MD_TEXTUAL@300..307
+        18: MD_TEXTUAL@300..307
           0: MD_TEXTUAL_LITERAL@300..307 " spaces" [] []
-        11: MD_TEXTUAL@307..308
+        19: MD_TEXTUAL@307..308
           0: MD_TEXTUAL_LITERAL@307..308 "\n" [] []
-        12: MD_TEXTUAL@308..313
-          0: MD_TEXTUAL_LITERAL@308..313 ">" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        13: MD_TEXTUAL@313..332
+        20: MD_INDENT_TOKEN@308..309
+          0: MD_INDENT_CHAR@308..309 " " [] []
+        21: MD_INDENT_TOKEN@309..310
+          0: MD_INDENT_CHAR@309..310 " " [] []
+        22: MD_INDENT_TOKEN@310..311
+          0: MD_INDENT_CHAR@310..311 " " [] []
+        23: MD_INDENT_TOKEN@311..312
+          0: MD_INDENT_CHAR@311..312 " " [] []
+        24: MD_TEXTUAL@312..313
+          0: MD_TEXTUAL_LITERAL@312..313 ">" [] []
+        25: MD_TEXTUAL@313..332
           0: MD_TEXTUAL_LITERAL@313..332 " not quote due to 4" [] []
-        14: MD_TEXTUAL@332..333
+        26: MD_TEXTUAL@332..333
           0: MD_TEXTUAL_LITERAL@332..333 "+" [] []
-        15: MD_TEXTUAL@333..340
+        27: MD_TEXTUAL@333..340
           0: MD_TEXTUAL_LITERAL@333..340 " spaces" [] []
-        16: MD_TEXTUAL@340..341
+        28: MD_TEXTUAL@340..341
           0: MD_TEXTUAL_LITERAL@340..341 "\n" [] []
-        17: MD_TEXTUAL@341..363
+        29: MD_TEXTUAL@341..363
           0: MD_TEXTUAL_LITERAL@341..363 "continues as paragraph" [] []
-        18: MD_TEXTUAL@363..364
+        30: MD_TEXTUAL@363..364
           0: MD_TEXTUAL_LITERAL@363..364 "\n" [] []
       1: (empty)
     17: MD_NEWLINE@364..365
@@ -528,10 +655,17 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@377..378 "\n" [] []
       1: (empty)
     19: MD_HEADER@378..416
-      0: MD_HASH_LIST@378..382
-        0: MD_HASH@378..382
-          0: HASH@378..382 "#" [Skipped(" "), Skipped(" "), Skipped(" ")] []
-      1: MD_PARAGRAPH@382..416
+      0: MD_INDENT_TOKEN_LIST@378..381
+        0: MD_INDENT_TOKEN@378..379
+          0: MD_INDENT_CHAR@378..379 " " [] []
+        1: MD_INDENT_TOKEN@379..380
+          0: MD_INDENT_CHAR@379..380 " " [] []
+        2: MD_INDENT_TOKEN@380..381
+          0: MD_INDENT_CHAR@380..381 " " [] []
+      1: MD_HASH_LIST@381..382
+        0: MD_HASH@381..382
+          0: HASH@381..382 "#" [] []
+      2: MD_PARAGRAPH@382..416
         0: MD_INLINE_ITEM_LIST@382..416
           0: MD_TEXTUAL@382..401
             0: MD_TEXTUAL_LITERAL@382..401 " this IS a heading " [] []
@@ -542,7 +676,7 @@ MdDocument {
           3: MD_TEXTUAL@415..416
             0: MD_TEXTUAL_LITERAL@415..416 ")" [] []
         1: (empty)
-      2: MD_HASH_LIST@416..416
+      3: MD_HASH_LIST@416..416
     20: MD_NEWLINE@416..417
       0: NEWLINE@416..417 "\n" [] []
     21: MD_NEWLINE@417..418
@@ -553,8 +687,16 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@418..442 "Para with indented fence" [] []
         1: MD_TEXTUAL@442..443
           0: MD_TEXTUAL_LITERAL@442..443 "\n" [] []
-        2: MD_INLINE_CODE@443..479
-          0: BACKTICK@443..450 "```" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
+        2: MD_INDENT_TOKEN@443..444
+          0: MD_INDENT_CHAR@443..444 " " [] []
+        3: MD_INDENT_TOKEN@444..445
+          0: MD_INDENT_CHAR@444..445 " " [] []
+        4: MD_INDENT_TOKEN@445..446
+          0: MD_INDENT_CHAR@445..446 " " [] []
+        5: MD_INDENT_TOKEN@446..447
+          0: MD_INDENT_CHAR@446..447 " " [] []
+        6: MD_INLINE_CODE@447..479
+          0: BACKTICK@447..450 "```" [] []
           1: MD_INLINE_ITEM_LIST@450..476
             0: MD_TEXTUAL@450..451
               0: MD_TEXTUAL_LITERAL@450..451 "\n" [] []
@@ -565,11 +707,11 @@ MdDocument {
             3: MD_TEXTUAL@472..476
               0: MD_TEXTUAL_LITERAL@472..476 "    " [] []
           2: BACKTICK@476..479 "```" [] []
-        3: MD_TEXTUAL@479..480
+        7: MD_TEXTUAL@479..480
           0: MD_TEXTUAL_LITERAL@479..480 "\n" [] []
-        4: MD_TEXTUAL@480..504
+        8: MD_TEXTUAL@480..504
           0: MD_TEXTUAL_LITERAL@480..504 "still the same paragraph" [] []
-        5: MD_TEXTUAL@504..505
+        9: MD_TEXTUAL@504..505
           0: MD_TEXTUAL_LITERAL@504..505 "\n" [] []
       1: (empty)
   2: EOF@505..505 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/emphasis_edge_cases.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/emphasis_edge_cases.md.snap
index 86f83db91dd9..4c94f08c2586 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/emphasis_edge_cases.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/emphasis_edge_cases.md.snap
@@ -342,6 +342,7 @@ MdDocument {
             value_token: NEWLINE@358..359 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@359..360 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -580,20 +581,21 @@ MdDocument {
     15: MD_NEWLINE@358..359
       0: NEWLINE@358..359 "\n" [] []
     16: MD_LINK_REFERENCE_DEFINITION@359..387
-      0: L_BRACK@359..360 "[" [] []
-      1: MD_LINK_LABEL@360..365
+      0: MD_INDENT_TOKEN_LIST@359..359
+      1: L_BRACK@359..360 "[" [] []
+      2: MD_LINK_LABEL@360..365
         0: MD_INLINE_ITEM_LIST@360..365
           0: MD_TEXTUAL@360..365
             0: MD_TEXTUAL_LITERAL@360..365 "label" [] []
-      2: R_BRACK@365..366 "]" [] []
-      3: COLON@366..367 ":" [] []
-      4: MD_LINK_DESTINATION@367..387
+      3: R_BRACK@365..366 "]" [] []
+      4: COLON@366..367 ":" [] []
+      5: MD_LINK_DESTINATION@367..387
         0: MD_INLINE_ITEM_LIST@367..387
           0: MD_TEXTUAL@367..368
             0: MD_TEXTUAL_LITERAL@367..368 " " [] []
           1: MD_TEXTUAL@368..387
             0: MD_TEXTUAL_LITERAL@368..387 "https://example.com" [] []
-      5: (empty)
+      6: (empty)
     17: MD_NEWLINE@387..388
       0: NEWLINE@387..388 "\n" [] []
   2: EOF@388..388 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_advanced.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_advanced.md.snap
index 9c18231d6139..59c2e72210a0 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_advanced.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_advanced.md.snap
@@ -78,6 +78,7 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@21..24 "```" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -91,6 +92,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@29..30 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@30..33 "```" [] [],
         },
         MdNewline {
@@ -123,6 +125,7 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@63..68 "`````" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -142,6 +145,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@89..90 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@90..95 "`````" [] [],
         },
         MdNewline {
@@ -162,6 +166,7 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_TILDE@105..108 "~~~" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -175,6 +180,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@113..114 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_TILDE@114..117 "~~~" [] [],
         },
         MdNewline {
@@ -207,6 +213,7 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@145..148 "```" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -232,6 +239,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@168..169 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@169..172 "```" [] [],
         },
         MdNewline {
@@ -264,6 +272,7 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@200..203 "```" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -277,7 +286,18 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@208..209 "\n" [] [],
                 },
             ],
-            r_fence: TRIPLE_BACKTICK@209..215 "```" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+            r_fence_indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@209..210 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@210..211 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@211..212 " " [] [],
+                },
+            ],
+            r_fence: TRIPLE_BACKTICK@212..215 "```" [] [],
         },
         MdNewline {
             value_token: NEWLINE@215..216 "\n" [] [],
@@ -315,6 +335,7 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@263..267 "````" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -340,6 +361,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@287..288 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@288..292 "````" [] [],
         },
         MdNewline {
@@ -372,7 +394,15 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdFencedCodeBlock {
-            l_fence: TRIPLE_BACKTICK@336..341 "```" [Skipped(" "), Skipped(" ")] [],
+            indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@336..337 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@337..338 " " [] [],
+                },
+            ],
+            l_fence: TRIPLE_BACKTICK@338..341 "```" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
                 MdTextual {
@@ -391,7 +421,15 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@353..354 "\n" [] [],
                 },
             ],
-            r_fence: TRIPLE_BACKTICK@354..359 "```" [Skipped(" "), Skipped(" ")] [],
+            r_fence_indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@354..355 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@355..356 " " [] [],
+                },
+            ],
+            r_fence: TRIPLE_BACKTICK@356..359 "```" [] [],
         },
         MdNewline {
             value_token: NEWLINE@359..360 "\n" [] [],
@@ -423,16 +461,18 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@20..21 "\n" [] []
       1: (empty)
     1: MD_FENCED_CODE_BLOCK@21..33
-      0: TRIPLE_BACKTICK@21..24 "```" [] []
-      1: MD_CODE_NAME_LIST@24..24
-      2: MD_INLINE_ITEM_LIST@24..30
+      0: MD_INDENT_TOKEN_LIST@21..21
+      1: TRIPLE_BACKTICK@21..24 "```" [] []
+      2: MD_CODE_NAME_LIST@24..24
+      3: MD_INLINE_ITEM_LIST@24..30
         0: MD_TEXTUAL@24..25
           0: MD_TEXTUAL_LITERAL@24..25 "\n" [] []
         1: MD_TEXTUAL@25..29
           0: MD_TEXTUAL_LITERAL@25..29 "code" [] []
         2: MD_TEXTUAL@29..30
           0: MD_TEXTUAL_LITERAL@29..30 "\n" [] []
-      3: TRIPLE_BACKTICK@30..33 "```" [] []
+      4: MD_INDENT_TOKEN_LIST@30..30
+      5: TRIPLE_BACKTICK@30..33 "```" [] []
     2: MD_NEWLINE@33..34
       0: NEWLINE@33..34 "\n" [] []
     3: MD_NEWLINE@34..35
@@ -453,9 +493,10 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@62..63 "\n" [] []
       1: (empty)
     5: MD_FENCED_CODE_BLOCK@63..95
-      0: TRIPLE_BACKTICK@63..68 "`````" [] []
-      1: MD_CODE_NAME_LIST@68..68
-      2: MD_INLINE_ITEM_LIST@68..90
+      0: MD_INDENT_TOKEN_LIST@63..63
+      1: TRIPLE_BACKTICK@63..68 "`````" [] []
+      2: MD_CODE_NAME_LIST@68..68
+      3: MD_INLINE_ITEM_LIST@68..90
         0: MD_TEXTUAL@68..69
           0: MD_TEXTUAL_LITERAL@68..69 "\n" [] []
         1: MD_TEXTUAL@69..79
@@ -466,7 +507,8 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@82..89 " inside" [] []
         4: MD_TEXTUAL@89..90
           0: MD_TEXTUAL_LITERAL@89..90 "\n" [] []
-      3: TRIPLE_BACKTICK@90..95 "`````" [] []
+      4: MD_INDENT_TOKEN_LIST@90..90
+      5: TRIPLE_BACKTICK@90..95 "`````" [] []
     6: MD_NEWLINE@95..96
       0: NEWLINE@95..96 "\n" [] []
     7: MD_NEWLINE@96..97
@@ -479,16 +521,18 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@104..105 "\n" [] []
       1: (empty)
     9: MD_FENCED_CODE_BLOCK@105..117
-      0: TRIPLE_TILDE@105..108 "~~~" [] []
-      1: MD_CODE_NAME_LIST@108..108
-      2: MD_INLINE_ITEM_LIST@108..114
+      0: MD_INDENT_TOKEN_LIST@105..105
+      1: TRIPLE_TILDE@105..108 "~~~" [] []
+      2: MD_CODE_NAME_LIST@108..108
+      3: MD_INLINE_ITEM_LIST@108..114
         0: MD_TEXTUAL@108..109
           0: MD_TEXTUAL_LITERAL@108..109 "\n" [] []
         1: MD_TEXTUAL@109..113
           0: MD_TEXTUAL_LITERAL@109..113 "code" [] []
         2: MD_TEXTUAL@113..114
           0: MD_TEXTUAL_LITERAL@113..114 "\n" [] []
-      3: TRIPLE_TILDE@114..117 "~~~" [] []
+      4: MD_INDENT_TOKEN_LIST@114..114
+      5: TRIPLE_TILDE@114..117 "~~~" [] []
     10: MD_NEWLINE@117..118
       0: NEWLINE@117..118 "\n" [] []
     11: MD_NEWLINE@118..119
@@ -509,9 +553,10 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@144..145 "\n" [] []
       1: (empty)
     13: MD_FENCED_CODE_BLOCK@145..172
-      0: TRIPLE_BACKTICK@145..148 "```" [] []
-      1: MD_CODE_NAME_LIST@148..148
-      2: MD_INLINE_ITEM_LIST@148..169
+      0: MD_INDENT_TOKEN_LIST@145..145
+      1: TRIPLE_BACKTICK@145..148 "```" [] []
+      2: MD_CODE_NAME_LIST@148..148
+      3: MD_INLINE_ITEM_LIST@148..169
         0: MD_TEXTUAL@148..149
           0: MD_TEXTUAL_LITERAL@148..149 "\n" [] []
         1: MD_TEXTUAL@149..153
@@ -526,7 +571,8 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@158..168 "still code" [] []
         6: MD_TEXTUAL@168..169
           0: MD_TEXTUAL_LITERAL@168..169 "\n" [] []
-      3: TRIPLE_BACKTICK@169..172 "```" [] []
+      4: MD_INDENT_TOKEN_LIST@169..169
+      5: TRIPLE_BACKTICK@169..172 "```" [] []
     14: MD_NEWLINE@172..173
       0: NEWLINE@172..173 "\n" [] []
     15: MD_NEWLINE@173..174
@@ -547,16 +593,24 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@199..200 "\n" [] []
       1: (empty)
     17: MD_FENCED_CODE_BLOCK@200..215
-      0: TRIPLE_BACKTICK@200..203 "```" [] []
-      1: MD_CODE_NAME_LIST@203..203
-      2: MD_INLINE_ITEM_LIST@203..209
+      0: MD_INDENT_TOKEN_LIST@200..200
+      1: TRIPLE_BACKTICK@200..203 "```" [] []
+      2: MD_CODE_NAME_LIST@203..203
+      3: MD_INLINE_ITEM_LIST@203..209
         0: MD_TEXTUAL@203..204
           0: MD_TEXTUAL_LITERAL@203..204 "\n" [] []
         1: MD_TEXTUAL@204..208
           0: MD_TEXTUAL_LITERAL@204..208 "code" [] []
         2: MD_TEXTUAL@208..209
           0: MD_TEXTUAL_LITERAL@208..209 "\n" [] []
-      3: TRIPLE_BACKTICK@209..215 "```" [Skipped(" "), Skipped(" "), Skipped(" ")] []
+      4: MD_INDENT_TOKEN_LIST@209..212
+        0: MD_INDENT_TOKEN@209..210
+          0: MD_INDENT_CHAR@209..210 " " [] []
+        1: MD_INDENT_TOKEN@210..211
+          0: MD_INDENT_CHAR@210..211 " " [] []
+        2: MD_INDENT_TOKEN@211..212
+          0: MD_INDENT_CHAR@211..212 " " [] []
+      5: TRIPLE_BACKTICK@212..215 "```" [] []
     18: MD_NEWLINE@215..216
       0: NEWLINE@215..216 "\n" [] []
     19: MD_NEWLINE@216..217
@@ -581,9 +635,10 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@262..263 "\n" [] []
       1: (empty)
     21: MD_FENCED_CODE_BLOCK@263..292
-      0: TRIPLE_BACKTICK@263..267 "````" [] []
-      1: MD_CODE_NAME_LIST@267..267
-      2: MD_INLINE_ITEM_LIST@267..288
+      0: MD_INDENT_TOKEN_LIST@263..263
+      1: TRIPLE_BACKTICK@263..267 "````" [] []
+      2: MD_CODE_NAME_LIST@267..267
+      3: MD_INLINE_ITEM_LIST@267..288
         0: MD_TEXTUAL@267..268
           0: MD_TEXTUAL_LITERAL@267..268 "\n" [] []
         1: MD_TEXTUAL@268..272
@@ -598,7 +653,8 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@277..287 "still code" [] []
         6: MD_TEXTUAL@287..288
           0: MD_TEXTUAL_LITERAL@287..288 "\n" [] []
-      3: TRIPLE_BACKTICK@288..292 "````" [] []
+      4: MD_INDENT_TOKEN_LIST@288..288
+      5: TRIPLE_BACKTICK@288..292 "````" [] []
     22: MD_NEWLINE@292..293
       0: NEWLINE@292..293 "\n" [] []
     23: MD_NEWLINE@293..294
@@ -619,9 +675,14 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@335..336 "\n" [] []
       1: (empty)
     25: MD_FENCED_CODE_BLOCK@336..359
-      0: TRIPLE_BACKTICK@336..341 "```" [Skipped(" "), Skipped(" ")] []
-      1: MD_CODE_NAME_LIST@341..341
-      2: MD_INLINE_ITEM_LIST@341..354
+      0: MD_INDENT_TOKEN_LIST@336..338
+        0: MD_INDENT_TOKEN@336..337
+          0: MD_INDENT_CHAR@336..337 " " [] []
+        1: MD_INDENT_TOKEN@337..338
+          0: MD_INDENT_CHAR@337..338 " " [] []
+      1: TRIPLE_BACKTICK@338..341 "```" [] []
+      2: MD_CODE_NAME_LIST@341..341
+      3: MD_INLINE_ITEM_LIST@341..354
         0: MD_TEXTUAL@341..342
           0: MD_TEXTUAL_LITERAL@341..342 "\n" [] []
         1: MD_INDENT_TOKEN@342..343
@@ -632,7 +693,12 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@344..353 "code line" [] []
         4: MD_TEXTUAL@353..354
           0: MD_TEXTUAL_LITERAL@353..354 "\n" [] []
-      3: TRIPLE_BACKTICK@354..359 "```" [Skipped(" "), Skipped(" ")] []
+      4: MD_INDENT_TOKEN_LIST@354..356
+        0: MD_INDENT_TOKEN@354..355
+          0: MD_INDENT_CHAR@354..355 " " [] []
+        1: MD_INDENT_TOKEN@355..356
+          0: MD_INDENT_CHAR@355..356 " " [] []
+      5: TRIPLE_BACKTICK@356..359 "```" [] []
     26: MD_NEWLINE@359..360
       0: NEWLINE@359..360 "\n" [] []
   2: EOF@360..360 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_block.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_block.md.snap
index 84d49e8b788d..3ad4c311d2e5 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_block.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_block.md.snap
@@ -32,6 +32,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@0..3 "```" [] [],
             code_list: MdCodeNameList [
                 MdTextual {
@@ -49,6 +50,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@26..27 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@27..30 "```" [] [],
         },
         MdNewline {
@@ -58,6 +60,7 @@ MdDocument {
             value_token: NEWLINE@31..32 "\n" [] [],
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@32..35 "```" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -71,6 +74,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@47..48 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@48..51 "```" [] [],
         },
         MdNewline {
@@ -80,6 +84,7 @@ MdDocument {
             value_token: NEWLINE@52..53 "\n" [] [],
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_TILDE@53..56 "~~~" [] [],
             code_list: MdCodeNameList [
                 MdTextual {
@@ -97,6 +102,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@68..69 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_TILDE@69..72 "~~~" [] [],
         },
         MdNewline {
@@ -106,6 +112,7 @@ MdDocument {
             value_token: NEWLINE@73..74 "\n" [] [],
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_TILDE@74..77 "~~~" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -119,6 +126,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@95..96 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_TILDE@96..99 "~~~" [] [],
         },
         MdNewline {
@@ -136,65 +144,73 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..100
     0: MD_FENCED_CODE_BLOCK@0..30
-      0: TRIPLE_BACKTICK@0..3 "```" [] []
-      1: MD_CODE_NAME_LIST@3..13
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: TRIPLE_BACKTICK@0..3 "```" [] []
+      2: MD_CODE_NAME_LIST@3..13
         0: MD_TEXTUAL@3..13
           0: MD_TEXTUAL_LITERAL@3..13 "javascript" [] []
-      2: MD_INLINE_ITEM_LIST@13..27
+      3: MD_INLINE_ITEM_LIST@13..27
         0: MD_TEXTUAL@13..14
           0: MD_TEXTUAL_LITERAL@13..14 "\n" [] []
         1: MD_TEXTUAL@14..26
           0: MD_TEXTUAL_LITERAL@14..26 "const x = 1;" [] []
         2: MD_TEXTUAL@26..27
           0: MD_TEXTUAL_LITERAL@26..27 "\n" [] []
-      3: TRIPLE_BACKTICK@27..30 "```" [] []
+      4: MD_INDENT_TOKEN_LIST@27..27
+      5: TRIPLE_BACKTICK@27..30 "```" [] []
     1: MD_NEWLINE@30..31
       0: NEWLINE@30..31 "\n" [] []
     2: MD_NEWLINE@31..32
       0: NEWLINE@31..32 "\n" [] []
     3: MD_FENCED_CODE_BLOCK@32..51
-      0: TRIPLE_BACKTICK@32..35 "```" [] []
-      1: MD_CODE_NAME_LIST@35..35
-      2: MD_INLINE_ITEM_LIST@35..48
+      0: MD_INDENT_TOKEN_LIST@32..32
+      1: TRIPLE_BACKTICK@32..35 "```" [] []
+      2: MD_CODE_NAME_LIST@35..35
+      3: MD_INLINE_ITEM_LIST@35..48
         0: MD_TEXTUAL@35..36
           0: MD_TEXTUAL_LITERAL@35..36 "\n" [] []
         1: MD_TEXTUAL@36..47
           0: MD_TEXTUAL_LITERAL@36..47 "No language" [] []
         2: MD_TEXTUAL@47..48
           0: MD_TEXTUAL_LITERAL@47..48 "\n" [] []
-      3: TRIPLE_BACKTICK@48..51 "```" [] []
+      4: MD_INDENT_TOKEN_LIST@48..48
+      5: TRIPLE_BACKTICK@48..51 "```" [] []
     4: MD_NEWLINE@51..52
       0: NEWLINE@51..52 "\n" [] []
     5: MD_NEWLINE@52..53
       0: NEWLINE@52..53 "\n" [] []
     6: MD_FENCED_CODE_BLOCK@53..72
-      0: TRIPLE_TILDE@53..56 "~~~" [] []
-      1: MD_CODE_NAME_LIST@56..62
+      0: MD_INDENT_TOKEN_LIST@53..53
+      1: TRIPLE_TILDE@53..56 "~~~" [] []
+      2: MD_CODE_NAME_LIST@56..62
         0: MD_TEXTUAL@56..62
           0: MD_TEXTUAL_LITERAL@56..62 "python" [] []
-      2: MD_INLINE_ITEM_LIST@62..69
+      3: MD_INLINE_ITEM_LIST@62..69
         0: MD_TEXTUAL@62..63
           0: MD_TEXTUAL_LITERAL@62..63 "\n" [] []
         1: MD_TEXTUAL@63..68
           0: MD_TEXTUAL_LITERAL@63..68 "x = 1" [] []
         2: MD_TEXTUAL@68..69
           0: MD_TEXTUAL_LITERAL@68..69 "\n" [] []
-      3: TRIPLE_TILDE@69..72 "~~~" [] []
+      4: MD_INDENT_TOKEN_LIST@69..69
+      5: TRIPLE_TILDE@69..72 "~~~" [] []
     7: MD_NEWLINE@72..73
       0: NEWLINE@72..73 "\n" [] []
     8: MD_NEWLINE@73..74
       0: NEWLINE@73..74 "\n" [] []
     9: MD_FENCED_CODE_BLOCK@74..99
-      0: TRIPLE_TILDE@74..77 "~~~" [] []
-      1: MD_CODE_NAME_LIST@77..77
-      2: MD_INLINE_ITEM_LIST@77..96
+      0: MD_INDENT_TOKEN_LIST@74..74
+      1: TRIPLE_TILDE@74..77 "~~~" [] []
+      2: MD_CODE_NAME_LIST@77..77
+      3: MD_INLINE_ITEM_LIST@77..96
         0: MD_TEXTUAL@77..78
           0: MD_TEXTUAL_LITERAL@77..78 "\n" [] []
         1: MD_TEXTUAL@78..95
           0: MD_TEXTUAL_LITERAL@78..95 "Tilde no language" [] []
         2: MD_TEXTUAL@95..96
           0: MD_TEXTUAL_LITERAL@95..96 "\n" [] []
-      3: TRIPLE_TILDE@96..99 "~~~" [] []
+      4: MD_INDENT_TOKEN_LIST@96..96
+      5: TRIPLE_TILDE@96..99 "~~~" [] []
     10: MD_NEWLINE@99..100
       0: NEWLINE@99..100 "\n" [] []
   2: EOF@100..100 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_in_blockquote.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_in_blockquote.md.snap
index 343c19da5373..d60f181986f4 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_in_blockquote.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_in_blockquote.md.snap
@@ -31,6 +31,7 @@ MdDocument {
             },
             content: MdBlockList [
                 MdFencedCodeBlock {
+                    indent: MdIndentTokenList [],
                     l_fence: TRIPLE_BACKTICK@2..5 "```" [] [],
                     code_list: MdCodeNameList [
                         MdTextual {
@@ -67,6 +68,7 @@ MdDocument {
                             post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@26..27 " " [] [],
                         },
                     ],
+                    r_fence_indent: MdIndentTokenList [],
                     r_fence: TRIPLE_BACKTICK@27..30 "```" [] [],
                 },
                 MdNewline {
@@ -92,6 +94,7 @@ MdDocument {
                     },
                     content: MdBlockList [
                         MdFencedCodeBlock {
+                            indent: MdIndentTokenList [],
                             l_fence: TRIPLE_BACKTICK@36..39 "```" [] [],
                             code_list: MdCodeNameList [],
                             content: MdInlineItemList [
@@ -125,6 +128,7 @@ MdDocument {
                                     post_marker_space_token: MD_QUOTE_POST_MARKER_SPACE@54..55 " " [] [],
                                 },
                             ],
+                            r_fence_indent: MdIndentTokenList [],
                             r_fence: TRIPLE_BACKTICK@55..58 "```" [] [],
                         },
                         MdNewline {
@@ -152,11 +156,12 @@ MdDocument {
         2: MD_QUOTE_POST_MARKER_SPACE@1..2 " " [] []
       1: MD_BLOCK_LIST@2..31
         0: MD_FENCED_CODE_BLOCK@2..30
-          0: TRIPLE_BACKTICK@2..5 "```" [] []
-          1: MD_CODE_NAME_LIST@5..9
+          0: MD_INDENT_TOKEN_LIST@2..2
+          1: TRIPLE_BACKTICK@2..5 "```" [] []
+          2: MD_CODE_NAME_LIST@5..9
             0: MD_TEXTUAL@5..9
               0: MD_TEXTUAL_LITERAL@5..9 "rust" [] []
-          2: MD_INLINE_ITEM_LIST@9..27
+          3: MD_INLINE_ITEM_LIST@9..27
             0: MD_TEXTUAL@9..10
               0: MD_TEXTUAL_LITERAL@9..10 "\n" [] []
             1: MD_QUOTE_PREFIX@10..12
@@ -177,7 +182,8 @@ MdDocument {
               0: MD_QUOTE_INDENT_LIST@25..25
               1: R_ANGLE@25..26 ">" [] []
               2: MD_QUOTE_POST_MARKER_SPACE@26..27 " " [] []
-          3: TRIPLE_BACKTICK@27..30 "```" [] []
+          4: MD_INDENT_TOKEN_LIST@27..27
+          5: TRIPLE_BACKTICK@27..30 "```" [] []
         1: MD_NEWLINE@30..31
           0: NEWLINE@30..31 "\n" [] []
     1: MD_NEWLINE@31..32
@@ -195,9 +201,10 @@ MdDocument {
             2: MD_QUOTE_POST_MARKER_SPACE@35..36 " " [] []
           1: MD_BLOCK_LIST@36..59
             0: MD_FENCED_CODE_BLOCK@36..58
-              0: TRIPLE_BACKTICK@36..39 "```" [] []
-              1: MD_CODE_NAME_LIST@39..39
-              2: MD_INLINE_ITEM_LIST@39..55
+              0: MD_INDENT_TOKEN_LIST@36..36
+              1: TRIPLE_BACKTICK@36..39 "```" [] []
+              2: MD_CODE_NAME_LIST@39..39
+              3: MD_INLINE_ITEM_LIST@39..55
                 0: MD_TEXTUAL@39..40
                   0: MD_TEXTUAL_LITERAL@39..40 "\n" [] []
                 1: MD_QUOTE_PREFIX@40..42
@@ -220,7 +227,8 @@ MdDocument {
                   0: MD_QUOTE_INDENT_LIST@53..53
                   1: R_ANGLE@53..54 ">" [] []
                   2: MD_QUOTE_POST_MARKER_SPACE@54..55 " " [] []
-              3: TRIPLE_BACKTICK@55..58 "```" [] []
+              4: MD_INDENT_TOKEN_LIST@55..55
+              5: TRIPLE_BACKTICK@55..58 "```" [] []
             1: MD_NEWLINE@58..59
               0: NEWLINE@58..59 "\n" [] []
   2: EOF@59..59 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_indentation.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_indentation.md.snap
index f9c5d4777fee..4f9514defa36 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_indentation.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/fenced_code_indentation.md.snap
@@ -20,6 +20,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@0..3 "```" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -39,6 +40,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@14..15 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@15..18 "```" [] [],
         },
         MdNewline {
@@ -56,9 +58,10 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..19
     0: MD_FENCED_CODE_BLOCK@0..18
-      0: TRIPLE_BACKTICK@0..3 "```" [] []
-      1: MD_CODE_NAME_LIST@3..3
-      2: MD_INLINE_ITEM_LIST@3..15
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: TRIPLE_BACKTICK@0..3 "```" [] []
+      2: MD_CODE_NAME_LIST@3..3
+      3: MD_INLINE_ITEM_LIST@3..15
         0: MD_TEXTUAL@3..4
           0: MD_TEXTUAL_LITERAL@3..4 "\n" [] []
         1: MD_TEXTUAL@4..5
@@ -69,7 +72,8 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@6..14 "indented" [] []
         4: MD_TEXTUAL@14..15
           0: MD_TEXTUAL_LITERAL@14..15 "\n" [] []
-      3: TRIPLE_BACKTICK@15..18 "```" [] []
+      4: MD_INDENT_TOKEN_LIST@15..15
+      5: TRIPLE_BACKTICK@15..18 "```" [] []
     1: MD_NEWLINE@18..19
       0: NEWLINE@18..19 "\n" [] []
   2: EOF@19..19 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/header.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/header.md.snap
index 7faa757adb91..d124c00457ea 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/header.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/header.md.snap
@@ -34,6 +34,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@0..1 "#" [] [],
@@ -56,6 +57,7 @@ MdDocument {
             value_token: NEWLINE@12..13 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@13..15 "##" [] [],
@@ -78,6 +80,7 @@ MdDocument {
             value_token: NEWLINE@26..27 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@27..30 "###" [] [],
@@ -100,6 +103,7 @@ MdDocument {
             value_token: NEWLINE@41..42 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@42..46 "####" [] [],
@@ -122,6 +126,7 @@ MdDocument {
             value_token: NEWLINE@57..58 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@58..63 "#####" [] [],
@@ -144,6 +149,7 @@ MdDocument {
             value_token: NEWLINE@74..75 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@75..81 "######" [] [],
@@ -166,6 +172,7 @@ MdDocument {
             value_token: NEWLINE@92..93 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@93..94 "#" [] [],
@@ -192,6 +199,7 @@ MdDocument {
             value_token: NEWLINE@111..112 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@112..114 "##" [] [],
@@ -218,6 +226,7 @@ MdDocument {
             value_token: NEWLINE@136..137 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@137..140 "###" [] [],
@@ -270,99 +279,106 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..183
     0: MD_HEADER@0..11
-      0: MD_HASH_LIST@0..1
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: MD_HASH_LIST@0..1
         0: MD_HASH@0..1
           0: HASH@0..1 "#" [] []
-      1: MD_PARAGRAPH@1..11
+      2: MD_PARAGRAPH@1..11
         0: MD_INLINE_ITEM_LIST@1..11
           0: MD_TEXTUAL@1..11
             0: MD_TEXTUAL_LITERAL@1..11 " Heading 1" [] []
         1: (empty)
-      2: MD_HASH_LIST@11..11
+      3: MD_HASH_LIST@11..11
     1: MD_NEWLINE@11..12
       0: NEWLINE@11..12 "\n" [] []
     2: MD_NEWLINE@12..13
       0: NEWLINE@12..13 "\n" [] []
     3: MD_HEADER@13..25
-      0: MD_HASH_LIST@13..15
+      0: MD_INDENT_TOKEN_LIST@13..13
+      1: MD_HASH_LIST@13..15
         0: MD_HASH@13..15
           0: HASH@13..15 "##" [] []
-      1: MD_PARAGRAPH@15..25
+      2: MD_PARAGRAPH@15..25
         0: MD_INLINE_ITEM_LIST@15..25
           0: MD_TEXTUAL@15..25
             0: MD_TEXTUAL_LITERAL@15..25 " Heading 2" [] []
         1: (empty)
-      2: MD_HASH_LIST@25..25
+      3: MD_HASH_LIST@25..25
     4: MD_NEWLINE@25..26
       0: NEWLINE@25..26 "\n" [] []
     5: MD_NEWLINE@26..27
       0: NEWLINE@26..27 "\n" [] []
     6: MD_HEADER@27..40
-      0: MD_HASH_LIST@27..30
+      0: MD_INDENT_TOKEN_LIST@27..27
+      1: MD_HASH_LIST@27..30
         0: MD_HASH@27..30
           0: HASH@27..30 "###" [] []
-      1: MD_PARAGRAPH@30..40
+      2: MD_PARAGRAPH@30..40
         0: MD_INLINE_ITEM_LIST@30..40
           0: MD_TEXTUAL@30..40
             0: MD_TEXTUAL_LITERAL@30..40 " Heading 3" [] []
         1: (empty)
-      2: MD_HASH_LIST@40..40
+      3: MD_HASH_LIST@40..40
     7: MD_NEWLINE@40..41
       0: NEWLINE@40..41 "\n" [] []
     8: MD_NEWLINE@41..42
       0: NEWLINE@41..42 "\n" [] []
     9: MD_HEADER@42..56
-      0: MD_HASH_LIST@42..46
+      0: MD_INDENT_TOKEN_LIST@42..42
+      1: MD_HASH_LIST@42..46
         0: MD_HASH@42..46
           0: HASH@42..46 "####" [] []
-      1: MD_PARAGRAPH@46..56
+      2: MD_PARAGRAPH@46..56
         0: MD_INLINE_ITEM_LIST@46..56
           0: MD_TEXTUAL@46..56
             0: MD_TEXTUAL_LITERAL@46..56 " Heading 4" [] []
         1: (empty)
-      2: MD_HASH_LIST@56..56
+      3: MD_HASH_LIST@56..56
     10: MD_NEWLINE@56..57
       0: NEWLINE@56..57 "\n" [] []
     11: MD_NEWLINE@57..58
       0: NEWLINE@57..58 "\n" [] []
     12: MD_HEADER@58..73
-      0: MD_HASH_LIST@58..63
+      0: MD_INDENT_TOKEN_LIST@58..58
+      1: MD_HASH_LIST@58..63
         0: MD_HASH@58..63
           0: HASH@58..63 "#####" [] []
-      1: MD_PARAGRAPH@63..73
+      2: MD_PARAGRAPH@63..73
         0: MD_INLINE_ITEM_LIST@63..73
           0: MD_TEXTUAL@63..73
             0: MD_TEXTUAL_LITERAL@63..73 " Heading 5" [] []
         1: (empty)
-      2: MD_HASH_LIST@73..73
+      3: MD_HASH_LIST@73..73
     13: MD_NEWLINE@73..74
       0: NEWLINE@73..74 "\n" [] []
     14: MD_NEWLINE@74..75
       0: NEWLINE@74..75 "\n" [] []
     15: MD_HEADER@75..91
-      0: MD_HASH_LIST@75..81
+      0: MD_INDENT_TOKEN_LIST@75..75
+      1: MD_HASH_LIST@75..81
         0: MD_HASH@75..81
           0: HASH@75..81 "######" [] []
-      1: MD_PARAGRAPH@81..91
+      2: MD_PARAGRAPH@81..91
         0: MD_INLINE_ITEM_LIST@81..91
           0: MD_TEXTUAL@81..91
             0: MD_TEXTUAL_LITERAL@81..91 " Heading 6" [] []
         1: (empty)
-      2: MD_HASH_LIST@91..91
+      3: MD_HASH_LIST@91..91
     16: MD_NEWLINE@91..92
       0: NEWLINE@91..92 "\n" [] []
     17: MD_NEWLINE@92..93
       0: NEWLINE@92..93 "\n" [] []
     18: MD_HEADER@93..110
-      0: MD_HASH_LIST@93..94
+      0: MD_INDENT_TOKEN_LIST@93..93
+      1: MD_HASH_LIST@93..94
         0: MD_HASH@93..94
           0: HASH@93..94 "#" [] []
-      1: MD_PARAGRAPH@94..108
+      2: MD_PARAGRAPH@94..108
         0: MD_INLINE_ITEM_LIST@94..108
           0: MD_TEXTUAL@94..108
             0: MD_TEXTUAL_LITERAL@94..108 " Trailing hash" [] []
         1: (empty)
-      2: MD_HASH_LIST@108..110
+      3: MD_HASH_LIST@108..110
         0: MD_HASH@108..110
           0: HASH@108..110 "#" [Skipped(" ")] []
     19: MD_NEWLINE@110..111
@@ -370,15 +386,16 @@ MdDocument {
     20: MD_NEWLINE@111..112
       0: NEWLINE@111..112 "\n" [] []
     21: MD_HEADER@112..135
-      0: MD_HASH_LIST@112..114
+      0: MD_INDENT_TOKEN_LIST@112..112
+      1: MD_HASH_LIST@112..114
         0: MD_HASH@112..114
           0: HASH@112..114 "##" [] []
-      1: MD_PARAGRAPH@114..132
+      2: MD_PARAGRAPH@114..132
         0: MD_INLINE_ITEM_LIST@114..132
           0: MD_TEXTUAL@114..132
             0: MD_TEXTUAL_LITERAL@114..132 " Multiple trailing" [] []
         1: (empty)
-      2: MD_HASH_LIST@132..135
+      3: MD_HASH_LIST@132..135
         0: MD_HASH@132..135
           0: HASH@132..135 "##" [Skipped(" ")] []
     22: MD_NEWLINE@135..136
@@ -386,10 +403,11 @@ MdDocument {
     23: MD_NEWLINE@136..137
       0: NEWLINE@136..137 "\n" [] []
     24: MD_HEADER@137..182
-      0: MD_HASH_LIST@137..140
+      0: MD_INDENT_TOKEN_LIST@137..137
+      1: MD_HASH_LIST@137..140
         0: MD_HASH@137..140
           0: HASH@137..140 "###" [] []
-      1: MD_PARAGRAPH@140..177
+      2: MD_PARAGRAPH@140..177
         0: MD_INLINE_ITEM_LIST@140..177
           0: MD_TEXTUAL@140..147
             0: MD_TEXTUAL_LITERAL@140..147 " Mixed " [] []
@@ -406,7 +424,7 @@ MdDocument {
           6: MD_TEXTUAL@168..177
             0: MD_TEXTUAL_LITERAL@168..177 " trailing" [] []
         1: (empty)
-      2: MD_HASH_LIST@177..182
+      3: MD_HASH_LIST@177..182
         0: MD_HASH@177..182
           0: HASH@177..182 "####" [Skipped(" ")] []
     25: MD_NEWLINE@182..183
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/html_block.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/html_block.md.snap
index a0dae7edfdb3..d39c143d36f5 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/html_block.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/html_block.md.snap
@@ -23,6 +23,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdHtmlBlock {
+            indent: MdIndentTokenList [],
             content: MdInlineItemList [
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@0..1 "<" [] [],
@@ -88,7 +89,8 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..101
     0: MD_HTML_BLOCK@0..67
-      0: MD_INLINE_ITEM_LIST@0..67
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: MD_INLINE_ITEM_LIST@0..67
         0: MD_TEXTUAL@0..1
           0: MD_TEXTUAL_LITERAL@0..1 "<" [] []
         1: MD_TEXTUAL@1..4
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/indent_code_block.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/indent_code_block.md.snap
index 55c95bf17724..156cfddec9e6 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/indent_code_block.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/indent_code_block.md.snap
@@ -26,8 +26,20 @@ MdDocument {
     value: MdBlockList [
         MdIndentCodeBlock {
             content: MdInlineItemList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@0..1 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@1..2 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@2..3 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@3..4 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@0..18 "function hello" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@4..18 "function hello" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@18..19 "(" [] [],
@@ -41,11 +53,32 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@22..23 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@23..24 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@24..25 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@25..26 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@26..27 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@23..28 " " [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@27..28 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@28..29 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@29..30 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@30..31 " " [] [],
                 },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@28..42 "console.log" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@31..42 "console.log" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@42..43 "(" [] [],
@@ -62,8 +95,20 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@55..56 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@56..57 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@57..58 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@58..59 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@59..60 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@56..61 "}" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@60..61 "}" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@61..62 "\n" [] [],
@@ -89,14 +134,38 @@ MdDocument {
         },
         MdIndentCodeBlock {
             content: MdInlineItemList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@88..89 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@89..90 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@90..91 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@91..92 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@88..101 "More code" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@92..101 "More code" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@101..102 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@102..103 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@103..104 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@104..105 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@105..106 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@102..120 "continues here" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@106..120 "continues here" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@120..121 "\n" [] [],
@@ -116,33 +185,63 @@ MdDocument {
   1: MD_BLOCK_LIST@0..121
     0: MD_INDENT_CODE_BLOCK@0..62
       0: MD_INLINE_ITEM_LIST@0..62
-        0: MD_TEXTUAL@0..18
-          0: MD_TEXTUAL_LITERAL@0..18 "function hello" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        1: MD_TEXTUAL@18..19
+        0: MD_INDENT_TOKEN@0..1
+          0: MD_INDENT_CHAR@0..1 " " [] []
+        1: MD_INDENT_TOKEN@1..2
+          0: MD_INDENT_CHAR@1..2 " " [] []
+        2: MD_INDENT_TOKEN@2..3
+          0: MD_INDENT_CHAR@2..3 " " [] []
+        3: MD_INDENT_TOKEN@3..4
+          0: MD_INDENT_CHAR@3..4 " " [] []
+        4: MD_TEXTUAL@4..18
+          0: MD_TEXTUAL_LITERAL@4..18 "function hello" [] []
+        5: MD_TEXTUAL@18..19
           0: MD_TEXTUAL_LITERAL@18..19 "(" [] []
-        2: MD_TEXTUAL@19..20
+        6: MD_TEXTUAL@19..20
           0: MD_TEXTUAL_LITERAL@19..20 ")" [] []
-        3: MD_TEXTUAL@20..22
+        7: MD_TEXTUAL@20..22
           0: MD_TEXTUAL_LITERAL@20..22 " {" [] []
-        4: MD_TEXTUAL@22..23
+        8: MD_TEXTUAL@22..23
           0: MD_TEXTUAL_LITERAL@22..23 "\n" [] []
-        5: MD_TEXTUAL@23..28
-          0: MD_TEXTUAL_LITERAL@23..28 " " [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        6: MD_TEXTUAL@28..42
-          0: MD_TEXTUAL_LITERAL@28..42 "console.log" [Skipped(" "), Skipped(" "), Skipped(" ")] []
-        7: MD_TEXTUAL@42..43
+        9: MD_INDENT_TOKEN@23..24
+          0: MD_INDENT_CHAR@23..24 " " [] []
+        10: MD_INDENT_TOKEN@24..25
+          0: MD_INDENT_CHAR@24..25 " " [] []
+        11: MD_INDENT_TOKEN@25..26
+          0: MD_INDENT_CHAR@25..26 " " [] []
+        12: MD_INDENT_TOKEN@26..27
+          0: MD_INDENT_CHAR@26..27 " " [] []
+        13: MD_TEXTUAL@27..28
+          0: MD_TEXTUAL_LITERAL@27..28 " " [] []
+        14: MD_INDENT_TOKEN@28..29
+          0: MD_INDENT_CHAR@28..29 " " [] []
+        15: MD_INDENT_TOKEN@29..30
+          0: MD_INDENT_CHAR@29..30 " " [] []
+        16: MD_INDENT_TOKEN@30..31
+          0: MD_INDENT_CHAR@30..31 " " [] []
+        17: MD_TEXTUAL@31..42
+          0: MD_TEXTUAL_LITERAL@31..42 "console.log" [] []
+        18: MD_TEXTUAL@42..43
           0: MD_TEXTUAL_LITERAL@42..43 "(" [] []
-        8: MD_TEXTUAL@43..53
+        19: MD_TEXTUAL@43..53
           0: MD_TEXTUAL_LITERAL@43..53 "\"indented\"" [] []
-        9: MD_TEXTUAL@53..54
+        20: MD_TEXTUAL@53..54
           0: MD_TEXTUAL_LITERAL@53..54 ")" [] []
-        10: MD_TEXTUAL@54..55
+        21: MD_TEXTUAL@54..55
           0: MD_TEXTUAL_LITERAL@54..55 ";" [] []
-        11: MD_TEXTUAL@55..56
+        22: MD_TEXTUAL@55..56
           0: MD_TEXTUAL_LITERAL@55..56 "\n" [] []
-        12: MD_TEXTUAL@56..61
-          0: MD_TEXTUAL_LITERAL@56..61 "}" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        13: MD_TEXTUAL@61..62
+        23: MD_INDENT_TOKEN@56..57
+          0: MD_INDENT_CHAR@56..57 " " [] []
+        24: MD_INDENT_TOKEN@57..58
+          0: MD_INDENT_CHAR@57..58 " " [] []
+        25: MD_INDENT_TOKEN@58..59
+          0: MD_INDENT_CHAR@58..59 " " [] []
+        26: MD_INDENT_TOKEN@59..60
+          0: MD_INDENT_CHAR@59..60 " " [] []
+        27: MD_TEXTUAL@60..61
+          0: MD_TEXTUAL_LITERAL@60..61 "}" [] []
+        28: MD_TEXTUAL@61..62
           0: MD_TEXTUAL_LITERAL@61..62 "\n" [] []
     1: MD_NEWLINE@62..63
       0: NEWLINE@62..63 "\n" [] []
@@ -157,13 +256,29 @@ MdDocument {
       0: NEWLINE@87..88 "\n" [] []
     4: MD_INDENT_CODE_BLOCK@88..121
       0: MD_INLINE_ITEM_LIST@88..121
-        0: MD_TEXTUAL@88..101
-          0: MD_TEXTUAL_LITERAL@88..101 "More code" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        1: MD_TEXTUAL@101..102
+        0: MD_INDENT_TOKEN@88..89
+          0: MD_INDENT_CHAR@88..89 " " [] []
+        1: MD_INDENT_TOKEN@89..90
+          0: MD_INDENT_CHAR@89..90 " " [] []
+        2: MD_INDENT_TOKEN@90..91
+          0: MD_INDENT_CHAR@90..91 " " [] []
+        3: MD_INDENT_TOKEN@91..92
+          0: MD_INDENT_CHAR@91..92 " " [] []
+        4: MD_TEXTUAL@92..101
+          0: MD_TEXTUAL_LITERAL@92..101 "More code" [] []
+        5: MD_TEXTUAL@101..102
           0: MD_TEXTUAL_LITERAL@101..102 "\n" [] []
-        2: MD_TEXTUAL@102..120
-          0: MD_TEXTUAL_LITERAL@102..120 "continues here" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        3: MD_TEXTUAL@120..121
+        6: MD_INDENT_TOKEN@102..103
+          0: MD_INDENT_CHAR@102..103 " " [] []
+        7: MD_INDENT_TOKEN@103..104
+          0: MD_INDENT_CHAR@103..104 " " [] []
+        8: MD_INDENT_TOKEN@104..105
+          0: MD_INDENT_CHAR@104..105 " " [] []
+        9: MD_INDENT_TOKEN@105..106
+          0: MD_INDENT_CHAR@105..106 " " [] []
+        10: MD_TEXTUAL@106..120
+          0: MD_TEXTUAL_LITERAL@106..120 "continues here" [] []
+        11: MD_TEXTUAL@120..121
           0: MD_TEXTUAL_LITERAL@120..121 "\n" [] []
   2: EOF@121..121 "" [] []
 
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/indented_code_blank_lines.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/indented_code_blank_lines.md.snap
index eb0cb0ecf4f2..884f27490b3d 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/indented_code_blank_lines.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/indented_code_blank_lines.md.snap
@@ -23,8 +23,20 @@ MdDocument {
     value: MdBlockList [
         MdIndentCodeBlock {
             content: MdInlineItemList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@0..1 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@1..2 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@2..3 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@3..4 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@0..5 "a" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@4..5 "a" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@5..6 "\n" [] [],
@@ -32,8 +44,20 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@6..7 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@7..8 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@8..9 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@9..10 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@10..11 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@7..12 "b" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@11..12 "b" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@12..13 "\n" [] [],
@@ -41,11 +65,32 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@13..14 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@14..15 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@15..16 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@16..17 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@17..18 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@14..19 " " [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@18..19 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@19..20 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@20..21 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@21..22 " " [] [],
                 },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@19..23 "x" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@22..23 "x" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@23..24 "\n" [] [],
@@ -65,23 +110,53 @@ MdDocument {
   1: MD_BLOCK_LIST@0..24
     0: MD_INDENT_CODE_BLOCK@0..24
       0: MD_INLINE_ITEM_LIST@0..24
-        0: MD_TEXTUAL@0..5
-          0: MD_TEXTUAL_LITERAL@0..5 "a" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        1: MD_TEXTUAL@5..6
+        0: MD_INDENT_TOKEN@0..1
+          0: MD_INDENT_CHAR@0..1 " " [] []
+        1: MD_INDENT_TOKEN@1..2
+          0: MD_INDENT_CHAR@1..2 " " [] []
+        2: MD_INDENT_TOKEN@2..3
+          0: MD_INDENT_CHAR@2..3 " " [] []
+        3: MD_INDENT_TOKEN@3..4
+          0: MD_INDENT_CHAR@3..4 " " [] []
+        4: MD_TEXTUAL@4..5
+          0: MD_TEXTUAL_LITERAL@4..5 "a" [] []
+        5: MD_TEXTUAL@5..6
           0: MD_TEXTUAL_LITERAL@5..6 "\n" [] []
-        2: MD_TEXTUAL@6..7
+        6: MD_TEXTUAL@6..7
           0: MD_TEXTUAL_LITERAL@6..7 "\n" [] []
-        3: MD_TEXTUAL@7..12
-          0: MD_TEXTUAL_LITERAL@7..12 "b" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        4: MD_TEXTUAL@12..13
+        7: MD_INDENT_TOKEN@7..8
+          0: MD_INDENT_CHAR@7..8 " " [] []
+        8: MD_INDENT_TOKEN@8..9
+          0: MD_INDENT_CHAR@8..9 " " [] []
+        9: MD_INDENT_TOKEN@9..10
+          0: MD_INDENT_CHAR@9..10 " " [] []
+        10: MD_INDENT_TOKEN@10..11
+          0: MD_INDENT_CHAR@10..11 " " [] []
+        11: MD_TEXTUAL@11..12
+          0: MD_TEXTUAL_LITERAL@11..12 "b" [] []
+        12: MD_TEXTUAL@12..13
           0: MD_TEXTUAL_LITERAL@12..13 "\n" [] []
-        5: MD_TEXTUAL@13..14
+        13: MD_TEXTUAL@13..14
           0: MD_TEXTUAL_LITERAL@13..14 "\n" [] []
-        6: MD_TEXTUAL@14..19
-          0: MD_TEXTUAL_LITERAL@14..19 " " [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        7: MD_TEXTUAL@19..23
-          0: MD_TEXTUAL_LITERAL@19..23 "x" [Skipped(" "), Skipped(" "), Skipped(" ")] []
-        8: MD_TEXTUAL@23..24
+        14: MD_INDENT_TOKEN@14..15
+          0: MD_INDENT_CHAR@14..15 " " [] []
+        15: MD_INDENT_TOKEN@15..16
+          0: MD_INDENT_CHAR@15..16 " " [] []
+        16: MD_INDENT_TOKEN@16..17
+          0: MD_INDENT_CHAR@16..17 " " [] []
+        17: MD_INDENT_TOKEN@17..18
+          0: MD_INDENT_CHAR@17..18 " " [] []
+        18: MD_TEXTUAL@18..19
+          0: MD_TEXTUAL_LITERAL@18..19 " " [] []
+        19: MD_INDENT_TOKEN@19..20
+          0: MD_INDENT_CHAR@19..20 " " [] []
+        20: MD_INDENT_TOKEN@20..21
+          0: MD_INDENT_CHAR@20..21 " " [] []
+        21: MD_INDENT_TOKEN@21..22
+          0: MD_INDENT_CHAR@21..22 " " [] []
+        22: MD_TEXTUAL@22..23
+          0: MD_TEXTUAL_LITERAL@22..23 "x" [] []
+        23: MD_TEXTUAL@23..24
           0: MD_TEXTUAL_LITERAL@23..24 "\n" [] []
   2: EOF@24..24 "" [] []
 
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/inline_html_edge_cases.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/inline_html_edge_cases.md.snap
index 1b0a0be924d5..3fcccec2545c 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/inline_html_edge_cases.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/inline_html_edge_cases.md.snap
@@ -80,6 +80,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@0..1 "#" [] [],
@@ -102,6 +103,7 @@ MdDocument {
             value_token: NEWLINE@25..26 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@26..28 "##" [] [],
@@ -205,6 +207,7 @@ MdDocument {
             value_token: NEWLINE@123..124 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@124..126 "##" [] [],
@@ -304,6 +307,7 @@ MdDocument {
             value_token: NEWLINE@231..232 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@232..234 "##" [] [],
@@ -433,6 +437,7 @@ MdDocument {
             value_token: NEWLINE@321..322 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@322..324 "##" [] [],
@@ -617,6 +622,7 @@ MdDocument {
             value_token: NEWLINE@455..456 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@456..458 "##" [] [],
@@ -688,6 +694,7 @@ MdDocument {
             value_token: NEWLINE@552..553 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@553..555 "##" [] [],
@@ -801,6 +808,7 @@ MdDocument {
             value_token: NEWLINE@638..639 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@639..641 "##" [] [],
@@ -909,6 +917,7 @@ MdDocument {
             value_token: NEWLINE@801..802 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@802..804 "##" [] [],
@@ -1050,6 +1059,7 @@ MdDocument {
             value_token: NEWLINE@968..969 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@969..971 "##" [] [],
@@ -1303,6 +1313,7 @@ MdDocument {
             value_token: NEWLINE@1261..1262 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@1262..1264 "##" [] [],
@@ -1424,6 +1435,7 @@ MdDocument {
             value_token: NEWLINE@1389..1390 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@1390..1392 "##" [] [],
@@ -1493,6 +1505,7 @@ MdDocument {
             value_token: NEWLINE@1493..1494 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@1494..1496 "##" [] [],
@@ -1632,6 +1645,7 @@ MdDocument {
             value_token: NEWLINE@1633..1634 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@1634..1636 "##" [] [],
@@ -1724,29 +1738,31 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..1703
     0: MD_HEADER@0..24
-      0: MD_HASH_LIST@0..1
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: MD_HASH_LIST@0..1
         0: MD_HASH@0..1
           0: HASH@0..1 "#" [] []
-      1: MD_PARAGRAPH@1..24
+      2: MD_PARAGRAPH@1..24
         0: MD_INLINE_ITEM_LIST@1..24
           0: MD_TEXTUAL@1..24
             0: MD_TEXTUAL_LITERAL@1..24 " Inline HTML Edge Cases" [] []
         1: (empty)
-      2: MD_HASH_LIST@24..24
+      3: MD_HASH_LIST@24..24
     1: MD_NEWLINE@24..25
       0: NEWLINE@24..25 "\n" [] []
     2: MD_NEWLINE@25..26
       0: NEWLINE@25..26 "\n" [] []
     3: MD_HEADER@26..44
-      0: MD_HASH_LIST@26..28
+      0: MD_INDENT_TOKEN_LIST@26..26
+      1: MD_HASH_LIST@26..28
         0: MD_HASH@26..28
           0: HASH@26..28 "##" [] []
-      1: MD_PARAGRAPH@28..44
+      2: MD_PARAGRAPH@28..44
         0: MD_INLINE_ITEM_LIST@28..44
           0: MD_TEXTUAL@28..44
             0: MD_TEXTUAL_LITERAL@28..44 " Basic Open Tags" [] []
         1: (empty)
-      2: MD_HASH_LIST@44..44
+      3: MD_HASH_LIST@44..44
     4: MD_NEWLINE@44..45
       0: NEWLINE@44..45 "\n" [] []
     5: MD_PARAGRAPH@45..123
@@ -1803,10 +1819,11 @@ MdDocument {
     6: MD_NEWLINE@123..124
       0: NEWLINE@123..124 "\n" [] []
     7: MD_HEADER@124..144
-      0: MD_HASH_LIST@124..126
+      0: MD_INDENT_TOKEN_LIST@124..124
+      1: MD_HASH_LIST@124..126
         0: MD_HASH@124..126
           0: HASH@124..126 "##" [] []
-      1: MD_PARAGRAPH@126..144
+      2: MD_PARAGRAPH@126..144
         0: MD_INLINE_ITEM_LIST@126..144
           0: MD_TEXTUAL@126..131
             0: MD_TEXTUAL_LITERAL@126..131 " Self" [] []
@@ -1815,7 +1832,7 @@ MdDocument {
           2: MD_TEXTUAL@132..144
             0: MD_TEXTUAL_LITERAL@132..144 "Closing Tags" [] []
         1: (empty)
-      2: MD_HASH_LIST@144..144
+      3: MD_HASH_LIST@144..144
     8: MD_NEWLINE@144..145
       0: NEWLINE@144..145 "\n" [] []
     9: MD_PARAGRAPH@145..231
@@ -1866,15 +1883,16 @@ MdDocument {
     10: MD_NEWLINE@231..232
       0: NEWLINE@231..232 "\n" [] []
     11: MD_HEADER@232..247
-      0: MD_HASH_LIST@232..234
+      0: MD_INDENT_TOKEN_LIST@232..232
+      1: MD_HASH_LIST@232..234
         0: MD_HASH@232..234
           0: HASH@232..234 "##" [] []
-      1: MD_PARAGRAPH@234..247
+      2: MD_PARAGRAPH@234..247
         0: MD_INLINE_ITEM_LIST@234..247
           0: MD_TEXTUAL@234..247
             0: MD_TEXTUAL_LITERAL@234..247 " Closing Tags" [] []
         1: (empty)
-      2: MD_HASH_LIST@247..247
+      3: MD_HASH_LIST@247..247
     12: MD_NEWLINE@247..248
       0: NEWLINE@247..248 "\n" [] []
     13: MD_PARAGRAPH@248..321
@@ -1947,15 +1965,16 @@ MdDocument {
     14: MD_NEWLINE@321..322
       0: NEWLINE@321..322 "\n" [] []
     15: MD_HEADER@322..333
-      0: MD_HASH_LIST@322..324
+      0: MD_INDENT_TOKEN_LIST@322..322
+      1: MD_HASH_LIST@322..324
         0: MD_HASH@322..324
           0: HASH@322..324 "##" [] []
-      1: MD_PARAGRAPH@324..333
+      2: MD_PARAGRAPH@324..333
         0: MD_INLINE_ITEM_LIST@324..333
           0: MD_TEXTUAL@324..333
             0: MD_TEXTUAL_LITERAL@324..333 " Comments" [] []
         1: (empty)
-      2: MD_HASH_LIST@333..333
+      3: MD_HASH_LIST@333..333
     16: MD_NEWLINE@333..334
       0: NEWLINE@333..334 "\n" [] []
     17: MD_PARAGRAPH@334..455
@@ -2066,15 +2085,16 @@ MdDocument {
     18: MD_NEWLINE@455..456
       0: NEWLINE@455..456 "\n" [] []
     19: MD_HEADER@456..482
-      0: MD_HASH_LIST@456..458
+      0: MD_INDENT_TOKEN_LIST@456..456
+      1: MD_HASH_LIST@456..458
         0: MD_HASH@456..458
           0: HASH@456..458 "##" [] []
-      1: MD_PARAGRAPH@458..482
+      2: MD_PARAGRAPH@458..482
         0: MD_INLINE_ITEM_LIST@458..482
           0: MD_TEXTUAL@458..482
             0: MD_TEXTUAL_LITERAL@458..482 " Processing Instructions" [] []
         1: (empty)
-      2: MD_HASH_LIST@482..482
+      3: MD_HASH_LIST@482..482
     20: MD_NEWLINE@482..483
       0: NEWLINE@482..483 "\n" [] []
     21: MD_PARAGRAPH@483..552
@@ -2111,15 +2131,16 @@ MdDocument {
     22: MD_NEWLINE@552..553
       0: NEWLINE@552..553 "\n" [] []
     23: MD_HEADER@553..570
-      0: MD_HASH_LIST@553..555
+      0: MD_INDENT_TOKEN_LIST@553..553
+      1: MD_HASH_LIST@553..555
         0: MD_HASH@553..555
           0: HASH@553..555 "##" [] []
-      1: MD_PARAGRAPH@555..570
+      2: MD_PARAGRAPH@555..570
         0: MD_INLINE_ITEM_LIST@555..570
           0: MD_TEXTUAL@555..570
             0: MD_TEXTUAL_LITERAL@555..570 " CDATA Sections" [] []
         1: (empty)
-      2: MD_HASH_LIST@570..570
+      3: MD_HASH_LIST@570..570
     24: MD_NEWLINE@570..571
       0: NEWLINE@570..571 "\n" [] []
     25: MD_PARAGRAPH@571..638
@@ -2184,15 +2205,16 @@ MdDocument {
     26: MD_NEWLINE@638..639
       0: NEWLINE@638..639 "\n" [] []
     27: MD_HEADER@639..654
-      0: MD_HASH_LIST@639..641
+      0: MD_INDENT_TOKEN_LIST@639..639
+      1: MD_HASH_LIST@639..641
         0: MD_HASH@639..641
           0: HASH@639..641 "##" [] []
-      1: MD_PARAGRAPH@641..654
+      2: MD_PARAGRAPH@641..654
         0: MD_INLINE_ITEM_LIST@641..654
           0: MD_TEXTUAL@641..654
             0: MD_TEXTUAL_LITERAL@641..654 " Declarations" [] []
         1: (empty)
-      2: MD_HASH_LIST@654..654
+      3: MD_HASH_LIST@654..654
     28: MD_NEWLINE@654..655
       0: NEWLINE@654..655 "\n" [] []
     29: MD_PARAGRAPH@655..801
@@ -2253,15 +2275,16 @@ MdDocument {
     30: MD_NEWLINE@801..802
       0: NEWLINE@801..802 "\n" [] []
     31: MD_HEADER@802..827
-      0: MD_HASH_LIST@802..804
+      0: MD_INDENT_TOKEN_LIST@802..802
+      1: MD_HASH_LIST@802..804
         0: MD_HASH@802..804
           0: HASH@802..804 "##" [] []
-      1: MD_PARAGRAPH@804..827
+      2: MD_PARAGRAPH@804..827
         0: MD_INLINE_ITEM_LIST@804..827
           0: MD_TEXTUAL@804..827
             0: MD_TEXTUAL_LITERAL@804..827 " Attributes with Quotes" [] []
         1: (empty)
-      2: MD_HASH_LIST@827..827
+      3: MD_HASH_LIST@827..827
     32: MD_NEWLINE@827..828
       0: NEWLINE@827..828 "\n" [] []
     33: MD_PARAGRAPH@828..968
@@ -2342,15 +2365,16 @@ MdDocument {
     34: MD_NEWLINE@968..969
       0: NEWLINE@968..969 "\n" [] []
     35: MD_HEADER@969..1001
-      0: MD_HASH_LIST@969..971
+      0: MD_INDENT_TOKEN_LIST@969..969
+      1: MD_HASH_LIST@969..971
         0: MD_HASH@969..971
           0: HASH@969..971 "##" [] []
-      1: MD_PARAGRAPH@971..1001
+      2: MD_PARAGRAPH@971..1001
         0: MD_INLINE_ITEM_LIST@971..1001
           0: MD_TEXTUAL@971..1001
             0: MD_TEXTUAL_LITERAL@971..1001 " Attributes with Special Chars" [] []
         1: (empty)
-      2: MD_HASH_LIST@1001..1001
+      3: MD_HASH_LIST@1001..1001
     36: MD_NEWLINE@1001..1002
       0: NEWLINE@1001..1002 "\n" [] []
     37: MD_PARAGRAPH@1002..1261
@@ -2503,10 +2527,11 @@ MdDocument {
     38: MD_NEWLINE@1261..1262
       0: NEWLINE@1261..1262 "\n" [] []
     39: MD_HEADER@1262..1308
-      0: MD_HASH_LIST@1262..1264
+      0: MD_INDENT_TOKEN_LIST@1262..1262
+      1: MD_HASH_LIST@1262..1264
         0: MD_HASH@1262..1264
           0: HASH@1262..1264 "##" [] []
-      1: MD_PARAGRAPH@1264..1308
+      2: MD_PARAGRAPH@1264..1308
         0: MD_INLINE_ITEM_LIST@1264..1308
           0: MD_TEXTUAL@1264..1279
             0: MD_TEXTUAL_LITERAL@1264..1279 " Newline Cases " [] []
@@ -2517,7 +2542,7 @@ MdDocument {
           3: MD_TEXTUAL@1307..1308
             0: MD_TEXTUAL_LITERAL@1307..1308 ")" [] []
         1: (empty)
-      2: MD_HASH_LIST@1308..1308
+      3: MD_HASH_LIST@1308..1308
     40: MD_NEWLINE@1308..1309
       0: NEWLINE@1308..1309 "\n" [] []
     41: MD_PARAGRAPH@1309..1389
@@ -2580,10 +2605,11 @@ MdDocument {
     42: MD_NEWLINE@1389..1390
       0: NEWLINE@1389..1390 "\n" [] []
     43: MD_HEADER@1390..1424
-      0: MD_HASH_LIST@1390..1392
+      0: MD_INDENT_TOKEN_LIST@1390..1390
+      1: MD_HASH_LIST@1390..1392
         0: MD_HASH@1390..1392
           0: HASH@1390..1392 "##" [] []
-      1: MD_PARAGRAPH@1392..1424
+      2: MD_PARAGRAPH@1392..1424
         0: MD_INLINE_ITEM_LIST@1392..1424
           0: MD_TEXTUAL@1392..1402
             0: MD_TEXTUAL_LITERAL@1392..1402 " Priority " [] []
@@ -2592,7 +2618,7 @@ MdDocument {
           2: MD_TEXTUAL@1403..1424
             0: MD_TEXTUAL_LITERAL@1403..1424 " Autolinks Should Win" [] []
         1: (empty)
-      2: MD_HASH_LIST@1424..1424
+      3: MD_HASH_LIST@1424..1424
     44: MD_NEWLINE@1424..1425
       0: NEWLINE@1424..1425 "\n" [] []
     45: MD_PARAGRAPH@1425..1493
@@ -2625,15 +2651,16 @@ MdDocument {
     46: MD_NEWLINE@1493..1494
       0: NEWLINE@1493..1494 "\n" [] []
     47: MD_HEADER@1494..1519
-      0: MD_HASH_LIST@1494..1496
+      0: MD_INDENT_TOKEN_LIST@1494..1494
+      1: MD_HASH_LIST@1494..1496
         0: MD_HASH@1494..1496
           0: HASH@1494..1496 "##" [] []
-      1: MD_PARAGRAPH@1496..1519
+      2: MD_PARAGRAPH@1496..1519
         0: MD_INLINE_ITEM_LIST@1496..1519
           0: MD_TEXTUAL@1496..1519
             0: MD_TEXTUAL_LITERAL@1496..1519 " Tag Names with Hyphens" [] []
         1: (empty)
-      2: MD_HASH_LIST@1519..1519
+      3: MD_HASH_LIST@1519..1519
     48: MD_NEWLINE@1519..1520
       0: NEWLINE@1519..1520 "\n" [] []
     49: MD_PARAGRAPH@1520..1633
@@ -2714,15 +2741,16 @@ MdDocument {
     50: MD_NEWLINE@1633..1634
       0: NEWLINE@1633..1634 "\n" [] []
     51: MD_HEADER@1634..1647
-      0: MD_HASH_LIST@1634..1636
+      0: MD_INDENT_TOKEN_LIST@1634..1634
+      1: MD_HASH_LIST@1634..1636
         0: MD_HASH@1634..1636
           0: HASH@1634..1636 "##" [] []
-      1: MD_PARAGRAPH@1636..1647
+      2: MD_PARAGRAPH@1636..1647
         0: MD_INLINE_ITEM_LIST@1636..1647
           0: MD_TEXTUAL@1636..1647
             0: MD_TEXTUAL_LITERAL@1636..1647 " Empty Tags" [] []
         1: (empty)
-      2: MD_HASH_LIST@1647..1647
+      3: MD_HASH_LIST@1647..1647
     52: MD_NEWLINE@1647..1648
       0: NEWLINE@1647..1648 "\n" [] []
     53: MD_PARAGRAPH@1648..1703
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/inline_html_invalid.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/inline_html_invalid.md.snap
index a854a5ad813d..bd952a48fc46 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/inline_html_invalid.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/inline_html_invalid.md.snap
@@ -38,6 +38,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@0..1 "#" [] [],
@@ -74,6 +75,7 @@ MdDocument {
             value_token: NEWLINE@85..86 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@86..88 "##" [] [],
@@ -137,6 +139,7 @@ MdDocument {
             value_token: NEWLINE@196..197 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@197..199 "##" [] [],
@@ -293,6 +296,7 @@ MdDocument {
             value_token: NEWLINE@506..507 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@507..509 "##" [] [],
@@ -433,15 +437,16 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..658
     0: MD_HEADER@0..27
-      0: MD_HASH_LIST@0..1
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: MD_HASH_LIST@0..1
         0: MD_HASH@0..1
           0: HASH@0..1 "#" [] []
-      1: MD_PARAGRAPH@1..27
+      2: MD_PARAGRAPH@1..27
         0: MD_INLINE_ITEM_LIST@1..27
           0: MD_TEXTUAL@1..27
             0: MD_TEXTUAL_LITERAL@1..27 " Invalid Inline HTML Cases" [] []
         1: (empty)
-      2: MD_HASH_LIST@27..27
+      3: MD_HASH_LIST@27..27
     1: MD_NEWLINE@27..28
       0: NEWLINE@27..28 "\n" [] []
     2: MD_NEWLINE@28..29
@@ -456,15 +461,16 @@ MdDocument {
     4: MD_NEWLINE@85..86
       0: NEWLINE@85..86 "\n" [] []
     5: MD_HEADER@86..107
-      0: MD_HASH_LIST@86..88
+      0: MD_INDENT_TOKEN_LIST@86..86
+      1: MD_HASH_LIST@86..88
         0: MD_HASH@86..88
           0: HASH@86..88 "##" [] []
-      1: MD_PARAGRAPH@88..107
+      2: MD_PARAGRAPH@88..107
         0: MD_INLINE_ITEM_LIST@88..107
           0: MD_TEXTUAL@88..107
             0: MD_TEXTUAL_LITERAL@88..107 " Period in Tag Name" [] []
         1: (empty)
-      2: MD_HASH_LIST@107..107
+      3: MD_HASH_LIST@107..107
     6: MD_NEWLINE@107..108
       0: NEWLINE@107..108 "\n" [] []
     7: MD_PARAGRAPH@108..196
@@ -497,15 +503,16 @@ MdDocument {
     8: MD_NEWLINE@196..197
       0: NEWLINE@196..197 "\n" [] []
     9: MD_HEADER@197..213
-      0: MD_HASH_LIST@197..199
+      0: MD_INDENT_TOKEN_LIST@197..197
+      1: MD_HASH_LIST@197..199
         0: MD_HASH@197..199
           0: HASH@197..199 "##" [] []
-      1: MD_PARAGRAPH@199..213
+      2: MD_PARAGRAPH@199..213
         0: MD_INLINE_ITEM_LIST@199..213
           0: MD_TEXTUAL@199..213
             0: MD_TEXTUAL_LITERAL@199..213 " Unclosed Tags" [] []
         1: (empty)
-      2: MD_HASH_LIST@213..213
+      3: MD_HASH_LIST@213..213
     10: MD_NEWLINE@213..214
       0: NEWLINE@213..214 "\n" [] []
     11: MD_PARAGRAPH@214..506
@@ -600,15 +607,16 @@ MdDocument {
     12: MD_NEWLINE@506..507
       0: NEWLINE@506..507 "\n" [] []
     13: MD_HEADER@507..526
-      0: MD_HASH_LIST@507..509
+      0: MD_INDENT_TOKEN_LIST@507..507
+      1: MD_HASH_LIST@507..509
         0: MD_HASH@507..509
           0: HASH@507..509 "##" [] []
-      1: MD_PARAGRAPH@509..526
+      2: MD_PARAGRAPH@509..526
         0: MD_INLINE_ITEM_LIST@509..526
           0: MD_TEXTUAL@509..526
             0: MD_TEXTUAL_LITERAL@509..526 " Invalid Comments" [] []
         1: (empty)
-      2: MD_HASH_LIST@526..526
+      3: MD_HASH_LIST@526..526
     14: MD_NEWLINE@526..527
       0: NEWLINE@526..527 "\n" [] []
     15: MD_PARAGRAPH@527..658
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/lazy_continuation.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/lazy_continuation.md.snap
index 433b613aeca8..783104e3563d 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/lazy_continuation.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/lazy_continuation.md.snap
@@ -178,6 +178,7 @@ MdDocument {
             ],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@205..206 "#" [] [],
@@ -313,6 +314,7 @@ MdDocument {
             ],
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@410..413 "```" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -326,6 +328,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@424..425 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@425..428 "```" [] [],
         },
         MdNewline {
@@ -388,8 +391,20 @@ MdDocument {
                         MdTextual {
                             value_token: MD_TEXTUAL_LITERAL@509..510 "\n" [] [],
                         },
+                        MdIndentToken {
+                            md_indent_char_token: MD_INDENT_CHAR@510..511 " " [] [],
+                        },
+                        MdIndentToken {
+                            md_indent_char_token: MD_INDENT_CHAR@511..512 " " [] [],
+                        },
+                        MdIndentToken {
+                            md_indent_char_token: MD_INDENT_CHAR@512..513 " " [] [],
+                        },
+                        MdIndentToken {
+                            md_indent_char_token: MD_INDENT_CHAR@513..514 " " [] [],
+                        },
                         MdTextual {
-                            value_token: MD_TEXTUAL_LITERAL@510..544 "This is an indented code block" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                            value_token: MD_TEXTUAL_LITERAL@514..544 "This is an indented code block" [] [],
                         },
                         MdTextual {
                             value_token: MD_TEXTUAL_LITERAL@544..545 "\n" [] [],
@@ -497,15 +512,16 @@ MdDocument {
               0: MD_TEXTUAL_LITERAL@204..205 "\n" [] []
           1: (empty)
     7: MD_HEADER@205..246
-      0: MD_HASH_LIST@205..206
+      0: MD_INDENT_TOKEN_LIST@205..205
+      1: MD_HASH_LIST@205..206
         0: MD_HASH@205..206
           0: HASH@205..206 "#" [] []
-      1: MD_PARAGRAPH@206..246
+      2: MD_PARAGRAPH@206..246
         0: MD_INLINE_ITEM_LIST@206..246
           0: MD_TEXTUAL@206..246
             0: MD_TEXTUAL_LITERAL@206..246 " This heading ends the lazy continuation" [] []
         1: (empty)
-      2: MD_HASH_LIST@246..246
+      3: MD_HASH_LIST@246..246
     8: MD_NEWLINE@246..247
       0: NEWLINE@246..247 "\n" [] []
     9: MD_NEWLINE@247..248
@@ -584,16 +600,18 @@ MdDocument {
               0: MD_TEXTUAL_LITERAL@409..410 "\n" [] []
           1: (empty)
     18: MD_FENCED_CODE_BLOCK@410..428
-      0: TRIPLE_BACKTICK@410..413 "```" [] []
-      1: MD_CODE_NAME_LIST@413..413
-      2: MD_INLINE_ITEM_LIST@413..425
+      0: MD_INDENT_TOKEN_LIST@410..410
+      1: TRIPLE_BACKTICK@410..413 "```" [] []
+      2: MD_CODE_NAME_LIST@413..413
+      3: MD_INLINE_ITEM_LIST@413..425
         0: MD_TEXTUAL@413..414
           0: MD_TEXTUAL_LITERAL@413..414 "\n" [] []
         1: MD_TEXTUAL@414..424
           0: MD_TEXTUAL_LITERAL@414..424 "code block" [] []
         2: MD_TEXTUAL@424..425
           0: MD_TEXTUAL_LITERAL@424..425 "\n" [] []
-      3: TRIPLE_BACKTICK@425..428 "```" [] []
+      4: MD_INDENT_TOKEN_LIST@425..425
+      5: TRIPLE_BACKTICK@425..428 "```" [] []
     19: MD_NEWLINE@428..429
       0: NEWLINE@428..429 "\n" [] []
     20: MD_NEWLINE@429..430
@@ -635,9 +653,17 @@ MdDocument {
               0: MD_TEXTUAL_LITERAL@475..509 "Quote interrupted by indented code" [] []
             1: MD_TEXTUAL@509..510
               0: MD_TEXTUAL_LITERAL@509..510 "\n" [] []
-            2: MD_TEXTUAL@510..544
-              0: MD_TEXTUAL_LITERAL@510..544 "This is an indented code block" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-            3: MD_TEXTUAL@544..545
+            2: MD_INDENT_TOKEN@510..511
+              0: MD_INDENT_CHAR@510..511 " " [] []
+            3: MD_INDENT_TOKEN@511..512
+              0: MD_INDENT_CHAR@511..512 " " [] []
+            4: MD_INDENT_TOKEN@512..513
+              0: MD_INDENT_CHAR@512..513 " " [] []
+            5: MD_INDENT_TOKEN@513..514
+              0: MD_INDENT_CHAR@513..514 " " [] []
+            6: MD_TEXTUAL@514..544
+              0: MD_TEXTUAL_LITERAL@514..544 "This is an indented code block" [] []
+            7: MD_TEXTUAL@544..545
               0: MD_TEXTUAL_LITERAL@544..545 "\n" [] []
           1: (empty)
   2: EOF@545..545 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/link_definition.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/link_definition.md.snap
index 2cc6a441b2a8..08853cdaf4a5 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/link_definition.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/link_definition.md.snap
@@ -26,6 +26,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@0..1 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -55,6 +56,7 @@ MdDocument {
             value_token: NEWLINE@31..32 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@32..33 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -84,7 +86,12 @@ MdDocument {
             value_token: NEWLINE@44..45 "\n" [] [],
         },
         MdLinkReferenceDefinition {
-            l_brack_token: L_BRACK@45..47 "[" [Skipped(" ")] [],
+            indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@45..46 " " [] [],
+                },
+            ],
+            l_brack_token: L_BRACK@46..47 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
                     MdTextual {
@@ -119,7 +126,15 @@ MdDocument {
             value_token: NEWLINE@64..65 "\n" [] [],
         },
         MdLinkReferenceDefinition {
-            l_brack_token: L_BRACK@65..68 "[" [Skipped(" "), Skipped(" ")] [],
+            indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@65..66 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@66..67 " " [] [],
+                },
+            ],
+            l_brack_token: L_BRACK@67..68 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
                     MdTextual {
@@ -154,7 +169,18 @@ MdDocument {
             value_token: NEWLINE@86..87 "\n" [] [],
         },
         MdLinkReferenceDefinition {
-            l_brack_token: L_BRACK@87..91 "[" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+            indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@87..88 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@88..89 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@89..90 " " [] [],
+                },
+            ],
+            l_brack_token: L_BRACK@90..91 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
                     MdTextual {
@@ -197,46 +223,51 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..111
     0: MD_LINK_REFERENCE_DEFINITION@0..30
-      0: L_BRACK@0..1 "[" [] []
-      1: MD_LINK_LABEL@1..8
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: L_BRACK@0..1 "[" [] []
+      2: MD_LINK_LABEL@1..8
         0: MD_INLINE_ITEM_LIST@1..8
           0: MD_TEXTUAL@1..8
             0: MD_TEXTUAL_LITERAL@1..8 "example" [] []
-      2: R_BRACK@8..9 "]" [] []
-      3: COLON@9..10 ":" [] []
-      4: MD_LINK_DESTINATION@10..30
+      3: R_BRACK@8..9 "]" [] []
+      4: COLON@9..10 ":" [] []
+      5: MD_LINK_DESTINATION@10..30
         0: MD_INLINE_ITEM_LIST@10..30
           0: MD_TEXTUAL@10..11
             0: MD_TEXTUAL_LITERAL@10..11 " " [] []
           1: MD_TEXTUAL@11..30
             0: MD_TEXTUAL_LITERAL@11..30 "https://example.com" [] []
-      5: (empty)
+      6: (empty)
     1: MD_NEWLINE@30..31
       0: NEWLINE@30..31 "\n" [] []
     2: MD_NEWLINE@31..32
       0: NEWLINE@31..32 "\n" [] []
     3: MD_LINK_REFERENCE_DEFINITION@32..43
-      0: L_BRACK@32..33 "[" [] []
-      1: MD_LINK_LABEL@33..36
+      0: MD_INDENT_TOKEN_LIST@32..32
+      1: L_BRACK@32..33 "[" [] []
+      2: MD_LINK_LABEL@33..36
         0: MD_INLINE_ITEM_LIST@33..36
           0: MD_TEXTUAL@33..36
             0: MD_TEXTUAL_LITERAL@33..36 "foo" [] []
-      2: R_BRACK@36..37 "]" [] []
-      3: COLON@37..38 ":" [] []
-      4: MD_LINK_DESTINATION@38..43
+      3: R_BRACK@36..37 "]" [] []
+      4: COLON@37..38 ":" [] []
+      5: MD_LINK_DESTINATION@38..43
         0: MD_INLINE_ITEM_LIST@38..43
           0: MD_TEXTUAL@38..39
             0: MD_TEXTUAL_LITERAL@38..39 " " [] []
           1: MD_TEXTUAL@39..43
             0: MD_TEXTUAL_LITERAL@39..43 "/url" [] []
-      5: (empty)
+      6: (empty)
     4: MD_NEWLINE@43..44
       0: NEWLINE@43..44 "\n" [] []
     5: MD_NEWLINE@44..45
       0: NEWLINE@44..45 "\n" [] []
     6: MD_LINK_REFERENCE_DEFINITION@45..63
-      0: L_BRACK@45..47 "[" [Skipped(" ")] []
-      1: MD_LINK_LABEL@47..56
+      0: MD_INDENT_TOKEN_LIST@45..46
+        0: MD_INDENT_TOKEN@45..46
+          0: MD_INDENT_CHAR@45..46 " " [] []
+      1: L_BRACK@46..47 "[" [] []
+      2: MD_LINK_LABEL@47..56
         0: MD_INLINE_ITEM_LIST@47..56
           0: MD_TEXTUAL@47..50
             0: MD_TEXTUAL_LITERAL@47..50 "one" [] []
@@ -244,22 +275,27 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@50..51 "-" [] []
           2: MD_TEXTUAL@51..56
             0: MD_TEXTUAL_LITERAL@51..56 "space" [] []
-      2: R_BRACK@56..57 "]" [] []
-      3: COLON@57..58 ":" [] []
-      4: MD_LINK_DESTINATION@58..63
+      3: R_BRACK@56..57 "]" [] []
+      4: COLON@57..58 ":" [] []
+      5: MD_LINK_DESTINATION@58..63
         0: MD_INLINE_ITEM_LIST@58..63
           0: MD_TEXTUAL@58..59
             0: MD_TEXTUAL_LITERAL@58..59 " " [] []
           1: MD_TEXTUAL@59..63
             0: MD_TEXTUAL_LITERAL@59..63 "/url" [] []
-      5: (empty)
+      6: (empty)
     7: MD_NEWLINE@63..64
       0: NEWLINE@63..64 "\n" [] []
     8: MD_NEWLINE@64..65
       0: NEWLINE@64..65 "\n" [] []
     9: MD_LINK_REFERENCE_DEFINITION@65..85
-      0: L_BRACK@65..68 "[" [Skipped(" "), Skipped(" ")] []
-      1: MD_LINK_LABEL@68..78
+      0: MD_INDENT_TOKEN_LIST@65..67
+        0: MD_INDENT_TOKEN@65..66
+          0: MD_INDENT_CHAR@65..66 " " [] []
+        1: MD_INDENT_TOKEN@66..67
+          0: MD_INDENT_CHAR@66..67 " " [] []
+      1: L_BRACK@67..68 "[" [] []
+      2: MD_LINK_LABEL@68..78
         0: MD_INLINE_ITEM_LIST@68..78
           0: MD_TEXTUAL@68..71
             0: MD_TEXTUAL_LITERAL@68..71 "two" [] []
@@ -267,22 +303,29 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@71..72 "-" [] []
           2: MD_TEXTUAL@72..78
             0: MD_TEXTUAL_LITERAL@72..78 "spaces" [] []
-      2: R_BRACK@78..79 "]" [] []
-      3: COLON@79..80 ":" [] []
-      4: MD_LINK_DESTINATION@80..85
+      3: R_BRACK@78..79 "]" [] []
+      4: COLON@79..80 ":" [] []
+      5: MD_LINK_DESTINATION@80..85
         0: MD_INLINE_ITEM_LIST@80..85
           0: MD_TEXTUAL@80..81
             0: MD_TEXTUAL_LITERAL@80..81 " " [] []
           1: MD_TEXTUAL@81..85
             0: MD_TEXTUAL_LITERAL@81..85 "/url" [] []
-      5: (empty)
+      6: (empty)
     10: MD_NEWLINE@85..86
       0: NEWLINE@85..86 "\n" [] []
     11: MD_NEWLINE@86..87
       0: NEWLINE@86..87 "\n" [] []
     12: MD_LINK_REFERENCE_DEFINITION@87..110
-      0: L_BRACK@87..91 "[" [Skipped(" "), Skipped(" "), Skipped(" ")] []
-      1: MD_LINK_LABEL@91..103
+      0: MD_INDENT_TOKEN_LIST@87..90
+        0: MD_INDENT_TOKEN@87..88
+          0: MD_INDENT_CHAR@87..88 " " [] []
+        1: MD_INDENT_TOKEN@88..89
+          0: MD_INDENT_CHAR@88..89 " " [] []
+        2: MD_INDENT_TOKEN@89..90
+          0: MD_INDENT_CHAR@89..90 " " [] []
+      1: L_BRACK@90..91 "[" [] []
+      2: MD_LINK_LABEL@91..103
         0: MD_INLINE_ITEM_LIST@91..103
           0: MD_TEXTUAL@91..96
             0: MD_TEXTUAL_LITERAL@91..96 "three" [] []
@@ -290,15 +333,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@96..97 "-" [] []
           2: MD_TEXTUAL@97..103
             0: MD_TEXTUAL_LITERAL@97..103 "spaces" [] []
-      2: R_BRACK@103..104 "]" [] []
-      3: COLON@104..105 ":" [] []
-      4: MD_LINK_DESTINATION@105..110
+      3: R_BRACK@103..104 "]" [] []
+      4: COLON@104..105 ":" [] []
+      5: MD_LINK_DESTINATION@105..110
         0: MD_INLINE_ITEM_LIST@105..110
           0: MD_TEXTUAL@105..106
             0: MD_TEXTUAL_LITERAL@105..106 " " [] []
           1: MD_TEXTUAL@106..110
             0: MD_TEXTUAL_LITERAL@106..110 "/url" [] []
-      5: (empty)
+      6: (empty)
     13: MD_NEWLINE@110..111
       0: NEWLINE@110..111 "\n" [] []
   2: EOF@111..111 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/link_definition_edge_cases.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/link_definition_edge_cases.md.snap
index c1d0f90e6c95..2eb68ddaaf2b 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/link_definition_edge_cases.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/link_definition_edge_cases.md.snap
@@ -63,7 +63,15 @@ MdDocument {
             value_token: NEWLINE@31..32 "\n" [] [],
         },
         MdLinkReferenceDefinition {
-            l_brack_token: L_BRACK@32..35 "[" [Skipped(" "), Skipped(" ")] [],
+            indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@32..33 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@33..34 " " [] [],
+                },
+            ],
+            l_brack_token: L_BRACK@34..35 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
                     MdTextual {
@@ -112,7 +120,15 @@ MdDocument {
             value_token: NEWLINE@76..77 "\n" [] [],
         },
         MdLinkReferenceDefinition {
-            l_brack_token: L_BRACK@77..80 "[" [Skipped(" "), Skipped(" ")] [],
+            indent: MdIndentTokenList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@77..78 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@78..79 " " [] [],
+                },
+            ],
+            l_brack_token: L_BRACK@79..80 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
                     MdTextual {
@@ -147,6 +163,7 @@ MdDocument {
             value_token: NEWLINE@101..102 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@102..103 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -176,6 +193,7 @@ MdDocument {
             value_token: NEWLINE@117..118 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@118..119 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -214,6 +232,7 @@ MdDocument {
             value_token: NEWLINE@151..152 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@152..153 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -267,6 +286,7 @@ MdDocument {
             value_token: NEWLINE@199..200 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@200..201 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -320,6 +340,7 @@ MdDocument {
             value_token: NEWLINE@244..245 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@245..246 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -373,6 +394,7 @@ MdDocument {
             value_token: NEWLINE@282..283 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@283..284 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -420,6 +442,7 @@ MdDocument {
             value_token: NEWLINE@338..339 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@339..340 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -479,6 +502,7 @@ MdDocument {
             value_token: NEWLINE@385..386 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@386..387 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -514,6 +538,7 @@ MdDocument {
             value_token: NEWLINE@411..412 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@412..413 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -557,6 +582,7 @@ MdDocument {
             value_token: NEWLINE@439..440 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@440..441 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -668,8 +694,13 @@ MdDocument {
     1: MD_NEWLINE@31..32
       0: NEWLINE@31..32 "\n" [] []
     2: MD_LINK_REFERENCE_DEFINITION@32..56
-      0: L_BRACK@32..35 "[" [Skipped(" "), Skipped(" ")] []
-      1: MD_LINK_LABEL@35..49
+      0: MD_INDENT_TOKEN_LIST@32..34
+        0: MD_INDENT_TOKEN@32..33
+          0: MD_INDENT_CHAR@32..33 " " [] []
+        1: MD_INDENT_TOKEN@33..34
+          0: MD_INDENT_CHAR@33..34 " " [] []
+      1: L_BRACK@34..35 "[" [] []
+      2: MD_LINK_LABEL@35..49
         0: MD_INLINE_ITEM_LIST@35..49
           0: MD_TEXTUAL@35..40
             0: MD_TEXTUAL_LITERAL@35..40 "after" [] []
@@ -677,15 +708,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@40..41 "-" [] []
           2: MD_TEXTUAL@41..49
             0: MD_TEXTUAL_LITERAL@41..49 "trailing" [] []
-      2: R_BRACK@49..50 "]" [] []
-      3: COLON@50..51 ":" [] []
-      4: MD_LINK_DESTINATION@51..56
+      3: R_BRACK@49..50 "]" [] []
+      4: COLON@50..51 ":" [] []
+      5: MD_LINK_DESTINATION@51..56
         0: MD_INLINE_ITEM_LIST@51..56
           0: MD_TEXTUAL@51..52
             0: MD_TEXTUAL_LITERAL@51..52 " " [] []
           1: MD_TEXTUAL@52..56
             0: MD_TEXTUAL_LITERAL@52..56 "/url" [] []
-      5: (empty)
+      6: (empty)
     3: MD_NEWLINE@56..57
       0: NEWLINE@56..57 "\n" [] []
     4: MD_NEWLINE@57..58
@@ -700,8 +731,13 @@ MdDocument {
     6: MD_NEWLINE@76..77
       0: NEWLINE@76..77 "\n" [] []
     7: MD_LINK_REFERENCE_DEFINITION@77..100
-      0: L_BRACK@77..80 "[" [Skipped(" "), Skipped(" ")] []
-      1: MD_LINK_LABEL@80..93
+      0: MD_INDENT_TOKEN_LIST@77..79
+        0: MD_INDENT_TOKEN@77..78
+          0: MD_INDENT_CHAR@77..78 " " [] []
+        1: MD_INDENT_TOKEN@78..79
+          0: MD_INDENT_CHAR@78..79 " " [] []
+      1: L_BRACK@79..80 "[" [] []
+      2: MD_LINK_LABEL@80..93
         0: MD_INLINE_ITEM_LIST@80..93
           0: MD_TEXTUAL@80..86
             0: MD_TEXTUAL_LITERAL@80..86 "normal" [] []
@@ -709,53 +745,55 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@86..87 "-" [] []
           2: MD_TEXTUAL@87..93
             0: MD_TEXTUAL_LITERAL@87..93 "indent" [] []
-      2: R_BRACK@93..94 "]" [] []
-      3: COLON@94..95 ":" [] []
-      4: MD_LINK_DESTINATION@95..100
+      3: R_BRACK@93..94 "]" [] []
+      4: COLON@94..95 ":" [] []
+      5: MD_LINK_DESTINATION@95..100
         0: MD_INLINE_ITEM_LIST@95..100
           0: MD_TEXTUAL@95..96
             0: MD_TEXTUAL_LITERAL@95..96 " " [] []
           1: MD_TEXTUAL@96..100
             0: MD_TEXTUAL_LITERAL@96..100 "/url" [] []
-      5: (empty)
+      6: (empty)
     8: MD_NEWLINE@100..101
       0: NEWLINE@100..101 "\n" [] []
     9: MD_NEWLINE@101..102
       0: NEWLINE@101..102 "\n" [] []
     10: MD_LINK_REFERENCE_DEFINITION@102..116
-      0: L_BRACK@102..103 "[" [] []
-      1: MD_LINK_LABEL@103..109
+      0: MD_INDENT_TOKEN_LIST@102..102
+      1: L_BRACK@102..103 "[" [] []
+      2: MD_LINK_LABEL@103..109
         0: MD_INLINE_ITEM_LIST@103..109
           0: MD_TEXTUAL@103..109
             0: MD_TEXTUAL_LITERAL@103..109 "lambda" [] []
-      2: R_BRACK@109..110 "]" [] []
-      3: COLON@110..111 ":" [] []
-      4: MD_LINK_DESTINATION@111..116
+      3: R_BRACK@109..110 "]" [] []
+      4: COLON@110..111 ":" [] []
+      5: MD_LINK_DESTINATION@111..116
         0: MD_INLINE_ITEM_LIST@111..116
           0: MD_TEXTUAL@111..112
             0: MD_TEXTUAL_LITERAL@111..112 " " [] []
           1: MD_TEXTUAL@112..116
             0: MD_TEXTUAL_LITERAL@112..116 "/url" [] []
-      5: (empty)
+      6: (empty)
     11: MD_NEWLINE@116..117
       0: NEWLINE@116..117 "\n" [] []
     12: MD_NEWLINE@117..118
       0: NEWLINE@117..118 "\n" [] []
     13: MD_LINK_REFERENCE_DEFINITION@118..150
-      0: L_BRACK@118..119 "[" [] []
-      1: MD_LINK_LABEL@119..126
+      0: MD_INDENT_TOKEN_LIST@118..118
+      1: L_BRACK@118..119 "[" [] []
+      2: MD_LINK_LABEL@119..126
         0: MD_INLINE_ITEM_LIST@119..126
           0: MD_TEXTUAL@119..126
             0: MD_TEXTUAL_LITERAL@119..126 "nihongo" [] []
-      2: R_BRACK@126..127 "]" [] []
-      3: COLON@127..128 ":" [] []
-      4: MD_LINK_DESTINATION@128..133
+      3: R_BRACK@126..127 "]" [] []
+      4: COLON@127..128 ":" [] []
+      5: MD_LINK_DESTINATION@128..133
         0: MD_INLINE_ITEM_LIST@128..133
           0: MD_TEXTUAL@128..129
             0: MD_TEXTUAL_LITERAL@128..129 " " [] []
           1: MD_TEXTUAL@129..133
             0: MD_TEXTUAL_LITERAL@129..133 "/url" [] []
-      5: MD_LINK_TITLE@133..150
+      6: MD_LINK_TITLE@133..150
         0: MD_INLINE_ITEM_LIST@133..150
           0: MD_TEXTUAL@133..134
             0: MD_TEXTUAL_LITERAL@133..134 " " [] []
@@ -766,8 +804,9 @@ MdDocument {
     15: MD_NEWLINE@151..152
       0: NEWLINE@151..152 "\n" [] []
     16: MD_LINK_REFERENCE_DEFINITION@152..198
-      0: L_BRACK@152..153 "[" [] []
-      1: MD_LINK_LABEL@153..168
+      0: MD_INDENT_TOKEN_LIST@152..152
+      1: L_BRACK@152..153 "[" [] []
+      2: MD_LINK_LABEL@153..168
         0: MD_INLINE_ITEM_LIST@153..168
           0: MD_TEXTUAL@153..158
             0: MD_TEXTUAL_LITERAL@153..158 "title" [] []
@@ -779,15 +818,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@163..164 "-" [] []
           4: MD_TEXTUAL@164..168
             0: MD_TEXTUAL_LITERAL@164..168 "line" [] []
-      2: R_BRACK@168..169 "]" [] []
-      3: COLON@169..170 ":" [] []
-      4: MD_LINK_DESTINATION@170..175
+      3: R_BRACK@168..169 "]" [] []
+      4: COLON@169..170 ":" [] []
+      5: MD_LINK_DESTINATION@170..175
         0: MD_INLINE_ITEM_LIST@170..175
           0: MD_TEXTUAL@170..171
             0: MD_TEXTUAL_LITERAL@170..171 " " [] []
           1: MD_TEXTUAL@171..175
             0: MD_TEXTUAL_LITERAL@171..175 "/url" [] []
-      5: MD_LINK_TITLE@175..198
+      6: MD_LINK_TITLE@175..198
         0: MD_INLINE_ITEM_LIST@175..198
           0: MD_TEXTUAL@175..176
             0: MD_TEXTUAL_LITERAL@175..176 "\n" [] []
@@ -800,8 +839,9 @@ MdDocument {
     18: MD_NEWLINE@199..200
       0: NEWLINE@199..200 "\n" [] []
     19: MD_LINK_REFERENCE_DEFINITION@200..243
-      0: L_BRACK@200..201 "[" [] []
-      1: MD_LINK_LABEL@201..218
+      0: MD_INDENT_TOKEN_LIST@200..200
+      1: L_BRACK@200..201 "[" [] []
+      2: MD_LINK_LABEL@201..218
         0: MD_INLINE_ITEM_LIST@201..218
           0: MD_TEXTUAL@201..207
             0: MD_TEXTUAL_LITERAL@201..207 "single" [] []
@@ -813,15 +853,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@213..214 "-" [] []
           4: MD_TEXTUAL@214..218
             0: MD_TEXTUAL_LITERAL@214..218 "next" [] []
-      2: R_BRACK@218..219 "]" [] []
-      3: COLON@219..220 ":" [] []
-      4: MD_LINK_DESTINATION@220..225
+      3: R_BRACK@218..219 "]" [] []
+      4: COLON@219..220 ":" [] []
+      5: MD_LINK_DESTINATION@220..225
         0: MD_INLINE_ITEM_LIST@220..225
           0: MD_TEXTUAL@220..221
             0: MD_TEXTUAL_LITERAL@220..221 " " [] []
           1: MD_TEXTUAL@221..225
             0: MD_TEXTUAL_LITERAL@221..225 "/url" [] []
-      5: MD_LINK_TITLE@225..243
+      6: MD_LINK_TITLE@225..243
         0: MD_INLINE_ITEM_LIST@225..243
           0: MD_TEXTUAL@225..226
             0: MD_TEXTUAL_LITERAL@225..226 "\n" [] []
@@ -834,8 +874,9 @@ MdDocument {
     21: MD_NEWLINE@244..245
       0: NEWLINE@244..245 "\n" [] []
     22: MD_LINK_REFERENCE_DEFINITION@245..281
-      0: L_BRACK@245..246 "[" [] []
-      1: MD_LINK_LABEL@246..256
+      0: MD_INDENT_TOKEN_LIST@245..245
+      1: L_BRACK@245..246 "[" [] []
+      2: MD_LINK_LABEL@246..256
         0: MD_INLINE_ITEM_LIST@246..256
           0: MD_TEXTUAL@246..251
             0: MD_TEXTUAL_LITERAL@246..251 "paren" [] []
@@ -843,15 +884,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@251..252 "-" [] []
           2: MD_TEXTUAL@252..256
             0: MD_TEXTUAL_LITERAL@252..256 "next" [] []
-      2: R_BRACK@256..257 "]" [] []
-      3: COLON@257..258 ":" [] []
-      4: MD_LINK_DESTINATION@258..263
+      3: R_BRACK@256..257 "]" [] []
+      4: COLON@257..258 ":" [] []
+      5: MD_LINK_DESTINATION@258..263
         0: MD_INLINE_ITEM_LIST@258..263
           0: MD_TEXTUAL@258..259
             0: MD_TEXTUAL_LITERAL@258..259 " " [] []
           1: MD_TEXTUAL@259..263
             0: MD_TEXTUAL_LITERAL@259..263 "/url" [] []
-      5: MD_LINK_TITLE@263..281
+      6: MD_LINK_TITLE@263..281
         0: MD_INLINE_ITEM_LIST@263..281
           0: MD_TEXTUAL@263..264
             0: MD_TEXTUAL_LITERAL@263..264 "\n" [] []
@@ -868,8 +909,9 @@ MdDocument {
     24: MD_NEWLINE@282..283
       0: NEWLINE@282..283 "\n" [] []
     25: MD_LINK_REFERENCE_DEFINITION@283..337
-      0: L_BRACK@283..284 "[" [] []
-      1: MD_LINK_LABEL@284..299
+      0: MD_INDENT_TOKEN_LIST@283..283
+      1: L_BRACK@283..284 "[" [] []
+      2: MD_LINK_LABEL@284..299
         0: MD_INLINE_ITEM_LIST@284..299
           0: MD_TEXTUAL@284..292
             0: MD_TEXTUAL_LITERAL@284..292 "balanced" [] []
@@ -877,9 +919,9 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@292..293 "-" [] []
           2: MD_TEXTUAL@293..299
             0: MD_TEXTUAL_LITERAL@293..299 "parens" [] []
-      2: R_BRACK@299..300 "]" [] []
-      3: COLON@300..301 ":" [] []
-      4: MD_LINK_DESTINATION@301..337
+      3: R_BRACK@299..300 "]" [] []
+      4: COLON@300..301 ":" [] []
+      5: MD_LINK_DESTINATION@301..337
         0: MD_INLINE_ITEM_LIST@301..337
           0: MD_TEXTUAL@301..302
             0: MD_TEXTUAL_LITERAL@301..302 " " [] []
@@ -893,14 +935,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@330..331 ")" [] []
           5: MD_TEXTUAL@331..337
             0: MD_TEXTUAL_LITERAL@331..337 "parens" [] []
-      5: (empty)
+      6: (empty)
     26: MD_NEWLINE@337..338
       0: NEWLINE@337..338 "\n" [] []
     27: MD_NEWLINE@338..339
       0: NEWLINE@338..339 "\n" [] []
     28: MD_LINK_REFERENCE_DEFINITION@339..384
-      0: L_BRACK@339..340 "[" [] []
-      1: MD_LINK_LABEL@340..353
+      0: MD_INDENT_TOKEN_LIST@339..339
+      1: L_BRACK@339..340 "[" [] []
+      2: MD_LINK_LABEL@340..353
         0: MD_INLINE_ITEM_LIST@340..353
           0: MD_TEXTUAL@340..346
             0: MD_TEXTUAL_LITERAL@340..346 "nested" [] []
@@ -908,9 +951,9 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@346..347 "-" [] []
           2: MD_TEXTUAL@347..353
             0: MD_TEXTUAL_LITERAL@347..353 "parens" [] []
-      2: R_BRACK@353..354 "]" [] []
-      3: COLON@354..355 ":" [] []
-      4: MD_LINK_DESTINATION@355..384
+      3: R_BRACK@353..354 "]" [] []
+      4: COLON@354..355 ":" [] []
+      5: MD_LINK_DESTINATION@355..384
         0: MD_INLINE_ITEM_LIST@355..384
           0: MD_TEXTUAL@355..356
             0: MD_TEXTUAL_LITERAL@355..356 " " [] []
@@ -932,14 +975,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@382..383 ")" [] []
           9: MD_TEXTUAL@383..384
             0: MD_TEXTUAL_LITERAL@383..384 "e" [] []
-      5: (empty)
+      6: (empty)
     29: MD_NEWLINE@384..385
       0: NEWLINE@384..385 "\n" [] []
     30: MD_NEWLINE@385..386
       0: NEWLINE@385..386 "\n" [] []
     31: MD_LINK_REFERENCE_DEFINITION@386..410
-      0: L_BRACK@386..387 "[" [] []
-      1: MD_LINK_LABEL@387..403
+      0: MD_INDENT_TOKEN_LIST@386..386
+      1: L_BRACK@386..387 "[" [] []
+      2: MD_LINK_LABEL@387..403
         0: MD_INLINE_ITEM_LIST@387..403
           0: MD_TEXTUAL@387..394
             0: MD_TEXTUAL_LITERAL@387..394 "escaped" [] []
@@ -947,22 +991,23 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@394..396 "\\]" [] []
           2: MD_TEXTUAL@396..403
             0: MD_TEXTUAL_LITERAL@396..403 "bracket" [] []
-      2: R_BRACK@403..404 "]" [] []
-      3: COLON@404..405 ":" [] []
-      4: MD_LINK_DESTINATION@405..410
+      3: R_BRACK@403..404 "]" [] []
+      4: COLON@404..405 ":" [] []
+      5: MD_LINK_DESTINATION@405..410
         0: MD_INLINE_ITEM_LIST@405..410
           0: MD_TEXTUAL@405..406
             0: MD_TEXTUAL_LITERAL@405..406 " " [] []
           1: MD_TEXTUAL@406..410
             0: MD_TEXTUAL_LITERAL@406..410 "/url" [] []
-      5: (empty)
+      6: (empty)
     32: MD_NEWLINE@410..411
       0: NEWLINE@410..411 "\n" [] []
     33: MD_NEWLINE@411..412
       0: NEWLINE@411..412 "\n" [] []
     34: MD_LINK_REFERENCE_DEFINITION@412..435
-      0: L_BRACK@412..413 "[" [] []
-      1: MD_LINK_LABEL@413..428
+      0: MD_INDENT_TOKEN_LIST@412..412
+      1: L_BRACK@412..413 "[" [] []
+      2: MD_LINK_LABEL@413..428
         0: MD_INLINE_ITEM_LIST@413..428
           0: MD_TEXTUAL@413..421
             0: MD_TEXTUAL_LITERAL@413..421 "trailing" [] []
@@ -970,15 +1015,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@421..422 "-" [] []
           2: MD_TEXTUAL@422..428
             0: MD_TEXTUAL_LITERAL@422..428 "spaces" [] []
-      2: R_BRACK@428..429 "]" [] []
-      3: COLON@429..430 ":" [] []
-      4: MD_LINK_DESTINATION@430..435
+      3: R_BRACK@428..429 "]" [] []
+      4: COLON@429..430 ":" [] []
+      5: MD_LINK_DESTINATION@430..435
         0: MD_INLINE_ITEM_LIST@430..435
           0: MD_TEXTUAL@430..431
             0: MD_TEXTUAL_LITERAL@430..431 " " [] []
           1: MD_TEXTUAL@431..435
             0: MD_TEXTUAL_LITERAL@431..435 "/url" [] []
-      5: (empty)
+      6: (empty)
     35: MD_PARAGRAPH@435..439
       0: MD_INLINE_ITEM_LIST@435..439
         0: MD_TEXTUAL@435..438
@@ -989,8 +1034,9 @@ MdDocument {
     36: MD_NEWLINE@439..440
       0: NEWLINE@439..440 "\n" [] []
     37: MD_LINK_REFERENCE_DEFINITION@440..464
-      0: L_BRACK@440..441 "[" [] []
-      1: MD_LINK_LABEL@441..457
+      0: MD_INDENT_TOKEN_LIST@440..440
+      1: L_BRACK@440..441 "[" [] []
+      2: MD_LINK_LABEL@441..457
         0: MD_INLINE_ITEM_LIST@441..457
           0: MD_TEXTUAL@441..448
             0: MD_TEXTUAL_LITERAL@441..448 "invalid" [] []
@@ -998,15 +1044,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@448..449 "-" [] []
           2: MD_TEXTUAL@449..457
             0: MD_TEXTUAL_LITERAL@449..457 "trailing" [] []
-      2: R_BRACK@457..458 "]" [] []
-      3: COLON@458..459 ":" [] []
-      4: MD_LINK_DESTINATION@459..464
+      3: R_BRACK@457..458 "]" [] []
+      4: COLON@458..459 ":" [] []
+      5: MD_LINK_DESTINATION@459..464
         0: MD_INLINE_ITEM_LIST@459..464
           0: MD_TEXTUAL@459..460
             0: MD_TEXTUAL_LITERAL@459..460 " " [] []
           1: MD_TEXTUAL@460..464
             0: MD_TEXTUAL_LITERAL@460..464 "/url" [] []
-      5: (empty)
+      6: (empty)
     38: MD_PARAGRAPH@464..473
       0: MD_INLINE_ITEM_LIST@464..473
         0: MD_TEXTUAL@464..465
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md.snap
index ffae40651a3c..b0bcc1a46672 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_blank_lines_between_items.md.snap
@@ -46,6 +46,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@0..1 "#" [] [],
@@ -144,6 +145,7 @@ MdDocument {
             value_token: NEWLINE@56..57 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@57..58 "#" [] [],
@@ -242,6 +244,7 @@ MdDocument {
             value_token: NEWLINE@124..125 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@125..126 "#" [] [],
@@ -319,6 +322,7 @@ MdDocument {
             value_token: NEWLINE@180..181 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@181..182 "#" [] [],
@@ -422,15 +426,16 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..243
     0: MD_HEADER@0..34
-      0: MD_HASH_LIST@0..1
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: MD_HASH_LIST@0..1
         0: MD_HASH@0..1
           0: HASH@0..1 "#" [] []
-      1: MD_PARAGRAPH@1..34
+      2: MD_PARAGRAPH@1..34
         0: MD_INLINE_ITEM_LIST@1..34
           0: MD_TEXTUAL@1..34
             0: MD_TEXTUAL_LITERAL@1..34 " Blank lines between bullet items" [] []
         1: (empty)
-      2: MD_HASH_LIST@34..34
+      3: MD_HASH_LIST@34..34
     1: MD_NEWLINE@34..35
       0: NEWLINE@34..35 "\n" [] []
     2: MD_NEWLINE@35..36
@@ -486,15 +491,16 @@ MdDocument {
     4: MD_NEWLINE@56..57
       0: NEWLINE@56..57 "\n" [] []
     5: MD_HEADER@57..92
-      0: MD_HASH_LIST@57..58
+      0: MD_INDENT_TOKEN_LIST@57..57
+      1: MD_HASH_LIST@57..58
         0: MD_HASH@57..58
           0: HASH@57..58 "#" [] []
-      1: MD_PARAGRAPH@58..92
+      2: MD_PARAGRAPH@58..92
         0: MD_INLINE_ITEM_LIST@58..92
           0: MD_TEXTUAL@58..92
             0: MD_TEXTUAL_LITERAL@58..92 " Blank lines between ordered items" [] []
         1: (empty)
-      2: MD_HASH_LIST@92..92
+      3: MD_HASH_LIST@92..92
     6: MD_NEWLINE@92..93
       0: NEWLINE@92..93 "\n" [] []
     7: MD_NEWLINE@93..94
@@ -550,15 +556,16 @@ MdDocument {
     9: MD_NEWLINE@124..125
       0: NEWLINE@124..125 "\n" [] []
     10: MD_HEADER@125..161
-      0: MD_HASH_LIST@125..126
+      0: MD_INDENT_TOKEN_LIST@125..125
+      1: MD_HASH_LIST@125..126
         0: MD_HASH@125..126
           0: HASH@125..126 "#" [] []
-      1: MD_PARAGRAPH@126..161
+      2: MD_PARAGRAPH@126..161
         0: MD_INLINE_ITEM_LIST@126..161
           0: MD_TEXTUAL@126..161
             0: MD_TEXTUAL_LITERAL@126..161 " Multiple blank lines between items" [] []
         1: (empty)
-      2: MD_HASH_LIST@161..161
+      3: MD_HASH_LIST@161..161
     11: MD_NEWLINE@161..162
       0: NEWLINE@161..162 "\n" [] []
     12: MD_NEWLINE@162..163
@@ -600,15 +607,16 @@ MdDocument {
     14: MD_NEWLINE@180..181
       0: NEWLINE@180..181 "\n" [] []
     15: MD_HEADER@181..220
-      0: MD_HASH_LIST@181..182
+      0: MD_INDENT_TOKEN_LIST@181..181
+      1: MD_HASH_LIST@181..182
         0: MD_HASH@181..182
           0: HASH@181..182 "#" [] []
-      1: MD_PARAGRAPH@182..220
+      2: MD_PARAGRAPH@182..220
         0: MD_INLINE_ITEM_LIST@182..220
           0: MD_TEXTUAL@182..220
             0: MD_TEXTUAL_LITERAL@182..220 " Mixed: some items separated, some not" [] []
         1: (empty)
-      2: MD_HASH_LIST@220..220
+      3: MD_HASH_LIST@220..220
     16: MD_NEWLINE@220..221
       0: NEWLINE@220..221 "\n" [] []
     17: MD_NEWLINE@221..222
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_continuation_edge_cases.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_continuation_edge_cases.md.snap
index c863f8c0488a..286cfa6b53b5 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_continuation_edge_cases.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_continuation_edge_cases.md.snap
@@ -45,6 +45,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@0..1 "#" [] [],
@@ -178,6 +179,7 @@ MdDocument {
             value_token: NEWLINE@106..107 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@107..108 "#" [] [],
@@ -252,6 +254,7 @@ MdDocument {
             value_token: NEWLINE@204..205 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@205..206 "#" [] [],
@@ -318,8 +321,20 @@ MdDocument {
                                                 MdTextual {
                                                     value_token: MD_TEXTUAL_LITERAL@299..300 "\n" [] [],
                                                 },
+                                                MdIndentToken {
+                                                    md_indent_char_token: MD_INDENT_CHAR@300..301 " " [] [],
+                                                },
+                                                MdIndentToken {
+                                                    md_indent_char_token: MD_INDENT_CHAR@301..302 " " [] [],
+                                                },
+                                                MdIndentToken {
+                                                    md_indent_char_token: MD_INDENT_CHAR@302..303 " " [] [],
+                                                },
+                                                MdIndentToken {
+                                                    md_indent_char_token: MD_INDENT_CHAR@303..304 " " [] [],
+                                                },
                                                 MdTextual {
-                                                    value_token: MD_TEXTUAL_LITERAL@300..322 "inner continuation" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                                                    value_token: MD_TEXTUAL_LITERAL@304..322 "inner continuation" [] [],
                                                 },
                                                 MdTextual {
                                                     value_token: MD_TEXTUAL_LITERAL@322..323 "\n" [] [],
@@ -375,6 +390,7 @@ MdDocument {
             value_token: NEWLINE@385..386 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@386..387 "#" [] [],
@@ -466,10 +482,11 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..507
     0: MD_HEADER@0..43
-      0: MD_HASH_LIST@0..1
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: MD_HASH_LIST@0..1
         0: MD_HASH@0..1
           0: HASH@0..1 "#" [] []
-      1: MD_PARAGRAPH@1..43
+      2: MD_PARAGRAPH@1..43
         0: MD_INLINE_ITEM_LIST@1..43
           0: MD_TEXTUAL@1..3
             0: MD_TEXTUAL_LITERAL@1..3 " 1" [] []
@@ -482,7 +499,7 @@ MdDocument {
           4: MD_TEXTUAL@11..43
             0: MD_TEXTUAL_LITERAL@11..43 "only blank line inside list item" [] []
         1: (empty)
-      2: MD_HASH_LIST@43..43
+      3: MD_HASH_LIST@43..43
     1: MD_NEWLINE@43..44
       0: NEWLINE@43..44 "\n" [] []
     2: MD_NEWLINE@44..45
@@ -553,10 +570,11 @@ MdDocument {
     4: MD_NEWLINE@106..107
       0: NEWLINE@106..107 "\n" [] []
     5: MD_HEADER@107..151
-      0: MD_HASH_LIST@107..108
+      0: MD_INDENT_TOKEN_LIST@107..107
+      1: MD_HASH_LIST@107..108
         0: MD_HASH@107..108
           0: HASH@107..108 "#" [] []
-      1: MD_PARAGRAPH@108..151
+      2: MD_PARAGRAPH@108..151
         0: MD_INLINE_ITEM_LIST@108..151
           0: MD_TEXTUAL@108..110
             0: MD_TEXTUAL_LITERAL@108..110 " 2" [] []
@@ -569,7 +587,7 @@ MdDocument {
           4: MD_TEXTUAL@119..151
             0: MD_TEXTUAL_LITERAL@119..151 "only item followed by blank line" [] []
         1: (empty)
-      2: MD_HASH_LIST@151..151
+      3: MD_HASH_LIST@151..151
     6: MD_NEWLINE@151..152
       0: NEWLINE@151..152 "\n" [] []
     7: MD_NEWLINE@152..153
@@ -601,10 +619,11 @@ MdDocument {
     11: MD_NEWLINE@204..205
       0: NEWLINE@204..205 "\n" [] []
     12: MD_HEADER@205..270
-      0: MD_HASH_LIST@205..206
+      0: MD_INDENT_TOKEN_LIST@205..205
+      1: MD_HASH_LIST@205..206
         0: MD_HASH@205..206
           0: HASH@205..206 "#" [] []
-      1: MD_PARAGRAPH@206..270
+      2: MD_PARAGRAPH@206..270
         0: MD_INLINE_ITEM_LIST@206..270
           0: MD_TEXTUAL@206..208
             0: MD_TEXTUAL_LITERAL@206..208 " 3" [] []
@@ -613,7 +632,7 @@ MdDocument {
           2: MD_TEXTUAL@209..270
             0: MD_TEXTUAL_LITERAL@209..270 " Nested list with continuation requiring virtual line restore" [] []
         1: (empty)
-      2: MD_HASH_LIST@270..270
+      3: MD_HASH_LIST@270..270
     13: MD_NEWLINE@270..271
       0: NEWLINE@270..271 "\n" [] []
     14: MD_NEWLINE@271..272
@@ -649,17 +668,25 @@ MdDocument {
                           0: MD_TEXTUAL_LITERAL@288..299 " inner item" [] []
                         1: MD_TEXTUAL@299..300
                           0: MD_TEXTUAL_LITERAL@299..300 "\n" [] []
-                        2: MD_TEXTUAL@300..322
-                          0: MD_TEXTUAL_LITERAL@300..322 "inner continuation" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-                        3: MD_TEXTUAL@322..323
+                        2: MD_INDENT_TOKEN@300..301
+                          0: MD_INDENT_CHAR@300..301 " " [] []
+                        3: MD_INDENT_TOKEN@301..302
+                          0: MD_INDENT_CHAR@301..302 " " [] []
+                        4: MD_INDENT_TOKEN@302..303
+                          0: MD_INDENT_CHAR@302..303 " " [] []
+                        5: MD_INDENT_TOKEN@303..304
+                          0: MD_INDENT_CHAR@303..304 " " [] []
+                        6: MD_TEXTUAL@304..322
+                          0: MD_TEXTUAL_LITERAL@304..322 "inner continuation" [] []
+                        7: MD_TEXTUAL@322..323
                           0: MD_TEXTUAL_LITERAL@322..323 "\n" [] []
-                        4: MD_TEXTUAL@323..324
+                        8: MD_TEXTUAL@323..324
                           0: MD_TEXTUAL_LITERAL@323..324 " " [] []
-                        5: MD_TEXTUAL@324..325
+                        9: MD_TEXTUAL@324..325
                           0: MD_TEXTUAL_LITERAL@324..325 " " [] []
-                        6: MD_TEXTUAL@325..365
+                        10: MD_TEXTUAL@325..365
                           0: MD_TEXTUAL_LITERAL@325..365 "outer continuation at parent indentation" [] []
-                        7: MD_TEXTUAL@365..366
+                        11: MD_TEXTUAL@365..366
                           0: MD_TEXTUAL_LITERAL@365..366 "\n" [] []
                       1: (empty)
             2: MD_NEWLINE@366..367
@@ -681,10 +708,11 @@ MdDocument {
     16: MD_NEWLINE@385..386
       0: NEWLINE@385..386 "\n" [] []
     17: MD_HEADER@386..449
-      0: MD_HASH_LIST@386..387
+      0: MD_INDENT_TOKEN_LIST@386..386
+      1: MD_HASH_LIST@386..387
         0: MD_HASH@386..387
           0: HASH@386..387 "#" [] []
-      1: MD_PARAGRAPH@387..449
+      2: MD_PARAGRAPH@387..449
         0: MD_INLINE_ITEM_LIST@387..449
           0: MD_TEXTUAL@387..389
             0: MD_TEXTUAL_LITERAL@387..389 " 4" [] []
@@ -693,7 +721,7 @@ MdDocument {
           2: MD_TEXTUAL@390..449
             0: MD_TEXTUAL_LITERAL@390..449 " Lazy continuation with insufficient indent after paragraph" [] []
         1: (empty)
-      2: MD_HASH_LIST@449..449
+      3: MD_HASH_LIST@449..449
     18: MD_NEWLINE@449..450
       0: NEWLINE@449..450 "\n" [] []
     19: MD_NEWLINE@450..451
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_indentation.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_indentation.md.snap
index 005e790ebb66..49e9c20f0d8c 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_indentation.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_indentation.md.snap
@@ -126,8 +126,14 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@58..59 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@59..60 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@60..61 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@59..70 "continued" [Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@61..70 "continued" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@70..71 "\n" [] [],
@@ -261,8 +267,20 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@231..232 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@232..233 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@233..234 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@234..235 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@235..236 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@232..245 "continued" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@236..245 "continued" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@245..246 "\n" [] [],
@@ -396,8 +414,17 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@400..401 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@401..402 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@402..403 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@403..404 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@401..413 "continued" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@404..413 "continued" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@413..414 "\n" [] [],
@@ -534,8 +561,17 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@582..583 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@583..584 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@584..585 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@585..586 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@583..607 "continued at 3 spaces" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@586..607 "continued at 3 spaces" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@607..608 "\n" [] [],
@@ -582,8 +618,14 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@629..630 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@630..631 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@631..632 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@630..641 "continued" [Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@632..641 "continued" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@641..642 "\n" [] [],
@@ -630,8 +672,14 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@663..664 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@664..665 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@665..666 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@664..675 "continued" [Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@666..675 "continued" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@675..676 "\n" [] [],
@@ -699,8 +747,20 @@ MdDocument {
                                                 MdTextual {
                                                     value_token: MD_TEXTUAL_LITERAL@721..722 "\n" [] [],
                                                 },
+                                                MdIndentToken {
+                                                    md_indent_char_token: MD_INDENT_CHAR@722..723 " " [] [],
+                                                },
+                                                MdIndentToken {
+                                                    md_indent_char_token: MD_INDENT_CHAR@723..724 " " [] [],
+                                                },
+                                                MdIndentToken {
+                                                    md_indent_char_token: MD_INDENT_CHAR@724..725 " " [] [],
+                                                },
+                                                MdIndentToken {
+                                                    md_indent_char_token: MD_INDENT_CHAR@725..726 " " [] [],
+                                                },
                                                 MdTextual {
-                                                    value_token: MD_TEXTUAL_LITERAL@722..741 "inner continued" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                                                    value_token: MD_TEXTUAL_LITERAL@726..741 "inner continued" [] [],
                                                 },
                                                 MdTextual {
                                                     value_token: MD_TEXTUAL_LITERAL@741..742 "\n" [] [],
@@ -777,8 +837,14 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@820..821 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@821..822 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@822..823 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@821..840 "with continuation" [Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@823..840 "with continuation" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@840..841 "\n" [] [],
@@ -851,9 +917,13 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@53..58 " item" [] []
                 1: MD_TEXTUAL@58..59
                   0: MD_TEXTUAL_LITERAL@58..59 "\n" [] []
-                2: MD_TEXTUAL@59..70
-                  0: MD_TEXTUAL_LITERAL@59..70 "continued" [Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@70..71
+                2: MD_INDENT_TOKEN@59..60
+                  0: MD_INDENT_CHAR@59..60 " " [] []
+                3: MD_INDENT_TOKEN@60..61
+                  0: MD_INDENT_CHAR@60..61 " " [] []
+                4: MD_TEXTUAL@61..70
+                  0: MD_TEXTUAL_LITERAL@61..70 "continued" [] []
+                5: MD_TEXTUAL@70..71
                   0: MD_TEXTUAL_LITERAL@70..71 "\n" [] []
               1: (empty)
     3: MD_NEWLINE@71..72
@@ -939,9 +1009,17 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@226..231 " item" [] []
                 1: MD_TEXTUAL@231..232
                   0: MD_TEXTUAL_LITERAL@231..232 "\n" [] []
-                2: MD_TEXTUAL@232..245
-                  0: MD_TEXTUAL_LITERAL@232..245 "continued" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@245..246
+                2: MD_INDENT_TOKEN@232..233
+                  0: MD_INDENT_CHAR@232..233 " " [] []
+                3: MD_INDENT_TOKEN@233..234
+                  0: MD_INDENT_CHAR@233..234 " " [] []
+                4: MD_INDENT_TOKEN@234..235
+                  0: MD_INDENT_CHAR@234..235 " " [] []
+                5: MD_INDENT_TOKEN@235..236
+                  0: MD_INDENT_CHAR@235..236 " " [] []
+                6: MD_TEXTUAL@236..245
+                  0: MD_TEXTUAL_LITERAL@236..245 "continued" [] []
+                7: MD_TEXTUAL@245..246
                   0: MD_TEXTUAL_LITERAL@245..246 "\n" [] []
               1: (empty)
     11: MD_NEWLINE@246..247
@@ -1027,9 +1105,15 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@395..400 " item" [] []
                 1: MD_TEXTUAL@400..401
                   0: MD_TEXTUAL_LITERAL@400..401 "\n" [] []
-                2: MD_TEXTUAL@401..413
-                  0: MD_TEXTUAL_LITERAL@401..413 "continued" [Skipped(" "), Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@413..414
+                2: MD_INDENT_TOKEN@401..402
+                  0: MD_INDENT_CHAR@401..402 " " [] []
+                3: MD_INDENT_TOKEN@402..403
+                  0: MD_INDENT_CHAR@402..403 " " [] []
+                4: MD_INDENT_TOKEN@403..404
+                  0: MD_INDENT_CHAR@403..404 " " [] []
+                5: MD_TEXTUAL@404..413
+                  0: MD_TEXTUAL_LITERAL@404..413 "continued" [] []
+                6: MD_TEXTUAL@413..414
                   0: MD_TEXTUAL_LITERAL@413..414 "\n" [] []
               1: (empty)
     19: MD_NEWLINE@414..415
@@ -1117,9 +1201,15 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@559..582 "  item with extra space" [] []
                 1: MD_TEXTUAL@582..583
                   0: MD_TEXTUAL_LITERAL@582..583 "\n" [] []
-                2: MD_TEXTUAL@583..607
-                  0: MD_TEXTUAL_LITERAL@583..607 "continued at 3 spaces" [Skipped(" "), Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@607..608
+                2: MD_INDENT_TOKEN@583..584
+                  0: MD_INDENT_CHAR@583..584 " " [] []
+                3: MD_INDENT_TOKEN@584..585
+                  0: MD_INDENT_CHAR@584..585 " " [] []
+                4: MD_INDENT_TOKEN@585..586
+                  0: MD_INDENT_CHAR@585..586 " " [] []
+                5: MD_TEXTUAL@586..607
+                  0: MD_TEXTUAL_LITERAL@586..607 "continued at 3 spaces" [] []
+                6: MD_TEXTUAL@607..608
                   0: MD_TEXTUAL_LITERAL@607..608 "\n" [] []
               1: (empty)
     27: MD_NEWLINE@608..609
@@ -1148,9 +1238,13 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@624..629 " item" [] []
                 1: MD_TEXTUAL@629..630
                   0: MD_TEXTUAL_LITERAL@629..630 "\n" [] []
-                2: MD_TEXTUAL@630..641
-                  0: MD_TEXTUAL_LITERAL@630..641 "continued" [Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@641..642
+                2: MD_INDENT_TOKEN@630..631
+                  0: MD_INDENT_CHAR@630..631 " " [] []
+                3: MD_INDENT_TOKEN@631..632
+                  0: MD_INDENT_CHAR@631..632 " " [] []
+                4: MD_TEXTUAL@632..641
+                  0: MD_TEXTUAL_LITERAL@632..641 "continued" [] []
+                5: MD_TEXTUAL@641..642
                   0: MD_TEXTUAL_LITERAL@641..642 "\n" [] []
               1: (empty)
     31: MD_NEWLINE@642..643
@@ -1179,9 +1273,13 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@658..663 " item" [] []
                 1: MD_TEXTUAL@663..664
                   0: MD_TEXTUAL_LITERAL@663..664 "\n" [] []
-                2: MD_TEXTUAL@664..675
-                  0: MD_TEXTUAL_LITERAL@664..675 "continued" [Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@675..676
+                2: MD_INDENT_TOKEN@664..665
+                  0: MD_INDENT_CHAR@664..665 " " [] []
+                3: MD_INDENT_TOKEN@665..666
+                  0: MD_INDENT_CHAR@665..666 " " [] []
+                4: MD_TEXTUAL@666..675
+                  0: MD_TEXTUAL_LITERAL@666..675 "continued" [] []
+                5: MD_TEXTUAL@675..676
                   0: MD_TEXTUAL_LITERAL@675..676 "\n" [] []
               1: (empty)
     35: MD_NEWLINE@676..677
@@ -1226,17 +1324,25 @@ MdDocument {
                           0: MD_TEXTUAL_LITERAL@715..721 " inner" [] []
                         1: MD_TEXTUAL@721..722
                           0: MD_TEXTUAL_LITERAL@721..722 "\n" [] []
-                        2: MD_TEXTUAL@722..741
-                          0: MD_TEXTUAL_LITERAL@722..741 "inner continued" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-                        3: MD_TEXTUAL@741..742
+                        2: MD_INDENT_TOKEN@722..723
+                          0: MD_INDENT_CHAR@722..723 " " [] []
+                        3: MD_INDENT_TOKEN@723..724
+                          0: MD_INDENT_CHAR@723..724 " " [] []
+                        4: MD_INDENT_TOKEN@724..725
+                          0: MD_INDENT_CHAR@724..725 " " [] []
+                        5: MD_INDENT_TOKEN@725..726
+                          0: MD_INDENT_CHAR@725..726 " " [] []
+                        6: MD_TEXTUAL@726..741
+                          0: MD_TEXTUAL_LITERAL@726..741 "inner continued" [] []
+                        7: MD_TEXTUAL@741..742
                           0: MD_TEXTUAL_LITERAL@741..742 "\n" [] []
-                        4: MD_TEXTUAL@742..743
+                        8: MD_TEXTUAL@742..743
                           0: MD_TEXTUAL_LITERAL@742..743 " " [] []
-                        5: MD_TEXTUAL@743..744
+                        9: MD_TEXTUAL@743..744
                           0: MD_TEXTUAL_LITERAL@743..744 " " [] []
-                        6: MD_TEXTUAL@744..759
+                        10: MD_TEXTUAL@744..759
                           0: MD_TEXTUAL_LITERAL@744..759 "outer continued" [] []
-                        7: MD_TEXTUAL@759..760
+                        11: MD_TEXTUAL@759..760
                           0: MD_TEXTUAL_LITERAL@759..760 "\n" [] []
                       1: (empty)
     39: MD_NEWLINE@760..761
@@ -1274,9 +1380,13 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@810..820 " list item" [] []
                 1: MD_TEXTUAL@820..821
                   0: MD_TEXTUAL_LITERAL@820..821 "\n" [] []
-                2: MD_TEXTUAL@821..840
-                  0: MD_TEXTUAL_LITERAL@821..840 "with continuation" [Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@840..841
+                2: MD_INDENT_TOKEN@821..822
+                  0: MD_INDENT_CHAR@821..822 " " [] []
+                3: MD_INDENT_TOKEN@822..823
+                  0: MD_INDENT_CHAR@822..823 " " [] []
+                4: MD_TEXTUAL@823..840
+                  0: MD_TEXTUAL_LITERAL@823..840 "with continuation" [] []
+                5: MD_TEXTUAL@840..841
                   0: MD_TEXTUAL_LITERAL@840..841 "\n" [] []
               1: (empty)
     45: MD_NEWLINE@841..842
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_tightness.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_tightness.md.snap
index 2bef8fd4179c..1a74fe3fb5b4 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/list_tightness.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/list_tightness.md.snap
@@ -75,6 +75,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@0..1 "#" [] [],
@@ -265,6 +266,7 @@ MdDocument {
             value_token: NEWLINE@140..141 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@141..142 "#" [] [],
@@ -467,6 +469,7 @@ MdDocument {
             value_token: NEWLINE@318..319 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@319..320 "#" [] [],
@@ -544,8 +547,14 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@429..430 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@430..431 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@431..432 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@430..446 "continues here" [Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@432..446 "continues here" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@446..447 "\n" [] [],
@@ -571,8 +580,14 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@457..458 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@458..459 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@459..460 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@458..474 "also continues" [Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@460..474 "also continues" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@474..475 "\n" [] [],
@@ -588,6 +603,7 @@ MdDocument {
             value_token: NEWLINE@475..476 "\n" [] [],
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@476..477 "#" [] [],
@@ -862,15 +878,16 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..655
     0: MD_HEADER@0..13
-      0: MD_HASH_LIST@0..1
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: MD_HASH_LIST@0..1
         0: MD_HASH@0..1
           0: HASH@0..1 "#" [] []
-      1: MD_PARAGRAPH@1..13
+      2: MD_PARAGRAPH@1..13
         0: MD_INLINE_ITEM_LIST@1..13
           0: MD_TEXTUAL@1..13
             0: MD_TEXTUAL_LITERAL@1..13 " Tight Lists" [] []
         1: (empty)
-      2: MD_HASH_LIST@13..13
+      3: MD_HASH_LIST@13..13
     1: MD_NEWLINE@13..14
       0: NEWLINE@13..14 "\n" [] []
     2: MD_NEWLINE@14..15
@@ -986,15 +1003,16 @@ MdDocument {
     10: MD_NEWLINE@140..141
       0: NEWLINE@140..141 "\n" [] []
     11: MD_HEADER@141..154
-      0: MD_HASH_LIST@141..142
+      0: MD_INDENT_TOKEN_LIST@141..141
+      1: MD_HASH_LIST@141..142
         0: MD_HASH@141..142
           0: HASH@141..142 "#" [] []
-      1: MD_PARAGRAPH@142..154
+      2: MD_PARAGRAPH@142..154
         0: MD_INLINE_ITEM_LIST@142..154
           0: MD_TEXTUAL@142..154
             0: MD_TEXTUAL_LITERAL@142..154 " Loose Lists" [] []
         1: (empty)
-      2: MD_HASH_LIST@154..154
+      3: MD_HASH_LIST@154..154
     12: MD_NEWLINE@154..155
       0: NEWLINE@154..155 "\n" [] []
     13: MD_NEWLINE@155..156
@@ -1118,10 +1136,11 @@ MdDocument {
     21: MD_NEWLINE@318..319
       0: NEWLINE@318..319 "\n" [] []
     22: MD_HEADER@319..358
-      0: MD_HASH_LIST@319..320
+      0: MD_INDENT_TOKEN_LIST@319..319
+      1: MD_HASH_LIST@319..320
         0: MD_HASH@319..320
           0: HASH@319..320 "#" [] []
-      1: MD_PARAGRAPH@320..358
+      2: MD_PARAGRAPH@320..358
         0: MD_INLINE_ITEM_LIST@320..358
           0: MD_TEXTUAL@320..327
             0: MD_TEXTUAL_LITERAL@320..327 " Mixed " [] []
@@ -1134,7 +1153,7 @@ MdDocument {
           4: MD_TEXTUAL@346..358
             0: MD_TEXTUAL_LITERAL@346..358 "line Content" [] []
         1: (empty)
-      2: MD_HASH_LIST@358..358
+      3: MD_HASH_LIST@358..358
     23: MD_NEWLINE@358..359
       0: NEWLINE@358..359 "\n" [] []
     24: MD_NEWLINE@359..360
@@ -1171,9 +1190,13 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@420..429 " Item one" [] []
                 1: MD_TEXTUAL@429..430
                   0: MD_TEXTUAL_LITERAL@429..430 "\n" [] []
-                2: MD_TEXTUAL@430..446
-                  0: MD_TEXTUAL_LITERAL@430..446 "continues here" [Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@446..447
+                2: MD_INDENT_TOKEN@430..431
+                  0: MD_INDENT_CHAR@430..431 " " [] []
+                3: MD_INDENT_TOKEN@431..432
+                  0: MD_INDENT_CHAR@431..432 " " [] []
+                4: MD_TEXTUAL@432..446
+                  0: MD_TEXTUAL_LITERAL@432..446 "continues here" [] []
+                5: MD_TEXTUAL@446..447
                   0: MD_TEXTUAL_LITERAL@446..447 "\n" [] []
               1: (empty)
         1: MD_BULLET@447..475
@@ -1189,18 +1212,23 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@448..457 " Item two" [] []
                 1: MD_TEXTUAL@457..458
                   0: MD_TEXTUAL_LITERAL@457..458 "\n" [] []
-                2: MD_TEXTUAL@458..474
-                  0: MD_TEXTUAL_LITERAL@458..474 "also continues" [Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@474..475
+                2: MD_INDENT_TOKEN@458..459
+                  0: MD_INDENT_CHAR@458..459 " " [] []
+                3: MD_INDENT_TOKEN@459..460
+                  0: MD_INDENT_CHAR@459..460 " " [] []
+                4: MD_TEXTUAL@460..474
+                  0: MD_TEXTUAL_LITERAL@460..474 "also continues" [] []
+                5: MD_TEXTUAL@474..475
                   0: MD_TEXTUAL_LITERAL@474..475 "\n" [] []
               1: (empty)
     28: MD_NEWLINE@475..476
       0: NEWLINE@475..476 "\n" [] []
     29: MD_HEADER@476..508
-      0: MD_HASH_LIST@476..477
+      0: MD_INDENT_TOKEN_LIST@476..476
+      1: MD_HASH_LIST@476..477
         0: MD_HASH@476..477
           0: HASH@476..477 "#" [] []
-      1: MD_PARAGRAPH@477..508
+      2: MD_PARAGRAPH@477..508
         0: MD_INLINE_ITEM_LIST@477..508
           0: MD_TEXTUAL@477..491
             0: MD_TEXTUAL_LITERAL@477..491 " Nested Lists " [] []
@@ -1209,7 +1237,7 @@ MdDocument {
           2: MD_TEXTUAL@492..508
             0: MD_TEXTUAL_LITERAL@492..508 " Mixed Tightness" [] []
         1: (empty)
-      2: MD_HASH_LIST@508..508
+      3: MD_HASH_LIST@508..508
     30: MD_NEWLINE@508..509
       0: NEWLINE@508..509 "\n" [] []
     31: MD_NEWLINE@509..510
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/multiline_label.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/multiline_label.md.snap
index 1fe4c4081286..ca80845ad8fd 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/multiline_label.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/multiline_label.md.snap
@@ -19,6 +19,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@0..1 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -62,8 +63,9 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..16
     0: MD_LINK_REFERENCE_DEFINITION@0..15
-      0: L_BRACK@0..1 "[" [] []
-      1: MD_LINK_LABEL@1..8
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: L_BRACK@0..1 "[" [] []
+      2: MD_LINK_LABEL@1..8
         0: MD_INLINE_ITEM_LIST@1..8
           0: MD_TEXTUAL@1..4
             0: MD_TEXTUAL_LITERAL@1..4 "foo" [] []
@@ -71,15 +73,15 @@ MdDocument {
             0: MD_TEXTUAL_LITERAL@4..5 "\n" [] []
           2: MD_TEXTUAL@5..8
             0: MD_TEXTUAL_LITERAL@5..8 "bar" [] []
-      2: R_BRACK@8..9 "]" [] []
-      3: COLON@9..10 ":" [] []
-      4: MD_LINK_DESTINATION@10..15
+      3: R_BRACK@8..9 "]" [] []
+      4: COLON@9..10 ":" [] []
+      5: MD_LINK_DESTINATION@10..15
         0: MD_INLINE_ITEM_LIST@10..15
           0: MD_TEXTUAL@10..11
             0: MD_TEXTUAL_LITERAL@10..11 " " [] []
           1: MD_TEXTUAL@11..15
             0: MD_TEXTUAL_LITERAL@11..15 "/url" [] []
-      5: (empty)
+      6: (empty)
     1: MD_NEWLINE@15..16
       0: NEWLINE@15..16 "\n" [] []
   2: EOF@16..16 "" [] []
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/multiline_list.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/multiline_list.md.snap
index 8e710450d1a1..45ce015ed547 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/multiline_list.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/multiline_list.md.snap
@@ -46,8 +46,14 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@12..13 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@13..14 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@14..15 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@13..32 "with continuation" [Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@15..32 "with continuation" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@32..33 "\n" [] [],
@@ -101,8 +107,17 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@63..64 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@64..65 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@65..66 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@66..67 " " [] [],
+                                },
                                 MdTextual {
-                                    value_token: MD_TEXTUAL_LITERAL@64..81 "continues here" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                                    value_token: MD_TEXTUAL_LITERAL@67..81 "continues here" [] [],
                                 },
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@81..82 "\n" [] [],
@@ -263,9 +278,13 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@1..12 " First item" [] []
                 1: MD_TEXTUAL@12..13
                   0: MD_TEXTUAL_LITERAL@12..13 "\n" [] []
-                2: MD_TEXTUAL@13..32
-                  0: MD_TEXTUAL_LITERAL@13..32 "with continuation" [Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@32..33
+                2: MD_INDENT_TOKEN@13..14
+                  0: MD_INDENT_CHAR@13..14 " " [] []
+                3: MD_INDENT_TOKEN@14..15
+                  0: MD_INDENT_CHAR@14..15 " " [] []
+                4: MD_TEXTUAL@15..32
+                  0: MD_TEXTUAL_LITERAL@15..32 "with continuation" [] []
+                5: MD_TEXTUAL@32..33
                   0: MD_TEXTUAL_LITERAL@32..33 "\n" [] []
               1: (empty)
         1: MD_BULLET@33..48
@@ -299,9 +318,15 @@ MdDocument {
                   0: MD_TEXTUAL_LITERAL@50..63 " Ordered item" [] []
                 1: MD_TEXTUAL@63..64
                   0: MD_TEXTUAL_LITERAL@63..64 "\n" [] []
-                2: MD_TEXTUAL@64..81
-                  0: MD_TEXTUAL_LITERAL@64..81 "continues here" [Skipped(" "), Skipped(" "), Skipped(" ")] []
-                3: MD_TEXTUAL@81..82
+                2: MD_INDENT_TOKEN@64..65
+                  0: MD_INDENT_CHAR@64..65 " " [] []
+                3: MD_INDENT_TOKEN@65..66
+                  0: MD_INDENT_CHAR@65..66 " " [] []
+                4: MD_INDENT_TOKEN@66..67
+                  0: MD_INDENT_CHAR@66..67 " " [] []
+                5: MD_TEXTUAL@67..81
+                  0: MD_TEXTUAL_LITERAL@67..81 "continues here" [] []
+                6: MD_TEXTUAL@81..82
                   0: MD_TEXTUAL_LITERAL@81..82 "\n" [] []
               1: (empty)
         1: MD_BULLET@82..99
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/paragraph_interruption.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/paragraph_interruption.md.snap
index 40d93eb48442..663c23c264e5 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/paragraph_interruption.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/paragraph_interruption.md.snap
@@ -44,6 +44,7 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdHeader {
+            indent: MdIndentTokenList [],
             before: MdHashList [
                 MdHash {
                     hash_token: HASH@15..16 "#" [] [],
@@ -150,6 +151,7 @@ MdDocument {
             hard_line: missing (optional),
         },
         MdFencedCodeBlock {
+            indent: MdIndentTokenList [],
             l_fence: TRIPLE_BACKTICK@114..117 "```" [] [],
             code_list: MdCodeNameList [],
             content: MdInlineItemList [
@@ -163,6 +165,7 @@ MdDocument {
                     value_token: MD_TEXTUAL_LITERAL@134..135 "\n" [] [],
                 },
             ],
+            r_fence_indent: MdIndentTokenList [],
             r_fence: TRIPLE_BACKTICK@135..138 "```" [] [],
         },
         MdNewline {
@@ -217,15 +220,16 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@14..15 "\n" [] []
       1: (empty)
     1: MD_HEADER@15..35
-      0: MD_HASH_LIST@15..16
+      0: MD_INDENT_TOKEN_LIST@15..15
+      1: MD_HASH_LIST@15..16
         0: MD_HASH@15..16
           0: HASH@15..16 "#" [] []
-      1: MD_PARAGRAPH@16..35
+      2: MD_PARAGRAPH@16..35
         0: MD_INLINE_ITEM_LIST@16..35
           0: MD_TEXTUAL@16..35
             0: MD_TEXTUAL_LITERAL@16..35 " Heading interrupts" [] []
         1: (empty)
-      2: MD_HASH_LIST@35..35
+      3: MD_HASH_LIST@35..35
     2: MD_NEWLINE@35..36
       0: NEWLINE@35..36 "\n" [] []
     3: MD_NEWLINE@36..37
@@ -285,16 +289,18 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@113..114 "\n" [] []
       1: (empty)
     11: MD_FENCED_CODE_BLOCK@114..138
-      0: TRIPLE_BACKTICK@114..117 "```" [] []
-      1: MD_CODE_NAME_LIST@117..117
-      2: MD_INLINE_ITEM_LIST@117..135
+      0: MD_INDENT_TOKEN_LIST@114..114
+      1: TRIPLE_BACKTICK@114..117 "```" [] []
+      2: MD_CODE_NAME_LIST@117..117
+      3: MD_INLINE_ITEM_LIST@117..135
         0: MD_TEXTUAL@117..118
           0: MD_TEXTUAL_LITERAL@117..118 "\n" [] []
         1: MD_TEXTUAL@118..134
           0: MD_TEXTUAL_LITERAL@118..134 "Fence interrupts" [] []
         2: MD_TEXTUAL@134..135
           0: MD_TEXTUAL_LITERAL@134..135 "\n" [] []
-      3: TRIPLE_BACKTICK@135..138 "```" [] []
+      4: MD_INDENT_TOKEN_LIST@135..135
+      5: TRIPLE_BACKTICK@135..138 "```" [] []
     12: MD_NEWLINE@138..139
       0: NEWLINE@138..139 "\n" [] []
     13: MD_NEWLINE@139..140
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/quote_pre_marker_indent.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/quote_pre_marker_indent.md.snap
index 3200ad246b0c..651af2c466cd 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/quote_pre_marker_indent.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/quote_pre_marker_indent.md.snap
@@ -156,8 +156,11 @@ MdDocument {
         },
         MdIndentCodeBlock {
             content: MdInlineItemList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@100..101 "\t" [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@100..102 ">" [Skipped("\t")] [],
+                    value_token: MD_TEXTUAL_LITERAL@101..102 ">" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@102..120 " tab before marker" [] [],
@@ -259,9 +262,11 @@ MdDocument {
       0: NEWLINE@99..100 "\n" [] []
     8: MD_INDENT_CODE_BLOCK@100..120
       0: MD_INLINE_ITEM_LIST@100..120
-        0: MD_TEXTUAL@100..102
-          0: MD_TEXTUAL_LITERAL@100..102 ">" [Skipped("\t")] []
-        1: MD_TEXTUAL@102..120
+        0: MD_INDENT_TOKEN@100..101
+          0: MD_INDENT_CHAR@100..101 "\t" [] []
+        1: MD_TEXTUAL@101..102
+          0: MD_TEXTUAL_LITERAL@101..102 ">" [] []
+        2: MD_TEXTUAL@102..120
           0: MD_TEXTUAL_LITERAL@102..120 " tab before marker" [] []
   2: EOF@120..120 "" [] []
 
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/reference_links.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/reference_links.md.snap
index fce5c5466dec..ba9d33162957 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/reference_links.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/reference_links.md.snap
@@ -54,6 +54,7 @@ MdDocument {
     bom_token: missing (optional),
     value: MdBlockList [
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@0..1 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -176,6 +177,7 @@ MdDocument {
             value_token: NEWLINE@151..152 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@152..153 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -367,6 +369,7 @@ MdDocument {
             value_token: NEWLINE@352..353 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@353..354 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -506,6 +509,7 @@ MdDocument {
             value_token: NEWLINE@571..572 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@572..573 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -589,6 +593,7 @@ MdDocument {
             value_token: NEWLINE@678..679 "\n" [] [],
         },
         MdLinkReferenceDefinition {
+            indent: MdIndentTokenList [],
             l_brack_token: L_BRACK@679..680 "[" [] [],
             label: MdLinkLabel {
                 content: MdInlineItemList [
@@ -664,20 +669,21 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..757
     0: MD_LINK_REFERENCE_DEFINITION@0..46
-      0: L_BRACK@0..1 "[" [] []
-      1: MD_LINK_LABEL@1..8
+      0: MD_INDENT_TOKEN_LIST@0..0
+      1: L_BRACK@0..1 "[" [] []
+      2: MD_LINK_LABEL@1..8
         0: MD_INLINE_ITEM_LIST@1..8
           0: MD_TEXTUAL@1..8
             0: MD_TEXTUAL_LITERAL@1..8 "example" [] []
-      2: R_BRACK@8..9 "]" [] []
-      3: COLON@9..10 ":" [] []
-      4: MD_LINK_DESTINATION@10..30
+      3: R_BRACK@8..9 "]" [] []
+      4: COLON@9..10 ":" [] []
+      5: MD_LINK_DESTINATION@10..30
         0: MD_INLINE_ITEM_LIST@10..30
           0: MD_TEXTUAL@10..11
             0: MD_TEXTUAL_LITERAL@10..11 " " [] []
           1: MD_TEXTUAL@11..30
             0: MD_TEXTUAL_LITERAL@11..30 "https://example.com" [] []
-      5: MD_LINK_TITLE@30..46
+      6: MD_LINK_TITLE@30..46
         0: MD_INLINE_ITEM_LIST@30..46
           0: MD_TEXTUAL@30..31
             0: MD_TEXTUAL_LITERAL@30..31 " " [] []
@@ -744,20 +750,21 @@ MdDocument {
     8: MD_NEWLINE@151..152
       0: NEWLINE@151..152 "\n" [] []
     9: MD_LINK_REFERENCE_DEFINITION@152..174
-      0: L_BRACK@152..153 "[" [] []
-      1: MD_LINK_LABEL@153..156
+      0: MD_INDENT_TOKEN_LIST@152..152
+      1: L_BRACK@152..153 "[" [] []
+      2: MD_LINK_LABEL@153..156
         0: MD_INLINE_ITEM_LIST@153..156
           0: MD_TEXTUAL@153..156
             0: MD_TEXTUAL_LITERAL@153..156 "foo" [] []
-      2: R_BRACK@156..157 "]" [] []
-      3: COLON@157..158 ":" [] []
-      4: MD_LINK_DESTINATION@158..174
+      3: R_BRACK@156..157 "]" [] []
+      4: COLON@157..158 ":" [] []
+      5: MD_LINK_DESTINATION@158..174
         0: MD_INLINE_ITEM_LIST@158..174
           0: MD_TEXTUAL@158..159
             0: MD_TEXTUAL_LITERAL@158..159 " " [] []
           1: MD_TEXTUAL@159..174
             0: MD_TEXTUAL_LITERAL@159..174 "https://foo.com" [] []
-      5: (empty)
+      6: (empty)
     10: MD_NEWLINE@174..175
       0: NEWLINE@174..175 "\n" [] []
     11: MD_NEWLINE@175..176
@@ -872,20 +879,21 @@ MdDocument {
     21: MD_NEWLINE@352..353
       0: NEWLINE@352..353 "\n" [] []
     22: MD_LINK_REFERENCE_DEFINITION@353..377
-      0: L_BRACK@353..354 "[" [] []
-      1: MD_LINK_LABEL@354..358
+      0: MD_INDENT_TOKEN_LIST@353..353
+      1: L_BRACK@353..354 "[" [] []
+      2: MD_LINK_LABEL@354..358
         0: MD_INLINE_ITEM_LIST@354..358
           0: MD_TEXTUAL@354..358
             0: MD_TEXTUAL_LITERAL@354..358 "test" [] []
-      2: R_BRACK@358..359 "]" [] []
-      3: COLON@359..360 ":" [] []
-      4: MD_LINK_DESTINATION@360..377
+      3: R_BRACK@358..359 "]" [] []
+      4: COLON@359..360 ":" [] []
+      5: MD_LINK_DESTINATION@360..377
         0: MD_INLINE_ITEM_LIST@360..377
           0: MD_TEXTUAL@360..361
             0: MD_TEXTUAL_LITERAL@360..361 " " [] []
           1: MD_TEXTUAL@361..377
             0: MD_TEXTUAL_LITERAL@361..377 "https://test.com" [] []
-      5: (empty)
+      6: (empty)
     23: MD_NEWLINE@377..378
       0: NEWLINE@377..378 "\n" [] []
     24: MD_NEWLINE@378..379
@@ -964,20 +972,21 @@ MdDocument {
     30: MD_NEWLINE@571..572
       0: NEWLINE@571..572 "\n" [] []
     31: MD_LINK_REFERENCE_DEFINITION@572..606
-      0: L_BRACK@572..573 "[" [] []
-      1: MD_LINK_LABEL@573..583
+      0: MD_INDENT_TOKEN_LIST@572..572
+      1: L_BRACK@572..573 "[" [] []
+      2: MD_LINK_LABEL@573..583
         0: MD_INLINE_ITEM_LIST@573..583
           0: MD_TEXTUAL@573..583
             0: MD_TEXTUAL_LITERAL@573..583 "Case Label" [] []
-      2: R_BRACK@583..584 "]" [] []
-      3: COLON@584..585 ":" [] []
-      4: MD_LINK_DESTINATION@585..606
+      3: R_BRACK@583..584 "]" [] []
+      4: COLON@584..585 ":" [] []
+      5: MD_LINK_DESTINATION@585..606
         0: MD_INLINE_ITEM_LIST@585..606
           0: MD_TEXTUAL@585..586
             0: MD_TEXTUAL_LITERAL@585..586 " " [] []
           1: MD_TEXTUAL@586..606
             0: MD_TEXTUAL_LITERAL@586..606 "https://case.example" [] []
-      5: (empty)
+      6: (empty)
     32: MD_NEWLINE@606..607
       0: NEWLINE@606..607 "\n" [] []
     33: MD_NEWLINE@607..608
@@ -1019,22 +1028,23 @@ MdDocument {
     37: MD_NEWLINE@678..679
       0: NEWLINE@678..679 "\n" [] []
     38: MD_LINK_REFERENCE_DEFINITION@679..713
-      0: L_BRACK@679..680 "[" [] []
-      1: MD_LINK_LABEL@680..687
+      0: MD_INDENT_TOKEN_LIST@679..679
+      1: L_BRACK@679..680 "[" [] []
+      2: MD_LINK_LABEL@680..687
         0: MD_INLINE_ITEM_LIST@680..687
           0: MD_TEXTUAL@680..685
             0: MD_TEXTUAL_LITERAL@680..685 "label" [] []
           1: MD_TEXTUAL@685..687
             0: MD_TEXTUAL_LITERAL@685..687 "\\]" [] []
-      2: R_BRACK@687..688 "]" [] []
-      3: COLON@688..689 ":" [] []
-      4: MD_LINK_DESTINATION@689..713
+      3: R_BRACK@687..688 "]" [] []
+      4: COLON@688..689 ":" [] []
+      5: MD_LINK_DESTINATION@689..713
         0: MD_INLINE_ITEM_LIST@689..713
           0: MD_TEXTUAL@689..690
             0: MD_TEXTUAL_LITERAL@689..690 " " [] []
           1: MD_TEXTUAL@690..713
             0: MD_TEXTUAL_LITERAL@690..713 "https://escaped.example" [] []
-      5: (empty)
+      6: (empty)
     39: MD_NEWLINE@713..714
       0: NEWLINE@713..714 "\n" [] []
     40: MD_NEWLINE@714..715
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/setext_heading_edge_cases.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/setext_heading_edge_cases.md.snap
index 89a9715a994d..96427c3f054b 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/setext_heading_edge_cases.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/setext_heading_edge_cases.md.snap
@@ -39,8 +39,17 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@3..4 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@4..5 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@5..6 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@6..7 " " [] [],
+                },
             ],
-            underline_token: MD_SETEXT_UNDERLINE_LITERAL@4..11 "----" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+            underline_token: MD_SETEXT_UNDERLINE_LITERAL@7..11 "----" [] [],
         },
         MdNewline {
             value_token: NEWLINE@11..12 "\n" [] [],
@@ -140,8 +149,14 @@ MdDocument {
                                 MdTextual {
                                     value_token: MD_TEXTUAL_LITERAL@53..54 "\n" [] [],
                                 },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@54..55 " " [] [],
+                                },
+                                MdIndentToken {
+                                    md_indent_char_token: MD_INDENT_CHAR@55..56 " " [] [],
+                                },
                             ],
-                            underline_token: MD_SETEXT_UNDERLINE_LITERAL@54..59 "---" [Skipped(" "), Skipped(" ")] [],
+                            underline_token: MD_SETEXT_UNDERLINE_LITERAL@56..59 "---" [] [],
                         },
                         MdNewline {
                             value_token: NEWLINE@59..60 "\n" [] [],
@@ -173,12 +188,18 @@ MdDocument {
   0: (empty)
   1: MD_BLOCK_LIST@0..66
     0: MD_SETEXT_HEADER@0..11
-      0: MD_INLINE_ITEM_LIST@0..4
+      0: MD_INLINE_ITEM_LIST@0..7
         0: MD_TEXTUAL@0..3
           0: MD_TEXTUAL_LITERAL@0..3 "Foo" [] []
         1: MD_TEXTUAL@3..4
           0: MD_TEXTUAL_LITERAL@3..4 "\n" [] []
-      1: MD_SETEXT_UNDERLINE_LITERAL@4..11 "----" [Skipped(" "), Skipped(" "), Skipped(" ")] []
+        2: MD_INDENT_TOKEN@4..5
+          0: MD_INDENT_CHAR@4..5 " " [] []
+        3: MD_INDENT_TOKEN@5..6
+          0: MD_INDENT_CHAR@5..6 " " [] []
+        4: MD_INDENT_TOKEN@6..7
+          0: MD_INDENT_CHAR@6..7 " " [] []
+      1: MD_SETEXT_UNDERLINE_LITERAL@7..11 "----" [] []
     1: MD_NEWLINE@11..12
       0: NEWLINE@11..12 "\n" [] []
     2: MD_NEWLINE@12..13
@@ -242,12 +263,16 @@ MdDocument {
             3: MD_INDENT_TOKEN_LIST@49..49
           1: MD_BLOCK_LIST@49..66
             0: MD_SETEXT_HEADER@49..59
-              0: MD_INLINE_ITEM_LIST@49..54
+              0: MD_INLINE_ITEM_LIST@49..56
                 0: MD_TEXTUAL@49..53
                   0: MD_TEXTUAL_LITERAL@49..53 " Foo" [] []
                 1: MD_TEXTUAL@53..54
                   0: MD_TEXTUAL_LITERAL@53..54 "\n" [] []
-              1: MD_SETEXT_UNDERLINE_LITERAL@54..59 "---" [Skipped(" "), Skipped(" ")] []
+                2: MD_INDENT_TOKEN@54..55
+                  0: MD_INDENT_CHAR@54..55 " " [] []
+                3: MD_INDENT_TOKEN@55..56
+                  0: MD_INDENT_CHAR@55..56 " " [] []
+              1: MD_SETEXT_UNDERLINE_LITERAL@56..59 "---" [] []
             1: MD_NEWLINE@59..60
               0: NEWLINE@59..60 "\n" [] []
             2: MD_PARAGRAPH@60..66
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/setext_heading_negative.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/setext_heading_negative.md.snap
index 5d0a9c53db49..3a9d78d64cca 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/setext_heading_negative.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/setext_heading_negative.md.snap
@@ -57,8 +57,20 @@ MdDocument {
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@12..13 "\n" [] [],
                 },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@13..14 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@14..15 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@15..16 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@16..17 " " [] [],
+                },
                 MdTextual {
-                    value_token: MD_TEXTUAL_LITERAL@13..20 "---" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value_token: MD_TEXTUAL_LITERAL@17..20 "---" [] [],
                 },
                 MdTextual {
                     value_token: MD_TEXTUAL_LITERAL@20..21 "\n" [] [],
@@ -161,9 +173,17 @@ MdDocument {
           0: MD_TEXTUAL_LITERAL@9..12 "Foo" [] []
         1: MD_TEXTUAL@12..13
           0: MD_TEXTUAL_LITERAL@12..13 "\n" [] []
-        2: MD_TEXTUAL@13..20
-          0: MD_TEXTUAL_LITERAL@13..20 "---" [Skipped(" "), Skipped(" "), Skipped(" "), Skipped(" ")] []
-        3: MD_TEXTUAL@20..21
+        2: MD_INDENT_TOKEN@13..14
+          0: MD_INDENT_CHAR@13..14 " " [] []
+        3: MD_INDENT_TOKEN@14..15
+          0: MD_INDENT_CHAR@14..15 " " [] []
+        4: MD_INDENT_TOKEN@15..16
+          0: MD_INDENT_CHAR@15..16 " " [] []
+        5: MD_INDENT_TOKEN@16..17
+          0: MD_INDENT_CHAR@16..17 " " [] []
+        6: MD_TEXTUAL@17..20
+          0: MD_TEXTUAL_LITERAL@17..20 "---" [] []
+        7: MD_TEXTUAL@20..21
           0: MD_TEXTUAL_LITERAL@20..21 "\n" [] []
       1: (empty)
     3: MD_NEWLINE@21..22
diff --git a/crates/biome_markdown_parser/tests/md_test_suite/ok/thematic_break_block.md.snap b/crates/biome_markdown_parser/tests/md_test_suite/ok/thematic_break_block.md.snap
index 75a86991bc12..f95981a34ee7 100644
--- a/crates/biome_markdown_parser/tests/md_test_suite/ok/thematic_break_block.md.snap
+++ b/crates/biome_markdown_parser/tests/md_test_suite/ok/thematic_break_block.md.snap
@@ -25,8 +25,17 @@ MdDocument {
     value: MdBlockList [
         MdThematicBreakBlock {
             parts: MdThematicBreakPartList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@0..1 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@1..2 " " [] [],
+                },
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@2..3 " " [] [],
+                },
                 MdThematicBreakChar {
-                    value: STAR@0..4 "*" [Skipped(" "), Skipped(" "), Skipped(" ")] [],
+                    value: STAR@3..4 "*" [] [],
                 },
                 MdThematicBreakChar {
                     value: STAR@4..5 "*" [] [],
@@ -41,8 +50,11 @@ MdDocument {
         },
         MdThematicBreakBlock {
             parts: MdThematicBreakPartList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@7..8 " " [] [],
+                },
                 MdThematicBreakChar {
-                    value: STAR@7..9 "*" [Skipped(" ")] [],
+                    value: STAR@8..9 "*" [] [],
                 },
                 MdThematicBreakChar {
                     value: STAR@9..10 "*" [] [],
@@ -57,8 +69,11 @@ MdDocument {
         },
         MdThematicBreakBlock {
             parts: MdThematicBreakPartList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@12..13 " " [] [],
+                },
                 MdThematicBreakChar {
-                    value: MINUS@12..14 "-" [Skipped(" ")] [],
+                    value: MINUS@13..14 "-" [] [],
                 },
                 MdIndentToken {
                     md_indent_char_token: MD_INDENT_CHAR@14..15 " " [] [],
@@ -98,8 +113,11 @@ MdDocument {
         },
         MdThematicBreakBlock {
             parts: MdThematicBreakPartList [
+                MdIndentToken {
+                    md_indent_char_token: MD_INDENT_CHAR@24..25 " " [] [],
+                },
                 MdThematicBreakChar {
-                    value: UNDERSCORE@24..26 "_" [Skipped(" ")] [],
+                    value: UNDERSCORE@25..26 "_" [] [],
                 },
                 MdIndentToken {
                     md_indent_char_token: MD_INDENT_CHAR@26..27 " " [] [],
@@ -153,35 +171,45 @@ MdDocument {
   1: MD_BLOCK_LIST@0..37
     0: MD_THEMATIC_BREAK_BLOCK@0..6
       0: MD_THEMATIC_BREAK_PART_LIST@0..6
-        0: MD_THEMATIC_BREAK_CHAR@0..4
-          0: STAR@0..4 "*" [Skipped(" "), Skipped(" "), Skipped(" ")] []
-        1: MD_THEMATIC_BREAK_CHAR@4..5
+        0: MD_INDENT_TOKEN@0..1
+          0: MD_INDENT_CHAR@0..1 " " [] []
+        1: MD_INDENT_TOKEN@1..2
+          0: MD_INDENT_CHAR@1..2 " " [] []
+        2: MD_INDENT_TOKEN@2..3
+          0: MD_INDENT_CHAR@2..3 " " [] []
+        3: MD_THEMATIC_BREAK_CHAR@3..4
+          0: STAR@3..4 "*" [] []
+        4: MD_THEMATIC_BREAK_CHAR@4..5
           0: STAR@4..5 "*" [] []
-        2: MD_THEMATIC_BREAK_CHAR@5..6
+        5: MD_THEMATIC_BREAK_CHAR@5..6
           0: STAR@5..6 "*" [] []
     1: MD_NEWLINE@6..7
       0: NEWLINE@6..7 "\n" [] []
     2: MD_THEMATIC_BREAK_BLOCK@7..11
       0: MD_THEMATIC_BREAK_PART_LIST@7..11
-        0: MD_THEMATIC_BREAK_CHAR@7..9
-          0: STAR@7..9 "*" [Skipped(" ")] []
-        1: MD_THEMATIC_BREAK_CHAR@9..10
+        0: MD_INDENT_TOKEN@7..8
+          0: MD_INDENT_CHAR@7..8 " " [] []
+        1: MD_THEMATIC_BREAK_CHAR@8..9
+          0: STAR@8..9 "*" [] []
+        2: MD_THEMATIC_BREAK_CHAR@9..10
           0: STAR@9..10 "*" [] []
-        2: MD_THEMATIC_BREAK_CHAR@10..11
+        3: MD_THEMATIC_BREAK_CHAR@10..11
           0: STAR@10..11 "*" [] []
     3: MD_NEWLINE@11..12
       0: NEWLINE@11..12 "\n" [] []
     4: MD_THEMATIC_BREAK_BLOCK@12..18
       0: MD_THEMATIC_BREAK_PART_LIST@12..18
-        0: MD_THEMATIC_BREAK_CHAR@12..14
-          0: MINUS@12..14 "-" [Skipped(" ")] []
-        1: MD_INDENT_TOKEN@14..15
+        0: MD_INDENT_TOKEN@12..13
+          0: MD_INDENT_CHAR@12..13 " " [] []
+        1: MD_THEMATIC_BREAK_CHAR@13..14
+          0: MINUS@13..14 "-" [] []
+        2: MD_INDENT_TOKEN@14..15
           0: MD_INDENT_CHAR@14..15 " " [] []
-        2: MD_THEMATIC_BREAK_CHAR@15..16
+        3: MD_THEMATIC_BREAK_CHAR@15..16
           0: MINUS@15..16 "-" [] []
-        3: MD_INDENT_TOKEN@16..17
+        4: MD_INDENT_TOKEN@16..17
           0: MD_INDENT_CHAR@16..17 " " [] []
-        4: MD_THEMATIC_BREAK_CHAR@17..18
+        5: MD_THEMATIC_BREAK_CHAR@17..18
           0: MINUS@17..18 "-" [] []
     5: MD_NEWLINE@18..19
       0: NEWLINE@18..19 "\n" [] []
@@ -199,15 +227,17 @@ MdDocument {
       0: NEWLINE@23..24 "\n" [] []
     9: MD_THEMATIC_BREAK_BLOCK@24..30
       0: MD_THEMATIC_BREAK_PART_LIST@24..30
-        0: MD_THEMATIC_BREAK_CHAR@24..26
-          0: UNDERSCORE@24..26 "_" [Skipped(" ")] []
-        1: MD_INDENT_TOKEN@26..27
+        0: MD_INDENT_TOKEN@24..25
+          0: MD_INDENT_CHAR@24..25 " " [] []
+        1: MD_THEMATIC_BREAK_CHAR@25..26
+          0: UNDERSCORE@25..26 "_" [] []
+        2: MD_INDENT_TOKEN@26..27
           0: MD_INDENT_CHAR@26..27 " " [] []
-        2: MD_THEMATIC_BREAK_CHAR@27..28
+        3: MD_THEMATIC_BREAK_CHAR@27..28
           0: UNDERSCORE@27..28 "_" [] []
-        3: MD_INDENT_TOKEN@28..29
+        4: MD_INDENT_TOKEN@28..29
           0: MD_INDENT_CHAR@28..29 " " [] []
-        4: MD_THEMATIC_BREAK_CHAR@29..30
+        5: MD_THEMATIC_BREAK_CHAR@29..30
           0: UNDERSCORE@29..30 "_" [] []
     10: MD_NEWLINE@30..31
       0: NEWLINE@30..31 "\n" [] []
diff --git a/crates/biome_markdown_syntax/src/generated/nodes.rs b/crates/biome_markdown_syntax/src/generated/nodes.rs
index 6266b6543ce6..13a4c68be357 100644
--- a/crates/biome_markdown_syntax/src/generated/nodes.rs
+++ b/crates/biome_markdown_syntax/src/generated/nodes.rs
@@ -236,23 +236,31 @@ impl MdFencedCodeBlock {
     }
     pub fn as_fields(&self) -> MdFencedCodeBlockFields {
         MdFencedCodeBlockFields {
+            indent: self.indent(),
             l_fence: self.l_fence(),
             code_list: self.code_list(),
             content: self.content(),
+            r_fence_indent: self.r_fence_indent(),
             r_fence: self.r_fence(),
         }
     }
+    pub fn indent(&self) -> MdIndentTokenList {
+        support::list(&self.syntax, 0usize)
+    }
     pub fn l_fence(&self) -> SyntaxResult {
-        support::required_token(&self.syntax, 0usize)
+        support::required_token(&self.syntax, 1usize)
     }
     pub fn code_list(&self) -> MdCodeNameList {
-        support::list(&self.syntax, 1usize)
+        support::list(&self.syntax, 2usize)
     }
     pub fn content(&self) -> MdInlineItemList {
-        support::list(&self.syntax, 2usize)
+        support::list(&self.syntax, 3usize)
+    }
+    pub fn r_fence_indent(&self) -> MdIndentTokenList {
+        support::list(&self.syntax, 4usize)
     }
     pub fn r_fence(&self) -> SyntaxResult {
-        support::required_token(&self.syntax, 3usize)
+        support::required_token(&self.syntax, 5usize)
     }
 }
 impl Serialize for MdFencedCodeBlock {
@@ -265,9 +273,11 @@ impl Serialize for MdFencedCodeBlock {
 }
 #[derive(Serialize)]
 pub struct MdFencedCodeBlockFields {
+    pub indent: MdIndentTokenList,
     pub l_fence: SyntaxResult,
     pub code_list: MdCodeNameList,
     pub content: MdInlineItemList,
+    pub r_fence_indent: MdIndentTokenList,
     pub r_fence: SyntaxResult,
 }
 #[derive(Clone, PartialEq, Eq, Hash)]
@@ -356,19 +366,23 @@ impl MdHeader {
     }
     pub fn as_fields(&self) -> MdHeaderFields {
         MdHeaderFields {
+            indent: self.indent(),
             before: self.before(),
             content: self.content(),
             after: self.after(),
         }
     }
-    pub fn before(&self) -> MdHashList {
+    pub fn indent(&self) -> MdIndentTokenList {
         support::list(&self.syntax, 0usize)
     }
+    pub fn before(&self) -> MdHashList {
+        support::list(&self.syntax, 1usize)
+    }
     pub fn content(&self) -> Option {
-        support::node(&self.syntax, 1usize)
+        support::node(&self.syntax, 2usize)
     }
     pub fn after(&self) -> MdHashList {
-        support::list(&self.syntax, 2usize)
+        support::list(&self.syntax, 3usize)
     }
 }
 impl Serialize for MdHeader {
@@ -381,6 +395,7 @@ impl Serialize for MdHeader {
 }
 #[derive(Serialize)]
 pub struct MdHeaderFields {
+    pub indent: MdIndentTokenList,
     pub before: MdHashList,
     pub content: Option,
     pub after: MdHashList,
@@ -401,12 +416,16 @@ impl MdHtmlBlock {
     }
     pub fn as_fields(&self) -> MdHtmlBlockFields {
         MdHtmlBlockFields {
+            indent: self.indent(),
             content: self.content(),
         }
     }
-    pub fn content(&self) -> MdInlineItemList {
+    pub fn indent(&self) -> MdIndentTokenList {
         support::list(&self.syntax, 0usize)
     }
+    pub fn content(&self) -> MdInlineItemList {
+        support::list(&self.syntax, 1usize)
+    }
 }
 impl Serialize for MdHtmlBlock {
     fn serialize(&self, serializer: S) -> Result
@@ -418,6 +437,7 @@ impl Serialize for MdHtmlBlock {
 }
 #[derive(Serialize)]
 pub struct MdHtmlBlockFields {
+    pub indent: MdIndentTokenList,
     pub content: MdInlineItemList,
 }
 #[derive(Clone, PartialEq, Eq, Hash)]
@@ -961,6 +981,7 @@ impl MdLinkReferenceDefinition {
     }
     pub fn as_fields(&self) -> MdLinkReferenceDefinitionFields {
         MdLinkReferenceDefinitionFields {
+            indent: self.indent(),
             l_brack_token: self.l_brack_token(),
             label: self.label(),
             r_brack_token: self.r_brack_token(),
@@ -969,23 +990,26 @@ impl MdLinkReferenceDefinition {
             title: self.title(),
         }
     }
+    pub fn indent(&self) -> MdIndentTokenList {
+        support::list(&self.syntax, 0usize)
+    }
     pub fn l_brack_token(&self) -> SyntaxResult {
-        support::required_token(&self.syntax, 0usize)
+        support::required_token(&self.syntax, 1usize)
     }
     pub fn label(&self) -> SyntaxResult {
-        support::required_node(&self.syntax, 1usize)
+        support::required_node(&self.syntax, 2usize)
     }
     pub fn r_brack_token(&self) -> SyntaxResult {
-        support::required_token(&self.syntax, 2usize)
+        support::required_token(&self.syntax, 3usize)
     }
     pub fn colon_token(&self) -> SyntaxResult {
-        support::required_token(&self.syntax, 3usize)
+        support::required_token(&self.syntax, 4usize)
     }
     pub fn destination(&self) -> SyntaxResult {
-        support::required_node(&self.syntax, 4usize)
+        support::required_node(&self.syntax, 5usize)
     }
     pub fn title(&self) -> Option {
-        support::node(&self.syntax, 5usize)
+        support::node(&self.syntax, 6usize)
     }
 }
 impl Serialize for MdLinkReferenceDefinition {
@@ -998,6 +1022,7 @@ impl Serialize for MdLinkReferenceDefinition {
 }
 #[derive(Serialize)]
 pub struct MdLinkReferenceDefinitionFields {
+    pub indent: MdIndentTokenList,
     pub l_brack_token: SyntaxResult,
     pub label: SyntaxResult,
     pub r_brack_token: SyntaxResult,
@@ -2224,9 +2249,11 @@ impl std::fmt::Debug for MdFencedCodeBlock {
         let result = if current_depth < 16 {
             DEPTH.set(current_depth + 1);
             f.debug_struct("MdFencedCodeBlock")
+                .field("indent", &self.indent())
                 .field("l_fence", &support::DebugSyntaxResult(self.l_fence()))
                 .field("code_list", &self.code_list())
                 .field("content", &self.content())
+                .field("r_fence_indent", &self.r_fence_indent())
                 .field("r_fence", &support::DebugSyntaxResult(self.r_fence()))
                 .finish()
         } else {
@@ -2371,6 +2398,7 @@ impl std::fmt::Debug for MdHeader {
         let result = if current_depth < 16 {
             DEPTH.set(current_depth + 1);
             f.debug_struct("MdHeader")
+                .field("indent", &self.indent())
                 .field("before", &self.before())
                 .field("content", &support::DebugOptionalElement(self.content()))
                 .field("after", &self.after())
@@ -2420,6 +2448,7 @@ impl std::fmt::Debug for MdHtmlBlock {
         let result = if current_depth < 16 {
             DEPTH.set(current_depth + 1);
             f.debug_struct("MdHtmlBlock")
+                .field("indent", &self.indent())
                 .field("content", &self.content())
                 .finish()
         } else {
@@ -3088,6 +3117,7 @@ impl std::fmt::Debug for MdLinkReferenceDefinition {
         let result = if current_depth < 16 {
             DEPTH.set(current_depth + 1);
             f.debug_struct("MdLinkReferenceDefinition")
+                .field("indent", &self.indent())
                 .field(
                     "l_brack_token",
                     &support::DebugSyntaxResult(self.l_brack_token()),
diff --git a/crates/biome_markdown_syntax/src/generated/nodes_mut.rs b/crates/biome_markdown_syntax/src/generated/nodes_mut.rs
index 134acf961fb6..052a6854ebee 100644
--- a/crates/biome_markdown_syntax/src/generated/nodes_mut.rs
+++ b/crates/biome_markdown_syntax/src/generated/nodes_mut.rs
@@ -74,28 +74,40 @@ impl MdEntityReference {
     }
 }
 impl MdFencedCodeBlock {
+    pub fn with_indent(self, element: MdIndentTokenList) -> Self {
+        Self::unwrap_cast(
+            self.syntax
+                .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))),
+        )
+    }
     pub fn with_l_fence_token(self, element: SyntaxToken) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(0usize..=0usize, once(Some(element.into()))),
+                .splice_slots(1usize..=1usize, once(Some(element.into()))),
         )
     }
     pub fn with_code_list(self, element: MdCodeNameList) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))),
+                .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))),
         )
     }
     pub fn with_content(self, element: MdInlineItemList) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))),
+                .splice_slots(3usize..=3usize, once(Some(element.into_syntax().into()))),
+        )
+    }
+    pub fn with_r_fence_indent(self, element: MdIndentTokenList) -> Self {
+        Self::unwrap_cast(
+            self.syntax
+                .splice_slots(4usize..=4usize, once(Some(element.into_syntax().into()))),
         )
     }
     pub fn with_r_fence_token(self, element: SyntaxToken) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(3usize..=3usize, once(Some(element.into()))),
+                .splice_slots(5usize..=5usize, once(Some(element.into()))),
         )
     }
 }
@@ -116,32 +128,44 @@ impl MdHash {
     }
 }
 impl MdHeader {
-    pub fn with_before(self, element: MdHashList) -> Self {
+    pub fn with_indent(self, element: MdIndentTokenList) -> Self {
         Self::unwrap_cast(
             self.syntax
                 .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))),
         )
     }
+    pub fn with_before(self, element: MdHashList) -> Self {
+        Self::unwrap_cast(
+            self.syntax
+                .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))),
+        )
+    }
     pub fn with_content(self, element: Option) -> Self {
         Self::unwrap_cast(self.syntax.splice_slots(
-            1usize..=1usize,
+            2usize..=2usize,
             once(element.map(|element| element.into_syntax().into())),
         ))
     }
     pub fn with_after(self, element: MdHashList) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))),
+                .splice_slots(3usize..=3usize, once(Some(element.into_syntax().into()))),
         )
     }
 }
 impl MdHtmlBlock {
-    pub fn with_content(self, element: MdInlineItemList) -> Self {
+    pub fn with_indent(self, element: MdIndentTokenList) -> Self {
         Self::unwrap_cast(
             self.syntax
                 .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))),
         )
     }
+    pub fn with_content(self, element: MdInlineItemList) -> Self {
+        Self::unwrap_cast(
+            self.syntax
+                .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))),
+        )
+    }
 }
 impl MdIndent {
     pub fn with_value_token(self, element: SyntaxToken) -> Self {
@@ -366,39 +390,45 @@ impl MdLinkLabel {
     }
 }
 impl MdLinkReferenceDefinition {
+    pub fn with_indent(self, element: MdIndentTokenList) -> Self {
+        Self::unwrap_cast(
+            self.syntax
+                .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))),
+        )
+    }
     pub fn with_l_brack_token(self, element: SyntaxToken) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(0usize..=0usize, once(Some(element.into()))),
+                .splice_slots(1usize..=1usize, once(Some(element.into()))),
         )
     }
     pub fn with_label(self, element: MdLinkLabel) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))),
+                .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))),
         )
     }
     pub fn with_r_brack_token(self, element: SyntaxToken) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(2usize..=2usize, once(Some(element.into()))),
+                .splice_slots(3usize..=3usize, once(Some(element.into()))),
         )
     }
     pub fn with_colon_token(self, element: SyntaxToken) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(3usize..=3usize, once(Some(element.into()))),
+                .splice_slots(4usize..=4usize, once(Some(element.into()))),
         )
     }
     pub fn with_destination(self, element: MdLinkDestination) -> Self {
         Self::unwrap_cast(
             self.syntax
-                .splice_slots(4usize..=4usize, once(Some(element.into_syntax().into()))),
+                .splice_slots(5usize..=5usize, once(Some(element.into_syntax().into()))),
         )
     }
     pub fn with_title(self, element: Option) -> Self {
         Self::unwrap_cast(self.syntax.splice_slots(
-            5usize..=5usize,
+            6usize..=6usize,
             once(element.map(|element| element.into_syntax().into())),
         ))
     }
diff --git a/xtask/codegen/markdown.ungram b/xtask/codegen/markdown.ungram
index 0aa0b3d7a346..df95f9ea6124 100644
--- a/xtask/codegen/markdown.ungram
+++ b/xtask/codegen/markdown.ungram
@@ -73,6 +73,7 @@ AnyMdContainerBlock =
 // ## Lorem
 // ^^^^^^^^
 MdHeader =
+	indent: MdIndentTokenList
 	before: MdHashList
 	content: MdParagraph?
 	after: MdHashList
@@ -101,7 +102,7 @@ AnyMdCodeBlock =
 //     code
 // ^^^^^^^^
 // The space before "code" is intentional.
-// Indentation is tracked in trivia, so we use MdInlineItemList for content.
+// Content indentation uses MdInlineItemList which can contain MdIndentToken nodes.
 MdIndentCodeBlock =
 	content: MdInlineItemList
 
@@ -114,20 +115,25 @@ MdIndentCodeBlock =
 //
 // ~~~
 MdFencedCodeBlock =
+	indent: MdIndentTokenList
 	l_fence: ('```' | '~~~')
 	code_list: MdCodeNameList
 	content: MdInlineItemList
+	r_fence_indent: MdIndentTokenList
 	r_fence: ('```' | '~~~')
 
 MdCodeNameList = MdTextual*
 
 // html block - content is stored as raw text (multiple textual tokens)
-MdHtmlBlock = content: MdInlineItemList
+MdHtmlBlock =
+	indent: MdIndentTokenList
+	content: MdInlineItemList
 
 // Link reference definition per CommonMark §4.7
 // [label]: destination "title" or [label]: destination 'title' or [label]: destination (title)
 // Labels are case-insensitive and whitespace-normalized
 MdLinkReferenceDefinition =
+	indent: MdIndentTokenList
 	'['
 	label: MdLinkLabel
 	']'