Stream: contributing

Topic: markdown


view this post on Zulip Steve Howell (Oct 29 2026 at 11:51):

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.

view this post on Zulip Steve Howell (Oct 29 2026 at 11:57):

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.

view this post on Zulip Steve Howell (Oct 29 2026 at 11:59):

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).

view this post on Zulip Steve Howell (Oct 29 2026 at 12:02):

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.

view this post on Zulip Steve Howell (Oct 29 2026 at 12:04):

I'll post more later today.

view this post on Zulip Steve Howell (Oct 29 2026 at 12:13):

(As an aside, I'm porting my entire chat server to Roc as well.)

view this post on Zulip Steve Howell (Oct 29 2026 at 13:42):

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.

view this post on Zulip Steve Howell (Oct 29 2026 at 20:48):

Here's a playground for it: https://roc.lynrummy.com/markdown/

The playground runs the markdown processor within the browser (Roc -> wasm).

view this post on Zulip Steve Howell (Oct 29 2026 at 21:00):

https://github.com/showell/roc-markdown is the repo. It has the same universal license as Roc.

view this post on Zulip Steve Howell (Oct 30 2026 at 15:41):

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