Allow CJK adjacency in emphasis delimiter runs - #839
JoshuaKirby88 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the CommonMark specification to allow emphasis delimiter runs to open/close when adjacent to CJK characters, addressing cases where CJK punctuation/adjacency previously caused literal * to remain visible.
Changes:
- Defines a new “CJK character” based on Unicode
East_Asian_Width/Scriptproperties (excludingEmoji_Presentation). - Extends left-/right-flanking delimiter run definitions to permit a CJK-adjacency alternative when punctuation would otherwise block emphasis.
- Adds conformance examples covering new supported cases and protected non-changes (underscores, whitespace, ambiguous-width punctuation, emoji presentation).
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@tats-u I would be grateful for your review of this. |
|
This is essentially, to put it nicely, an ultra-simplified version, or to put it bluntly, a poor man's copy of https://github.com/tats-u/markdown-cjk-friendly. It becomes equivalent to that if you remove the support for variation sequences before delimiter runs. While it is commendable for handling many cases with minimal effort, it is regrettable that the PR description makes no mention of my repository. Also, although cases that cannot be covered by this are rare, Japanese or Chinese people who are knowledgeable about Unicode could easily list them. The test cases lack coverage for at least the following:
|
|
By the way, do CommonMark maintainers like you consider the change in 0.31.2, where emojis are now treated as punctuation (meaning, for example, |
|
Thanks for reviewing and identifying missing tests. Your implementation is relevant and I should've acknowledged it. My aim was to address the behavior in CommonMark itself, since this still affects many widely used renderers like cmark, cmark-gfm, markdown-it, micromark, and Marked. I'll add coverage for the cases you listed and look more closely at the differences in variation-sequence handling. |
|
@tats-u would you like to prepare an alternative PR based on your work?
Just built 0.31.1, and it has same behavior. Are you sure it used to work differently? |
Addresses #650.
Problem
CommonMark's punctuation-based flanking rules can leave ordinary CJK emphasis visible as literal
*characters. Japanese and Chinese generally do not add spaces at these boundaries, and Korean particles attach directly to the text they follow.Before and after
Japanese
Markdown:
Current CommonMark HTML:
Proposed HTML:
Chinese
Markdown:
Current CommonMark HTML:
Proposed HTML:
Korean
Markdown:
Current CommonMark HTML:
Proposed HTML:
Proposed rule
This PR defines a CJK character as an assigned Unicode character that meets either of these conditions:
East_Asian_Widthproperty isW,F, orH, excluding characters withEmoji_Presentation;Scriptproperty isHangul.A delimiter run adjacent to such a character can satisfy the punctuation portion of the left-flanking or right-flanking definition.
The existing whitespace conditions still apply. The existing restrictions on underscore delimiters also remain unchanged.
Conformance examples
The PR adds nine examples covering Japanese, Chinese, Korean, strong and single emphasis, ASCII punctuation inside CJK text, and protected behavior involving ambiguous-width punctuation, underscores, whitespace, and emoji presentation.
Five examples demonstrate newly supported emphasis. Four protect behavior that must remain unchanged.
Related work
tats-u/markdown-cjk-friendly provides proposed CommonMark amendments and implementations addressing the same CJK emphasis problem. Its specification includes closely related CJK character classification and emphasis-flanking rules, with additional handling for variation sequences.
Thanks to @tats-u for reviewing this proposal and identifying gaps in the test coverage.
Proof implementation
The complete cmark proof is available as an exact comparison against upstream cmark. It includes the implementation, regression tests, and a Unicode 17 range generator that pins and verifies every input file by SHA-256.
The classifier uses binary search over 68 non-overlapping ranges, requiring at most seven range comparisons for each adjacent code point.
Reproduce the verification
The following starts from public repositories and does not require this branch to be checked out already:
Expected results: