Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/amauryt/cr-cmark-gfm
Crystal C bindings for cmark-gfm to work with Commonmark and Github Flavored Markdown
https://github.com/amauryt/cr-cmark-gfm
commonmark crystal gfm markdown
Last synced: 6 days ago
JSON representation
Crystal C bindings for cmark-gfm to work with Commonmark and Github Flavored Markdown
- Host: GitHub
- URL: https://github.com/amauryt/cr-cmark-gfm
- Owner: amauryt
- License: bsd-2-clause
- Created: 2019-10-14T02:26:14.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2024-09-27T13:16:39.000Z (about 1 month ago)
- Last Synced: 2024-10-06T03:07:18.567Z (about 1 month ago)
- Topics: commonmark, crystal, gfm, markdown
- Language: Crystal
- Size: 455 KB
- Stars: 20
- Watchers: 1
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-crystal - cr-cmark-gfm - Crystal C bindings for cmark-gfm to work with Commonmark and Github Flavored Markdown (Markdown/Text Processors)
README
# cr-cmark-gfm
[![Crystal CI](https://github.com/amauryt/cr-cmark-gfm/actions/workflows/crystal.yml/badge.svg)](https://github.com/amauryt/cr-cmark-gfm/actions/workflows/crystal.yml)
[![Docs](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://amauryt.github.io/cr-cmark-gfm/)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](https://github.github.com/gfm/).
Features:
- 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## Installation
Add the dependency to your `shard.yml` and then run `shards install`:
```yaml
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.
## Usage
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.
```crystal
require "cmark"options = Option.flags(Nobreaks, ValidateUTF8) # deafult is Option::None
extensions = Extension.flags(Table, Tasklist) # default is Extension::Nonecommonmark_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)
```### Node creation and rendering
```crystal
require "cmark"
include Cmarkcontents = 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
```### Tree traversal and manipulation
```crystal
# Using the node from the previous examplenode.previous # => nil
node.first_child # =>
last_child = node.last_child.not_nil!
last_child == node.first_child # => true
last_child.next # =>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
endnode.render_commonmark # => [click here](http://example.com "My Example")
```### Custom rendering
```crystal
class MyHTMLRenderer < Cmark::HTMLRenderer
# Container nodes receive `node` and `entering`
def strong(node, entering)
if entering
out ""
else
out ""
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::Nonerenderer = MyHTMLRenderer.new(options, extensions)
html = renderer.render(node)
html # => don't click here
```## Alternatives
Other alternatives (from which this shard took inspiration) are:
* [markd](https://github.com/icyleaf/markd): A pure Crystal port of [commonmark.js](https://github.com/jgm/commonmark.js). Compliant to Commonmark v0.29, but it has no GFM support.
* [crystal-cmark](https://github.com/ysbaddaden/crystal-cmark): Minimal parsing and rendering C bindings with [cmark](https://github.com/commonmark/cmark) v0.30.2 but without GFM support.
* [crystal-cmark-gfm](https://github.com/mamantoha/crystal-cmark-gfm): Minimal C bindings for parsing and rendering with the latest commit of [cmark-gfm](https://github.com/github/cmark-gfm) (v0.29.0.gfm.x)## Contributing
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## Contributors
- [Amaury Trujillo](https://github.com/amauryt) - creator and maintainer
- [Anton Maminov](https://github.com/mamantoha) - contributor