I'm working on creating a pure-Roc implementation of the chat-centric markdown flavor that I have been using on my personal chat server since about May of this year.
The original implementation was based on a couple community-approved golang packages for parsing and rendering common markdown. I then soon ported it to zig. It's battle-tested with several thousand real-world messages from me and a couple friends using the chat, and it's extensively tested with automated tests for correctness and dealing with pathological inputs.
The chat markdown's design is also influenced my time on the Zulip project as both a developer and user. I actually did significant work on Zulip's markdown parser, which is a heavy layer over python-markdown.
There's really no such thing a markdown standard in the chat world. Zulip has had its own flavor of markdown since 2014. Chat has different ergonomics than document creation, plus chat has a large attack surface. So chat-centric markdown implementations usually cut certain features for safety while adding other features for ergonomics or better expressiveness.
For safety, the most obvious thing that markdown authors do is allow-list only a few tags like <img> tags, and of course those tags have restricted attributes. You're not bring down this Zulip server with a simple script tag, nor would you bring down mine.
My only audience up until now has been my little chat community, but now that I'm in the Roc world, I intend to support documentation as well. With docs you usually want a mode where you know the markdown source is trusted, and certain features that don't really work for chat (e.g. tables don't work great in chat, because the syntax is so clumsy) are quite important for docs (e.g. tables).
I know there's some prior work out there, including https://github.com/lukewilliamboswell/roc-parser from @Luke Boswell (markdown is part of a bigger general-purpose parsing project). So I'm having Claude try to steal the best ideas from the other projects we found.
I'll post more later today.
(As an aside, I'm porting my entire chat server to Roc as well.)
Here's an example of what the code looks like now (still evolving): https://github.com/showell/roc-markdown/blob/main/package/MdInline.roc
It's not the most elegant code in the world, but I think this is par for the course for production markdown processors across all languages. As I mentioned earlier, this code is ultimately modeled after the most popular golang libraries.
Here's a playground for it: https://roc.lynrummy.com/markdown/
The playground runs the markdown processor within the browser (Roc -> wasm).
https://github.com/showell/roc-markdown is the repo. It has the same universal license as Roc.
The playground now has an example with hostile input too:
`x``x```x````x`````x``````x```````x````````x`````````x``````````x```````````x````````````x`````````````x``````````````x```````````````x````````````````x`````````````````x``````````````````x```````````````````x````````````````````x`````````````````````x``````````````````````x```````````````````````x````````````````````````x`````````````````````````x``````````````````````````x```````````````````````````x````````````````````````````x`````````````````````````````x``````````````````````````````x```````````````````````````````x````````````````````````````````x`````````````````````````````````x``````````````````````````````````x```````````````````````````````````x````````````````````````````````````x
Note that this message doesn't crash Zulip's markdown processor, because I quoted the hostile run of backticks. I didn't try actually hostile markdown against Zulip, nor will I. :) My parser also handles quoted hostile text fine, which you can verify in the playground.
Last updated: Nov 04 2026 at 18:54 UTC