Skip to content

Allow HTML declarations with lowercase letters and without whitespace - #469

Open
wleeaf wants to merge 1 commit into
commonmark:mainfrom
wleeaf:fix-html-declaration-letters
Open

wleeaf wants to merge 1 commit into
commonmark:mainfrom
wleeaf:fix-html-declaration-letters

Conversation

@wleeaf

@wleeaf wleeaf commented Oct 24, 2026

Copy link
Copy Markdown

Since spec 0.30, a declaration is "the string <!, an ASCII letter, zero or more characters not including the character >, and the character >". The HTML block start condition 4 is "<! followed by an ASCII letter". commonmark-java still follows the older rules in two places:

  • HtmlBlockParser starts a type 4 block only for an uppercase letter (^<![A-Z]), so a lowercase doctype is wrapped in a paragraph:

    <!doctype html>
    

    commonmark-java: <p><!doctype html></p>. cmark and commonmark.js: <!doctype html>.

  • HtmlInlineParser.tryDeclaration still requires whitespace after the letters, so inline <!FOO> and inline <!foo> are escaped (&lt;!FOO&gt;). cmark and commonmark.js render them as inline HTML.

4ca7a59 ("Allow lowercase ASCII in HTML declaration (spec 0.30)") already updated the comment in tryDeclaration to the new wording and switched the inline check to any ASCII letter. It kept the whitespace check, though, and did not touch the block pattern.

Changes:

  • ^<![A-Z] becomes ^<![A-Za-z] in HtmlBlockParser.
  • The whitespace check in tryDeclaration is removed. The noDeclarationEnd shortcut still prevents rescanning when there is no >; inputs like "<!A " * 30000 and "<!A" * 30000 render in well under a second.

Tests:

  • New SpecialInputTest.htmlBlockDeclarationWithLowercaseLetter.
  • HtmlInlineParserTest.declaration no longer says "Whitespace is mandatory": <!FOO> is now expected to be inline HTML, plus a lowercase case without whitespace.
  • afterFailedAttempt used <!foo> as the failing attempt; it now uses <!1>, which is still not HTML.

The changed tests fail before the change and pass after. mvn test passes, except that PathologicalTest.paragraphOfLinesThatTryBlockStarts hit its 3 s timeout once on a heavily loaded machine. That test is unrelated and passes when run on its own, on main as well as on this branch. spotless:check is clean.

Found by differential testing against cmark.

Copilot AI balanced review requested due to automatic review settings October 24, 2026 14:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants