C bindings for cmark-gfm to work with Commonmark and Github Flavored Markdown commonmark gfm markdown
0.1.1 Latest release released


Crystal CI Docs

Crystal C bindings for cmark-gfm, with support for the latest version of Github Flavored Markdown (v0.29.0.gfm.2). For more information regarding the available options and extensions see the official GFM spec documentation.


  • Simple parsing and rendering of markdown content
  • Render any node of the markdown AST in the following formats:
    • HTML
    • XML
    • Plaintext
    • Commonmark (including GFM-only nodes)
    • Groff man pages
    • LaTeX
  • Create custom renderers or customize the included crystal HTML renderer, which outputs the same HTML as the library's C renderer
  • Getters and setters for almost all of the properties of AST nodes
  • Tree traversal and manipulation
  • Directly create and customize nodes


Add the dependency to your shard.yml and then run shards install:

    github: amauryt/cr-cmark-gfm

This will automatically clone the cmark-gfm repository and compile both libcmark-gfm and libcmark-gfm-extensions, which will be then statically linked.


The Cmark module offers high-level parsing and rendering of markdown content, be it Commonmark-only, full GFM, or partially GFM.

If the content is Commonmark-only use the respective commonmark parsing and HTML rendering methods for the best performance. If all of the GFM extensions must be enabled use the gfm methods. For partial support of GFM extensions use the more generic document methods.

require "cmark"

options = Option.flags(Nobreaks, ValidateUTF8) # deafult is Option::None
extensions = Extension.flags(Table, Tasklist)  # default is Extension::None

commonmark_only ="")
full_gfm ="")
partially_gfm ="")

# Direct parsing and rendering

commonmark_only_html  = Cmark.commonmark_to_html(commonmark_only, options)
full_gfm_html         = Cmark.gfm_to_html(full_gfm, options)
partially_gfm_html    = Cmark.document_to_html(partially_gfm, options, extensions)

# Parse to obtain a document node for further processing

commonmark_only_node  = Cmark.parse_commonmark(commonmark_only, options)
full_gfm_node         = Cmark.parse_gfm(full_gfm, options)
partially_gfm_node    = Cmark.parse_document(partially_gfm, options, extensions)

Node creation and rendering

require "cmark"
include Cmark

contents = NodeMaker.strong
contents.append_child NodeMaker.text("click here")
node = "", title: "Example")
node.append_child(contents) # => true
node.url # =>
node.title # => "Example"
node.title = "My Example"

node.render_commonmark # => [**click here**]( "My Example")
node.render_plaintext # => click here

Tree traversal and manipulation

# Using the node from the previous example

node.previous # => nil
node.first_child # => <Cmark::Node::Strong>
last_child =  node.last_child.not_nil!
last_child == node.first_child # => true # => <Cmark::Node::Text>

iterator =

iterator.each do |event|
  node = event.node
  if event.enter?
    puts "entering node"
  if event.modifiable? && node.type.strong?
    # Transform strong text into unformatted text
    text_node = node.first_child.not_nil!

node.render_commonmark # => [click here]( "My Example")

Custom rendering

class MyHTMLRenderer < Cmark::HTMLRenderer
  # Container nodes receive `node` and `entering`
  def strong(node, entering)
    if entering
      out "<b>"
      out "</b>"

  # Leaf nodes only receive `node`
  def text(node)
    out node.literal.gsub("click", "don't click")

# Using the node from the "Node creation and rendering" example

options = Option.flags(Nobreaks, ValidateUTF8) # default is Option::None
extensions = Extension.flags(Table, Tasklist) # default is Extension::None

renderer =, extensions)
html = renderer.render(node)
html # => <a href="" title="My Example"><b>don't click here</b></a>


Now that that the Crystal language (subset of) Markdown is no longer part of the public API in the standard library, other alternatives (from which this shard took inspiration) are:


  1. Fork it (
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request


  github: amauryt/cr-cmark-gfm
  version: ~> 0.1.1
License BSD-2-Clause
Crystal >= 0.31.1


  • Amaury Trujillo

Dependencies 0

Development Dependencies 0

Last synced .
search fire star recently