If you cannot see this post, you can use this image

Your task is to create a markdown parser that outputs Unicode. It should support 𝗯𝗼𝗹𝗱, 𝘪𝘵𝘢𝘭𝘪𝘤, 𝙼𝚘𝚗𝚘𝚜𝚙𝚊𝚌𝚎, and 𝗎̲𝗇̲𝖽̲𝖾̲𝗋̲𝗅̲𝗂̲𝗇̲𝖾̲.

Every alphabetical character should be converted into Math Sans. This includes the characters before an underline character.

Underlines: Add a ̲ character (code point 818) after each character. Underlines can be combined with anything else.

There should be no way to escape a control character.

The following combinations should be supported:

𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓 (code point 120224 to 120275 Math Sans)

` 𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣 ` (120432 to 120483 Math Monospace)

* 𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻 * (120328 to 120379 Math Sans Italic)

** 𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇 ** (120276 to 120327 Math Sans Bold)

*** 𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯 *** (120380 to 120431 Math Sans Bold Italic)

__ 𝖠̲𝖡̲𝖢̲𝖣̲𝖤̲𝖥̲𝖦̲𝖧̲𝖨̲𝖩̲𝖪̲𝖫̲𝖬̲𝖭̲𝖮̲𝖯̲𝖰̲𝖱̲𝖲̲𝖳̲𝖴̲𝖵̲𝖶̲𝖷̲𝖸̲𝖹̲𝖺̲𝖻̲𝖼̲𝖽̲𝖾̲𝖿̲𝗀̲𝗁̲𝗂̲𝗃̲𝗄̲𝗅̲𝗆̲𝗇̲𝗈̲𝗉̲𝗊̲𝗋̲𝗌̲𝗍̲𝗎̲𝗏̲𝗐̲𝗑̲𝗒̲𝗓̲ __ (818 Math Sans with Combining Low Line after each character)

__` 𝙰̲𝙱̲𝙲̲𝙳̲𝙴̲𝙵̲𝙶̲𝙷̲𝙸̲𝙹̲𝙺̲𝙻̲𝙼̲𝙽̲𝙾̲𝙿̲𝚀̲𝚁̲𝚂̲𝚃̲𝚄̲𝚅̲𝚆̲𝚇̲𝚈̲𝚉̲𝚊̲𝚋̲𝚌̲𝚍̲𝚎̲𝚏̲𝚐̲𝚑̲𝚒̲𝚓̲𝚔̲𝚕̲𝚖̲𝚗̲𝚘̲𝚙̲𝚚̲𝚛̲𝚜̲𝚝̲𝚞̲𝚟̲𝚠̲𝚡̲𝚢̲𝚣̲ `__ (Math Sans Monospace with Combining Low Line)

Underline should also support Math Sans Italic, Math Sans Bold, and Math Sans Bold Italic

The final output should not contain the characters used to format the text.


Some things can be nested. Underlines can nest with any character and can be put in the inside or outside of another control character. Both of these will have an underline.

**Underlines __inside the bold__**
__Bold **inside the underline**__

Other things such as bold, monospace, bold italic, and italic can't nest because there are no characters for it.

**This is `not valid` input and will***never be given*

Ambiguous Formatting Characters

Formatting characters that can be ambiguous will never be given. ** is valid because it is bold, but **** will never be given because it is undefined.

At the end of formatting characters, there will always be another character between the next formatting delimiter of the same character. *format***ing** will not be given because there should be a character before the next *format* **ing** delimiter using *s, however *format*__ing__ could be given because they are different characters used in the delimiter.

**Which is bold ***and which is italic?* <-- Invalid, will never be given
**Oh I see** *now.* <-- Valid


Nothing can escape. There is no way to use any of the control characters except for a singular underscore

*There is no way to put a * in the text, not even \* backslashes* <-- All of the asterisks will be italic

Even __newlines
don't interrupt__ formatting <-- newlines don't interrupt will all be underlined

Because the singular _underscore is not a formatting character, it_is allowed_ and will not be removed

Example I/O

Example I

*This* is_a **test** of __the ***markdown*** `parser`__ Multi-line `__should
be__ supported`. Nothing `can\` escape.

Example O

𝘛𝘩𝘪𝘴 𝗂𝗌_𝖺 𝘁𝗲𝘀𝘁 𝗈𝖿 𝗍̲𝗁̲𝖾̲ ̲𝙢̲𝙖̲𝙧̲𝙠̲𝙙̲𝙤̲𝙬̲𝙣̲ ̲𝚙̲𝚊̲𝚛̲𝚜̲𝚎̲𝚛̲ 𝖬𝗎𝗅𝗍𝗂-𝗅𝗂𝗇𝖾 𝚜̲𝚑̲𝚘̲𝚞̲𝚕̲𝚍̲
̲𝚋̲𝚎̲ 𝚜𝚞𝚙𝚙𝚘𝚛𝚝𝚎𝚍. 𝖭𝗈𝗍𝗁𝗂𝗇𝗀 𝚌𝚊𝚗\ 𝖾𝗌𝖼𝖺𝗉𝖾.

This input is not valid and it doesn't matter what your program outputs:

*This **is not valid** input* because it nests italic and bold

*Neither `is this`* because it nests italic and monospace

*This***Is not valid** Either because it can be interpreted different ways

As this is , the shortest solution in bytes wins.

  • \$\begingroup\$ Can you change the title so my eyes stop bleeding? \$\endgroup\$
    – user63187
    Mar 12, 2018 at 18:09
  • \$\begingroup\$ @Christopher what is wrong with it? i.imgur.com/04ErkFu.png \$\endgroup\$
    – pfg
    Mar 12, 2018 at 18:10
  • \$\begingroup\$ @pfg it doesn't format well on some devices. (particularly the underlined characters) \$\endgroup\$
    – Riker
    Mar 12, 2018 at 18:12
  • \$\begingroup\$ @Riker Hmm, works on my phone i.imgur.com/hjBVwHp.png. I've put both in the title for people who can't read it \$\endgroup\$
    – pfg
    Mar 12, 2018 at 18:15
  • \$\begingroup\$ Very related \$\endgroup\$
    – Shaggy
    Mar 12, 2018 at 19:13

3 Answers 3


Stax, 75 73 74 70 bytes


Run and debug it online

The basic approach is store the 4 types of formatting in a bit field, and then get the correct character offset from a lookup using the integer value. Only 8 values are in the lookup. The high bit denoting underline is handled separately.

Here's a commented ungolfed version.

m                       Map mode: for each line of input, 
                            run the rest of the program, then output
"\*\*|__|."|F           Find all regex matches using pattern. This splits the string into 
                            individual characters except for ** and __, which stay together.
                            These will be called "atoms" of the input.
{                       begin a block
  VAVa+                 Construct "ABC..XYZabc..xyz"
  "_*``_****__"_I       Get the index of the current atom in "_*`_****__"
  0|MY                  Take the maximum with zero, then store in register y.
                            This gives {*: 1, `: 2, **: 4, __: 8} and 0 for all else. 
  x|^X                  Xor with the x register and write back. It stores bitflags for 4 modes.
  "&6mU*9*9 0E*9 !"!@   Index into codepoint lookup table using x.
  c52+|r                Build range of 52 consecutive values starting at codepoint.
  \$                    Build translation string by combination with the alphabetic string.
  |t                    Perform translation on the current atom.
  818+                  Add codepoint 818 to the current atom.
  x8<T                  Remove it again if x<8.  This is iff underline mode is off.
  y!*                   Multiply by the logical not of y.  If the atom is for formatting, 
                        this eliminates output for this atom
m                       map over atoms using the enclosed block

Run this one

  • \$\begingroup\$ It seems like monospace underline is using bold italic instead of monospace \$\endgroup\$
    – pfg
    Mar 12, 2018 at 22:19
  • \$\begingroup\$ My mistake. I thought that that was a disallowed combination. I'll see about addressing that. \$\endgroup\$
    – recursive
    Mar 12, 2018 at 23:03
  • \$\begingroup\$ I guess I should make it more clear in my post. Underlines combine with anything \$\endgroup\$
    – pfg
    Mar 12, 2018 at 23:04
  • 1
    \$\begingroup\$ Let us continue this discussion in chat. \$\endgroup\$
    – recursive
    Mar 12, 2018 at 23:22
  • 1
    \$\begingroup\$ @pfg That combination overflowed the lookup table. I've added a fix at a cost of 1 byte. \$\endgroup\$
    – recursive
    Mar 12, 2018 at 23:30

Python 3, 267 253 243 239 235 229 226 224 bytes

import re
def f(s):
 for c in re.findall(r'__|\*+|`|.|\n',s):
  if c in a:m,u=[a.index(c)-m,m,u,1-u][c=='__'::2]

Try it online!


Jelly, 87 bytes


Try it online!

  • \$\begingroup\$ If I'm reading this right the difference is that the newline is underlined. \$\endgroup\$
    – recursive
    Mar 13, 2018 at 18:53
  • \$\begingroup\$ @recursive Yes it is, although I think it has been fixed now. \$\endgroup\$ Mar 13, 2018 at 18:54
  • \$\begingroup\$ Hm. It appears this "fix" has invalidated my solution. \$\endgroup\$
    – recursive
    Mar 13, 2018 at 19:27
  • \$\begingroup\$ @recursive Looks like it, but, well, that's what the challenge specification really says, not me. \$\endgroup\$ Mar 13, 2018 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.