Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

keycap emoji is treated as formatting #646

Open
mikesamuel opened this issue Apr 24, 2020 · 7 comments
Open

keycap emoji is treated as formatting #646

mikesamuel opened this issue Apr 24, 2020 · 7 comments

Comments

@mikesamuel
Copy link

The keycap emoji, *️⃣, used for the '*' telephone button is encoded via a sequence of 3 codepoints:

  • U+2A (Asterisk)
  • U+FE0F
  • U+20E3

Sometimes CommonMark treats the leading asterisk as a formatting character as in **️⃣abc** (
\x{2A 2A FE0F 20E3 61 62 63 2A 2A} )

To reproduce

permalink to REPL

Screenshot

Observe that there is a placeholder glyph followed by bold "abc".
Note that the HTML tab shows <p><strong>️⃣abc</strong></p>.

I expect that instead, the output should contain all three UTF-16 code units for the *️⃣ emoji.

Relevant specifications

Unicode TR#51 explains

ED-14c. emoji keycap sequence — A sequence of the following form:

emoji_keycap_sequence := [0-9#*] \x{FE0F 20E3}

Possibly out of scope, but to get the keycap on the first line of this issue to show up properly in Github flavoured markdown, I needed to precede it with a backslash (\).

@jgm
Copy link
Member

jgm commented Apr 24, 2020

Simple solution is to backslash-escape it. Commonmark regards its input as a sequence of characters and doesn't know about this keycap encoding (which I'd never heard of before).

But maybe it would be worth changing the spec so that an emphasis character followed by a variation selector (U+FE00..U+FE0F) is always treated as literal.

@Crissov
Copy link
Contributor

Crissov commented Apr 24, 2020

This would also apply to digits 0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣ and hash mark #️⃣.

@wooorm
Copy link
Contributor

wooorm commented Jul 4, 2020

@Crissov While that could theoretically be a problem, it wouldn’t practically occur, right? As CM needs a following .) for lists or a space for headings?


*️⃣a*

*a*️⃣

Yields:

️⃣a

a️⃣


I believe that, to change this behavior in CM, we could add FE0F to 2a) of left-flanking delimiter run:

 A [left-flanking delimiter run](@) is
 a [delimiter run] that is (1) not followed by [Unicode whitespace],
-and either (2a) not followed by a [Unicode punctuation character], or
+and either (2a) not followed by a [Unicode punctuation character] or `U+FE0F, or
 (2b) followed by a [Unicode punctuation character] and
 preceded by [Unicode whitespace] or a [Unicode punctuation character].
 For purposes of this definition, the beginning and the end of
 the line count as Unicode whitespace.

…and to change 2a) of right-flanking delimiter run too:

 A [right-flanking delimiter run](@) is
 a [delimiter run] that is (1) not preceded by [Unicode whitespace],
-and either (2a) not preceded by a [Unicode punctuation character], or
+and either (2a) not preceded by a [Unicode punctuation character] and not followed by `U+FE0F`, or
 (2b) preceded by a [Unicode punctuation character] and
 followed by [Unicode whitespace] or a [Unicode punctuation character].
 For purposes of this definition, the beginning and the end of
 the line count as Unicode whitespace.

@Crissov
Copy link
Contributor

Crissov commented Jul 4, 2020

Indeed, it is less of a problem for digits and # than it is for *.

@ghost
Copy link

ghost commented Oct 28, 2020

I wanted to mention that I personally think the best way to handle this in the specification level is to work with the text as grapheme clusters, rather than as code points.

Of course, implementations that do not wish to implement the whole segmentation algorithm can use ad‐hoc criteria like @wooorm’s.

@rsc
Copy link

rsc commented Sep 4, 2021

@zamfofex are there instances other than this one where the two approaches would differ?

Edited: Struck out "other than this one" because they don't differ here. The question was whether they ever differ. If not, that's a good sign because an implementation can do whichever is more convenient.

@tats-u
Copy link

tats-u commented Oct 13, 2024

Here is a simple corner case:

**foo**️⃣

Bad (current): <p><strong>foo</strong>️⃣</p>
Bad: <p>**foo**️⃣</p>
Good: <p><em>*foo</em>*️⃣</p>

I wanted to mention that I personally think the best way to handle this in the specification level is to work with the text as grapheme clusters, rather than as code points.

How about peeking two next codepoints? All we have to do is treat * followed by the following sequences as neither-flanking:

  • U+FE0F U+20E3 (*️⃣: emoji)
  • U+FE0E U+20E3 (*︎⃣: text symbol)
  • U+20E3 (can be either)

I think this can't be fixed with the current delimiter run; we have to exclude such * from delimiter run of *.

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

No branches or pull requests

6 participants