Zulip has a special flavor of Markdown, currently called ‘bugdown’ after Zulip’s original name of “humbug”. End users are using Bugdown within the client, not original Markdown.
Zulip has two implementations of Bugdown. The first is based on
zerver/lib/bugdown/) and is used to authoritatively
render messages on the backend (and implements expensive features like
querying the Twitter API to render tweets nicely). The other is in
static/js/echo.js), and is used to
preview and locally echo messages the moment the sender hits enter,
without waiting for round trip from the server. The two
implementations are tested for compatibility via
zerver/tests/test_bugdown.py and the fixtures under
I should note that the below documentation is based on a comparison with original Markdown, not newer Markdown variants like CommonMark.
Zulip’s Markdown philosophy¶
Markdown is great for group chat for the same reason it’s been successful in products ranging from blogs to wikis to bug trackers: it’s close enough to how people try to express themselves when writing plain text (e.g. emails) that is helps more than getting in the way.
The main issue for using Markdown in instant messaging is that the Markdown standard syntax used in a lot of wikis/blogs has nontrivial error rates, where the author needs to go back and edit the post to fix the formatting after typing it the first time. While that’s basically fine when writing a blog, it gets annoying very fast in a chat product; even though you can edit messages to fix formatting mistakes, you don’t want to be doing that often. There are basically 2 types of error rates that are important for a product like Zulip:
- What fraction of the time, if you pasted a short technical email
that you wrote to your team and passed it through your Markdown
implementation, would you need to change the text of your email for it
to render in a reasonable way? This is the “accidental Markdown
syntax” problem, common with Markdown syntax like the italics syntax
interacting with talking about
- What fraction of the time do users attempting to use a particular Markdown syntax actually succeed at doing so correctly? Syntax like required a blank line between text and the start of a bulleted list raise this figure substantially.
Both of these are minor issues for most products using Markdown, but they are major problems in the instant messaging context, because one can’t edit a message that has already been sent and users are generally writing quickly. Zulip’s Markdown strategy is based on the principles of giving users the power they need to express complicated ideas in a chat context while minimizing those two error rates.
Zulip’s Changes to Markdown¶
Below, we document the changes that Zulip has against stock Python-Markdown; some of the features we modify / disable may already be non-standard.
- Enable `nl2br extension: this means one newline creates a line break (not paragraph break).
- Disable italics entirely. This resolves an issue where people were
_and hitting it by mistake too often. E.g. with stock Markdown
You should use char * instead of void * therewould trigger italics.
- Allow only
**syntax for bold, not
__(easy to hit by mistake if discussing Python
- Disable special use of
\to escape other syntax. Rendering
\was hugely controversial, but having no escape syntax is also controversial. We may revisit this. For now you can always put things in code blocks.
- Allow tacking a bulleted list or block quote onto the end of a paragraph, i.e. without a blank line before it
- Allow only
*for bulleted lists, not
-(previously created confusion with diff-style text sloppily not included in a code block)
- Disable ordered list syntax: it automatically renumbers, which can be really confusing when sending a numbered list across multiple messages.
- Enable fenced code block extension, with syntax highlighting
- Disable line-numbering within fenced code blocks – the
<table>output confused our web client code.
- Disable headings, both
== foo ==syntax: they don’t make much sense for chat messages.
- Disabled images.
- Allow embedding any avatar as a tiny (list bullet size) image. This is used primarily by version control integrations.
- We added the
~~~ quoteblock quote syntax.