Crystal C bindings for cmark-gfm, with support for Github Flavored Markdown (v0.29.0.gfm.8). For more information regarding the available options and extensions see the official GFM spec documentation.
Features:
Add the dependency to your shard.yml
and then run shards install
:
dependencies:
cmark:
github: amauryt/cr-cmark-gfm
version: ~> 0.1.3
This will automatically clone the cmark-gfm repository and compile both libcmark-gfm
and libcmark-gfm-extensions
, which can then be 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 = File.read("commonmark_only.md")
full_gfm = File.read("full_gfm.md")
partially_gfm = File.read("partially_gfm.md")
# 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)
require "cmark"
include Cmark
contents = NodeMaker.strong
contents.append_child NodeMaker.text("click here")
node = NodeMaker.link(url: "http://example.com", title: "Example")
node.append_child(contents)
node.type.link? # => true
node.url # => http://example.com
node.title # => "Example"
node.title = "My Example"
node.render_commonmark # => [**click here**](http://example.com "My Example")
node.render_plaintext # => click here
# 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
last_child.next # => <Cmark::Node::Text>
iterator = EventIterator.new(node)
iterator.each do |event|
node = event.node
if event.enter?
puts "entering node"
end
if event.modifiable? && node.type.strong?
# Transform strong text into unformatted text
text_node = node.first_child.not_nil!
node.parent.not_nil!.prepend_child(text_node)
node.unlink
end
end
node.render_commonmark # => [click here](http://example.com "My Example")
class MyHTMLRenderer < Cmark::HTMLRenderer
# Container nodes receive `node` and `entering`
def strong(node, entering)
if entering
out "<b>"
else
out "</b>"
end
end
# Leaf nodes only receive `node`
def text(node)
out node.literal.gsub("click", "don't click")
end
end
# 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 = MyHTMLRenderer.new(options, extensions)
html = renderer.render(node)
html # => <a href="http://example.com" title="My Example"><b>don't click here</b></a>
Other alternatives (from which this shard took inspiration) are:
git checkout -b my-new-feature
)git commit -am 'Add some feature'
)git push origin my-new-feature
)