Skip to content

HTML comment block incorrectly ended before --> when rendering CommonMark #377

@Jayman2000

Description

@Jayman2000

Describe the bug

context
I’m trying use markdown-it-py to convert this chunk of Markdown (taken from here) into HTML:

1. **Install the prerequisite build tools.**

    Make sure that you have Git and Visual Studio 2022 with the “Desktop development with C++” workload and the “C++ MFC for latest v143 build tools (x86 & x64)” component. If you don’t already have those installed or you aren’t sure, then open an elevated Command Prompt and run:
    <!--
    The following code block specifies the full path to the Visual Studio Installer because the Visual Studio Installer doesn’t add itself to the user’s Path. The installer is guaranteed to be in a specific location on 64-bit systems [1]. The installer will be in a different location on 32-bit systems [2], but Visual Studio 2022 doesn’t support 32-bit systems [3] so we can ignore that detail.

    [1]: <https://learn.microsoft.com/en-us/visualstudio/install/use-command-line-parameters-to-install-visual-studio?view=vs-2022>
    [2]: <https://github.com/microsoft/vswhere/wiki#installing>
    [3]: <https://learn.microsoft.com/en-us/answers/questions/1689898/does-visual-studio-build-tools-2022-support-32-bit>
    -->
    ```batch
    winget install Git.Git Microsoft.VisualStudio.2022.Community

    "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\setup.exe" modify^
        --passive^
        --channelId VisualStudio.17.Release^
        --productId Microsoft.VisualStudio.Product.Community^
        --add Microsoft.VisualStudio.Workload.NativeDesktop;includeRecommended^
        --add Microsoft.VisualStudio.Component.VC.ATLMFC
    ```

expectation
I expect markdown-it-py to generate HTML that contains -->.

bug
markdown-it-py actually generates HTML that does not contain -->:

<ol>
<li>
<p><strong>Install the prerequisite build tools.</strong></p>
<p>Make sure that you have Git and Visual Studio 2022 with the “Desktop development with C++” workload and the “C++ MFC for latest v143 build tools (x86 &amp; x64)” component. If you don’t already have those installed or you aren’t sure, then open an elevated Command Prompt and run:</p>
 <!--
 The following code block specifies the full path to the Visual Studio Installer because the Visual Studio Installer doesn’t add itself to the user’s Path. The installer is guaranteed to be in a specific location on 64-bit systems [1]. The installer will be in a different location on 32-bit systems [2], but Visual Studio 2022 doesn’t support 32-bit systems [3] so we can ignore that detail.
<p>--&gt;</p>
<pre><code class="language-batch">winget install Git.Git Microsoft.VisualStudio.2022.Community

&quot;%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\setup.exe&quot; modify^
    --passive^
    --channelId VisualStudio.17.Release^
    --productId Microsoft.VisualStudio.Product.Community^
    --add Microsoft.VisualStudio.Workload.NativeDesktop;includeRecommended^
    --add Microsoft.VisualStudio.Component.VC.ATLMFC
</code></pre>
</li>
</ol>

In this situation, it looks like markdown-it-py is not quite conforming to the CommonMark specification properly. Section 4.6 of version 0.31.2 of the CommonMark specification says:

There are seven kinds of HTML block, which can be defined by their
start and end conditions. The block begins with a line that meets a
start condition (after up to three optional spaces of indentation).
It ends with the first subsequent line that meets a matching
end condition, or the last line of the document, or the last line of
the container block containing the current HTML
block, if no line is encountered that meets the end condition. If
the first line meets both the start condition and the end
condition
, the block will contain just that line.

  1. Start condition: line begins with the string <pre,
    <script, <style, or <textarea (case-insensitive), followed by a space,
    a tab, the string >, or the end of the line.
    End condition: line contains an end tag
    </pre>, </script>, </style>, or </textarea> (case-insensitive; it
    need not match the start tag).

  2. Start condition: line begins with the string <!--.
    End condition: line contains the string -->.

  3. Start condition: line begins with the string <?.
    End condition: line contains the string ?>.

  4. Start condition: line begins with the string <!
    followed by an ASCII letter.
    End condition: line contains the character >.

  5. Start condition: line begins with the string
    <![CDATA[.
    End condition: line contains the string ]]>.

  6. Start condition: line begins with the string < or </
    followed by one of the strings (case-insensitive) address,
    article, aside, base, basefont, blockquote, body,
    caption, center, col, colgroup, dd, details, dialog,
    dir, div, dl, dt, fieldset, figcaption, figure,
    footer, form, frame, frameset,
    h1, h2, h3, h4, h5, h6, head, header, hr,
    html, iframe, legend, li, link, main, menu, menuitem,
    nav, noframes, ol, optgroup, option, p, param,
    search, section, summary, table, tbody, td,
    tfoot, th, thead, title, tr, track, ul, followed
    by a space, a tab, the end of the line, the string >, or
    the string />.
    End condition: line is followed by a blank line.

  7. Start condition: line begins with a complete open tag
    (with any tag name other than pre, script,
    style, or textarea) or a complete closing tag,
    followed by zero or more spaces and tabs, followed by the end of the line.
    End condition: line is followed by a blank line.

HTML blocks continue until they are closed by their appropriate
end condition, or the last line of the document or other container
block
.

Based on that quote, it seems like HTML blocks that start with <!-- should never end until there is a -->. In this situation, it looks like markdown-it-py is mistakenly ending the HTML block after a line that is followed by a blank line. While it is correct for a line followed by a blank line to end an HTML block that began with <details> (for example), it is not correct for a line followed by a blank line to end an HTML block that began with <!--.

problem
When I view the generated HTML in a Web browser, everything after “then open an elevated Command Prompt and run:” is not displayed.

Reproduce the bug

  1. Open a terminal.

  2. Make sure that you have the uv command. If you use the Nix package manager, then you can make sure that you have the exact same versions of Python and uv that I used to reproduce this bug by doing the following:

    1. Create a file named shell-for-reproducing-markdown-it-py-bug.nix that contains the following Nix expression:

      # This file is dedicated to the public domain using 🅭🄍1.0:
      # <https://creativecommons.org/publicdomain/zero/1.0>.
      let
        nixpkgsCommit = "09eb77e94fa25202af8f3e81ddc7353d9970ac1b";
        nixpkgsDirectory = builtins.fetchTarball {
          url = "https://github.com/NixOS/nixpkgs/archive/${nixpkgsCommit}.tar.gz";
          sha256 = "02hdh4r0cc5h78cmymndb8clfhkn6phbrkrv6s8kvyfspqwzj84r";
        };
        pkgs = import nixpkgsDirectory { };
        python = pkgs.python314;
      in
      pkgs.mkShellNoCC {
        name = "shell-for-reproducing-markdown-it-py-bug";
        packages = [
          python
          python.pkgs.uv
        ];
      }
    2. Activate that Nix shell by running the following command:

      nix-shell <path to shell-for-reproducing-markdown-it-py-bug.nix>
  3. Create a file named reproduce_markdown_it_py_bug.py that contains the following Python script:

    # /// script
    # requires-python = ">=3.10"
    # dependencies = [
    #   "markdown-it-py",
    # ]
    # ///
    import markdown_it
    to_render = """
    1. **Install the prerequisite build tools.**
    
        Make sure that you have Git and Visual Studio 2022 with the “Desktop development with C++” workload and the “C++ MFC for latest v143 build tools (x86 & x64)” component. If you don’t already have those installed or you aren’t sure, then open an elevated Command Prompt and run:
        <!--
        The following code block specifies the full path to the Visual Studio Installer because the Visual Studio Installer doesn’t add itself to the user’s Path. The installer is guaranteed to be in a specific location on 64-bit systems [1]. The installer will be in a different location on 32-bit systems [2], but Visual Studio 2022 doesn’t support 32-bit systems [3] so we can ignore that detail.
    
        [1]: <https://learn.microsoft.com/en-us/visualstudio/install/use-command-line-parameters-to-install-visual-studio?view=vs-2022>
        [2]: <https://github.com/microsoft/vswhere/wiki#installing>
        [3]: <https://learn.microsoft.com/en-us/answers/questions/1689898/does-visual-studio-build-tools-2022-support-32-bit>
        -->
        ```batch
        winget install Git.Git Microsoft.VisualStudio.2022.Community
    
        "%ProgramFiles(x86)%\\Microsoft Visual Studio\\Installer\\setup.exe" modify^
            --passive^
            --channelId VisualStudio.17.Release^
            --productId Microsoft.VisualStudio.Product.Community^
            --add Microsoft.VisualStudio.Workload.NativeDesktop;includeRecommended^
            --add Microsoft.VisualStudio.Component.VC.ATLMFC
        ```
    """
    md = markdown_it.MarkdownIt()
    print(md.render(to_render))
  4. Create a file named reproduce_markdown_it_py_bug.py.lock that’s in the same directory as reproduce_markdown_it_py_bug.py and contains the following TOML document:

    version = 1
    revision = 3
    requires-python = ">=3.10"
    
    [manifest]
    requirements = [{ name = "markdown-it-py" }]
    
    [[package]]
    name = "markdown-it-py"
    version = "4.0.0"
    source = { registry = "https://pypi.org/simple" }
    dependencies = [
        { name = "mdurl" },
    ]
    sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
    wheels = [
        { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
    ]
    
    [[package]]
    name = "mdurl"
    version = "0.1.2"
    source = { registry = "https://pypi.org/simple" }
    sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
    wheels = [
        { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
    ]
  5. Run the reproduce_markdown_it_py_bug.py script by running this command:

    uv run --locked --script <path to reproduce_markdown_it_py_bug.py>

List your environment

  • Version of markdown-it-py: 4.0.0
  • Version of mdit-py-plugins: none
  • Version of Python: 3.14.0
  • My operating system: NixOS 25.05.812554.6faeb062ee4c

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions