DEV Community

Cover image for Marks, Streamlined evolution of a Markdown engine...

Marks, Streamlined evolution of a Markdown engine...

nomoredeps profile image NoMoreDeps ・6 min read

The begining

When I started writing documentation in a web format, I was overwhelmed by the Markdown. This simplicity of writing, allowing on a simple annotated text, to be able to format in a quick but brief way was a real revolution.

But just as every new feature comes with its bunch of good things, it also comes with its frustrating side.

Indeed, can we be more productive in handling emphasis than just writing this?

This **will** add *emphasis* to your `text` !
Enter fullscreen mode Exit fullscreen mode

and just have this in return ...

This will add emphasis to your text !

Feel the problems coming from miles away

At which point do you realize the limits of something you appreciate? It's when you want to do even more with it... and it's not as simple in reality.

Let's take a simple example. It is very easy to put a piece of text in bold or italics. It is natural to want to add a touch of color to it, isn't it?

And that's where the trouble starts. How do we put our text in red ? The answer ? Mix it with HTML...

HTML, right in the middle of my text... Ohhh, that sounds slightly insulting to my ears. Why would I want to mix text, with HTML code. Worse yet, how could I convince my colleagues who are not familiar with source code to adopt Markdown...

Another example, funny, the tables.

What a chance to be able to display data in the form of a table. I saw it as an excellent opportunity to make the documentation pages more relevant.

So go go go go, it was off to try to format my first data in a format that seems super simple :-)

| COL A | COL B   | COL C  |
| Left  | Center  |Right   |
Enter fullscreen mode Exit fullscreen mode

And then you have this :

Left Center Right

The disappointment

I was so cheerful, that I wanted my colleagues to share this enthusiasm, and to adopt this syntax as soon as possible...

And one of my colleague immediately gave me some data to format to see how practical it was... To receive data... in the... CSV format.

What a pain to transform the csv before using it, it is a very common format for data tables. 😄

I then realized that a user who, by nature, is a bit resistant to change, won't even bother to do the same if he encounters the slightest difficulty with what he had been told.

So I was the only one to use it for a while :-) But that was fair.

The rise of the new era 😄

Then it became more and more widespread, and during my last project, we decided to keep our documentation up to date, and include this small documentation phase in our Agile cycle.

Just after each Kickoff, before we start coding, we update or create the minimalist documentation related to this feature. And naturally, as everyone has started to learn Markdown, the frustrations are reappearing on a massive scale. 😄 😄

As a developer, I decided to extend at least one markdown engine in order to meet the growing needs. But there is the following problem:

How to make an engine simple and extensible, if the format, although simple in appearance, brings problems of streamlining in terms of design?

The new hope

So I decided to give it a try. To begin with, I had to tackle this heratic side of the parsing.

The syntax of the emphasis is convenient, it should not be changed. But if we want to adopt an extensible approach, we need to streamline the complex blocks, to allow the rendering engine to analyze them more flexibly, without making the syntax more awkward. The notion is fixed by repetition, and from this hypothesis, a single block declaration syntax seems appropriate.

Marks engine, was born 😄
But what can we do with it ?


You can keep writing emphasis as in Markdown.
Alt Text
Will result as this :

Alt Text


You can use Emoji(s) out of the box. Marks includes Twitter emojis.

Alt Text

The documentation includes a search engine to find all Emoji's name

Alt Text


Heading has no reason to be used in another way

Alt Text


Same here, syntax is quite the same, but nesting is not allowed the same way for readability purpose.

Alt Text

Alt Text

Unordered list

Alt Text

Ordered list

Alt Text

And we added a neutral symbol if you don't want to use numbers in your document

Alt Text

The Legacy

Tables, images, links, code blocks, they all keep the same syntax too.

New blocks ?

Yeah, we added a unique way to declare all kind of new blocks.

Enter fullscreen mode Exit fullscreen mode

So for example, the Table syntax becomes ...

[table format:markdown] {{
  | COL A | COL B   | COL C  |
  | AA    | BB      |CC      |
Enter fullscreen mode Exit fullscreen mode

But, with this syntax, you can easily change options and brings more flexibility without changing the way you declare it

[table format:csv] {{
Enter fullscreen mode Exit fullscreen mode

And for both blocks, the result will be the same
Alt Text

This allows several things:

  • Simplify the work of the parser, and thus keep its speed.
  • Prevent users from getting lost in complex syntax
  • Simplify the creation of third party plugins.


In Marks, styles are options, but to keep it simple, some option names are dedicated to style. A paragraph, or a block can have styles. The way you declare styles in a block is the same as a paragraph. The difference is where you can set them.

[table format:csv theme:dark variant:bordered,striped] {{
Enter fullscreen mode Exit fullscreen mode

In this block, just setting the theme to dark will apply some predifined style to it. So the user can defined easily styles.

Variant are predifined css too, to help streamline the global page templating.

The result with the bootstrap template looks like this :

Alt Text


Even if it is possible to apply styles or other options to a custom block, it is still possible to define the same thing on classic paragraphs

Alt Text


If you've ever worked with Markdown, you've seen that there are limits to how you can / cannot nest one component into another.

For example, it is not possible to nest one table into another, the syntax is not flexible enough to allow this.

To allow and simplify this feature, we introduced the ref option.

If you add the option ref to a component, it will not be rendered where you declared it. Instead, it will be added where a placeholder exist, with the same ref name.

| Rows id       | A1            | A2    | ::- ref:TAB_1
| ------------- |:-------------:| -----:|
| Row 1         | AA-AA         | AA-AA |

| Rows id       | B1            | B2    |
| ------------- |:-------------:| -----:|
| Row 1         | @@TAB_1@@     | BB-BB |
Enter fullscreen mode Exit fullscreen mode

Alt Text

Extending it

With this easy block declaration, you can imaging that adding a new plugin will be easy. For example, we provide the Mermaid plugin for Marks.

[mermaid] {{
graph LR
    A[Hard edge] -->|Link text| B(Round edge)
    B --> C{Decision}
    C -->|One| D[Result one]
    C -->|Two| E[Result two]
Enter fullscreen mode Exit fullscreen mode

Alt Text


If you liked this article and want to know more, feel free to follow links


Npm package


Enjoy 😄

Discussion (0)

Editor guide