Skip to content

List item HTML block is pulled into paragraph on round-trip #75

@ChristianMurphy

Description

@ChristianMurphy

Initial checklist

Affected package

mdast-util-gfm 3.1.0, mdast-util-to-markdown 2.1.2, mdast-util-from-markdown 2.0.3

Steps to reproduce

Input (8 bytes):

- :
<a>

tree₁ (listItem has two children: a paragraph and an html block):

{
  "type": "listItem",
  "children": [
    { "type": "paragraph", "children": [{ "type": "text", "value": ":" }] },
    { "type": "html", "value": "<a>" }
  ]
}

stringify:

* :
  <a>

The serializer emits the <a> indented with the listItem's continuation
spaces. On re-parse the indented <a> no longer starts at column 1, so it
is not eligible to begin a new html block, and instead becomes inline html
inside the paragraph's continuation line:

tree₂:

{
  "type": "listItem",
  "children": [{
    "type": "paragraph",
    "children": [
      { "type": "text", "value": ":\n" },
      { "type": "html", "value": "<a>" }
    ]
  }]
}

Minimal reproducer:

import {fromMarkdown} from 'mdast-util-from-markdown'
import {toMarkdown} from 'mdast-util-to-markdown'
import {gfm} from 'micromark-extension-gfm'
import {gfmFromMarkdown, gfmToMarkdown} from 'mdast-util-gfm'

const opts = {extensions: [gfm()], mdastExtensions: [gfmFromMarkdown()]}
const tree1 = fromMarkdown('- :\n<a>\n', opts)
const text2 = toMarkdown(tree1, {extensions: [gfmToMarkdown()]})
const tree2 = fromMarkdown(text2, opts)
// listItem.children.length: 2 vs 1

Actual behavior

The re-parsed listItem has one fewer child: the block-html sibling has been
pulled into the paragraph's content as inline html.

Expected behavior

A listItem's block children round-trip as block children. If an indented
<a> inside a list continuation is ambiguous, the serializer should emit
a form that preserves the block shape (for example: insert a blank line,
use unindented hard-wrap, or wrap in a fenced code boundary).

Runtime

No response

Package manager

No response

Operating system

No response

Build and bundle tools

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    🤞 phase/openPost is being triaged manually

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions