https://github.com/gjtorikian/commonmarker
Ruby wrapper for the comrak (CommonMark parser) Rust crate
https://github.com/gjtorikian/commonmarker
Keywords
commonmark html libcmark
Keywords from Contributors
crash-reporting rubygems activerecord activejob mvc feature-flag rubocop error-monitoring rack feature-toggle
Last synced: about 6 hours ago
JSON representation
Repository metadata
Ruby wrapper for the comrak (CommonMark parser) Rust crate
- Host: GitHub
- URL: https://github.com/gjtorikian/commonmarker
- Owner: gjtorikian
- License: mit
- Created: 2015-05-07T04:06:29.000Z (over 10 years ago)
- Default Branch: main
- Last Pushed: 2025-12-25T17:47:47.000Z (12 days ago)
- Last Synced: 2025-12-27T01:37:48.252Z (11 days ago)
- Topics: commonmark, html, libcmark
- Language: Rust
- Homepage:
- Size: 4.22 MB
- Stars: 518
- Watchers: 11
- Forks: 91
- Open Issues: 5
- Releases: 71
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.txt
README.md
Commonmarker
Ruby wrapper for Rust's comrak crate.
It passes all of the CommonMark test suite, and is therefore spec-complete. It also includes extensions to the CommonMark spec as documented in the GitHub Flavored Markdown spec, such as support for tables, strikethroughs, and autolinking.
[!NOTE]
By default, several extensions not in any spec have been enabled, for the sake of end user convenience when generating HTML.For more information on the available options and extensions, see the documentation below.
Installation
Add this line to your application's Gemfile:
gem 'commonmarker'
And then execute:
$ bundle
Or install it yourself as:
$ gem install commonmarker
Usage
This gem expects to receive UTF-8 strings. Ensure your strings are the right encoding before passing them into Commonmarker.
Converting to HTML
Call to_html on a string to convert it to HTML:
require 'commonmarker'
Commonmarker.to_html('"Hi *there*"', options: {
parse: { smart: true }
})
# => <p>“Hi <em>there</em>”</p>\n
(The second argument is optional--see below for more information.)
Generating a document
You can also parse a string to receive a :document node. You can then print that node to HTML, iterate over the children, and do other fun node stuff. For example:
require 'commonmarker'
doc = Commonmarker.parse("*Hello* world", options: {
parse: { smart: true }
})
puts(doc.to_html) # => <p><em>Hello</em> world</p>\n
doc.walk do |node|
puts node.type # => [:document, :paragraph, :emph, :text, :text]
end
(The second argument is optional--see below for more information.)
When it comes to modifying the document, you can perform the following operations:
insert_beforeinsert_afterprepend_childappend_childdelete
You can also get the source position of a node by calling source_position:
doc = Commonmarker.parse("*Hello* world")
puts doc.first_child.first_child.source_position
# => {:start_line=>1, :start_column=>1, :end_line=>1, :end_column=>7}
You can also modify the following attributes:
urltitleheader_levellist_typelist_startlist_tightfence_info
Example: Walking the AST
You can use walk or each to iterate over nodes:
walkwill iterate on a node and recursively iterate on a node's children.eachwill iterate on a node's direct children, but no further.
require 'commonmarker'
# parse some string
doc = Commonmarker.parse("# The site\n\n [GitHub](https://www.github.com)")
# Walk tree and print out URLs for links
doc.walk do |node|
if node.type == :link
printf("URL = %s\n", node.url)
end
end
# => URL = https://www.github.com
# Transform links to regular text
doc.walk do |node|
if node.type == :link
node.insert_before(node.first_child)
node.delete
end
end
# => <h1><a href=\"#the-site\"></a>The site</h1>\n<p>GitHub</p>\n
Example: Converting a document back into raw CommonMark
You can use to_commonmark on a node to render it as raw text:
require 'commonmarker'
# parse some string
doc = Commonmarker.parse("# The site\n\n [GitHub](https://www.github.com)")
# Transform links to regular text
doc.walk do |node|
if node.type == :link
node.insert_before(node.first_child)
node.delete
end
end
doc.to_commonmark
# => # The site\n\nGitHub\n
Options and plugins
Options
Commonmarker accepts the same parse, render, and extensions options that comrak does, as a hash dictionary with symbol keys:
Commonmarker.to_html('"Hi *there*"', options:{
parse: { smart: true },
render: { hardbreaks: false}
})
Note that there is a distinction in comrak for "parse" options and "render" options, which are represented in the tables below. As well, if you wish to disable any-non boolean option, pass in nil.
Parse options
| Name | Description | Default |
|---|---|---|
smart |
Punctuation (quotes, full-stops and hyphens) are converted into 'smart' punctuation. | false |
default_info_string |
The default info string for fenced code blocks. | "" |
relaxed_tasklist_matching |
Enables relaxing of the tasklist extension matching, allowing any non-space to be used for the "checked" state instead of only x and X. |
false |
relaxed_autolinks |
Enable relaxing of the autolink extension parsing, allowing links to be recognized when in brackets, as well as permitting any url scheme. | false |
leave_footnote_definitions |
Allow footnote definitions to remain in their original positions instead of being moved to the document's end (only affects AST) | false |
Render options
| Name | Description | Default |
|---|---|---|
hardbreaks |
Soft line breaks translate into hard line breaks. | true |
github_pre_lang |
GitHub-style <pre lang="xyz"> is used for fenced code blocks with info tags. |
true |
full_info_string |
Gives info string data after a space in a data-meta attribute on code blocks. |
false |
width |
The wrap column when outputting CommonMark. | 80 |
unsafe |
Allow rendering of raw HTML and potentially dangerous links. | false |
escape |
Escape raw HTML instead of clobbering it. | false |
sourcepos |
Include source position attribute in HTML and XML output. | false |
escaped_char_spans |
Wrap escaped characters in span tags. | true |
ignore_setext |
Ignores setext-style headings. | false |
ignore_empty_links |
Ignores empty links, leaving the Markdown text in place. | false |
gfm_quirks |
Outputs HTML with GFM-style quirks; namely, not nesting <strong> inlines. |
false |
prefer_fenced |
Always output fenced code blocks, even where an indented one could be used. | false |
tasklist_classes |
Add CSS classes to the HTML output of the tasklist extension | false |
As well, there are several extensions which you can toggle in the same manner:
Commonmarker.to_html('"Hi *there*"', options: {
extension: { footnotes: true, description_lists: true },
render: { hardbreaks: false }
})
Extension options
| Name | Description | Default |
|---|---|---|
strikethrough |
Enables the strikethrough extension from the GFM spec. | true |
tagfilter |
Enables the tagfilter extension from the GFM spec. | true |
table |
Enables the table extension from the GFM spec. | true |
autolink |
Enables the autolink extension from the GFM spec. | true |
tasklist |
Enables the task list extension from the GFM spec. | true |
superscript |
Enables the superscript Comrak extension. | false |
header_ids |
Enables the header IDs Comrak extension. from the GFM spec. | "" |
footnotes |
Enables the footnotes extension per cmark-gfm. |
false |
inline_footnotes |
Enables the inline footnotes extension. | false |
description_lists |
Enables the description lists extension. | false |
front_matter_delimiter |
Enables the front matter extension. | "" |
multiline_block_quotes |
Enables the multiline block quotes extension. | false |
math_dollars, math_code |
Enables the math extension. | false |
shortcodes |
Enables the shortcodes extension. | true |
wikilinks_title_before_pipe |
Enables the wikilinks extension, placing the title before the dividing pipe. | false |
wikilinks_title_after_pipe |
Enables the wikilinks extension, placing the title after the dividing pipe. | false |
underline |
Enables the underline extension. | false |
spoiler |
Enables the spoiler extension. | false |
greentext |
Enables the greentext extension. | false |
subtext |
Enables the subtext extension. | false |
subscript |
Enables the subscript extension. | false |
alerts |
Enables the alerts extension. | false |
cjk_friendly_emphasis |
Enables the CJK friendly emphasis extension. | false |
highlight |
Enables highlighting via == |
false |
For more information on these options, see the comrak documentation.
Plugins
In addition to the possibilities provided by generic CommonMark rendering, Commonmarker also supports plugins as a means of
providing further niceties.
Syntax Highlighter Plugin
The library comes with a set of pre-existing themes for highlighting code:
"base16-ocean.dark""base16-eighties.dark""base16-mocha.dark""base16-ocean.light""InspiredGitHub""Solarized (dark)""Solarized (light)"
code = <<~CODE
```ruby
def hello
puts "hello"
end
```
CODE
# pass in a theme name from a pre-existing set
puts Commonmarker.to_html(code, plugins: { syntax_highlighter: { theme: "InspiredGitHub" } })
# <pre style="background-color:#ffffff;" lang="ruby"><code>
# <span style="font-weight:bold;color:#a71d5d;">def </span><span style="font-weight:bold;color:#795da3;">hello
# </span><span style="color:#62a35c;">puts </span><span style="color:#183691;">"hello"
# </span><span style="font-weight:bold;color:#a71d5d;">end
# </span>
# </code></pre>
By default, the plugin uses the "base16-ocean.dark" theme to syntax highlight code.
To disable this plugin, set the value to nil:
code = <<~CODE
```ruby
def hello
puts "hello"
end
```
CODE
Commonmarker.to_html(code, plugins: { syntax_highlighter: nil })
# <pre lang="ruby"><code>def hello
# puts "hello"
# end
# </code></pre>
To output CSS classes instead of style attributes, set the theme key to "":
code = <<~CODE
```ruby
def hello
puts "hello"
end
CODE
Commonmarker.to_html(code, plugins: { syntax_highlighter: { theme: "" } })
# <pre class="syntax-highlighting"><code><span class="source ruby"><span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> # <span class="entity name function ruby">hello</span></span>
# <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">"</span>hello<span class="punctuation definition string end ruby">"</span></span>
# <span class="keyword control ruby">end</span>\n</span></code></pre>
To use a custom theme, you can provide a path to a directory containing .tmtheme files to load:
Commonmarker.to_html(code, plugins: { syntax_highlighter: { theme: "Monokai", path: "./themes" } })
Output formats
Commonmarker can currently only generate output in one format: HTML.
HTML
puts Commonmarker.to_html('*Hello* world!')
# <p><em>Hello</em> world!</p>
Developing locally
After cloning the repo:
script/bootstrap
bundle exec rake compile
If there were no errors, you're done! Otherwise, make sure to follow the comrak dependency instructions.
Benchmarks
❯ bundle exec rake benchmark
input size = 11064832 bytes
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
Warming up --------------------------------------
Markly.render_html 1.000 i/100ms
Markly::Node#to_html 1.000 i/100ms
Commonmarker.to_html 1.000 i/100ms
Commonmarker::Node.to_html
1.000 i/100ms
Kramdown::Document#to_html
1.000 i/100ms
Calculating -------------------------------------
Markly.render_html 15.606 (±25.6%) i/s - 71.000 in 5.047132s
Markly::Node#to_html 15.692 (±25.5%) i/s - 72.000 in 5.095810s
Commonmarker.to_html 4.482 (± 0.0%) i/s - 23.000 in 5.137680s
Commonmarker::Node.to_html
5.092 (±19.6%) i/s - 25.000 in 5.072220s
Kramdown::Document#to_html
0.379 (± 0.0%) i/s - 2.000 in 5.277770s
Comparison:
Markly::Node#to_html: 15.7 i/s
Markly.render_html: 15.6 i/s - same-ish: difference falls within error
Commonmarker::Node.to_html: 5.1 i/s - 3.08x slower
Commonmarker.to_html: 4.5 i/s - 3.50x slower
Kramdown::Document#to_html: 0.4 i/s - 41.40x slower
Owner metadata
- Name: Garen Torikian
- Login: gjtorikian
- Email:
- Kind: user
- Description:
- Website: https://www.gjtorikian.online
- Location: Lenapehoking
- Twitter:
- Company: Yetto
- Icon url: https://avatars.githubusercontent.com/u/64050?u=e41ff60552c0dcda088e5c5c3ed1e3bf34f37dcc&v=4
- Repositories: 407
- Last ynced at: 2025-12-26T04:00:10.229Z
- Profile URL: https://github.com/gjtorikian
GitHub Events
Total
- Create event: 71
- Commit comment event: 2
- Release event: 16
- Issues event: 34
- Watch event: 61
- Delete event: 59
- Issue comment event: 105
- Push event: 90
- Pull request review comment event: 2
- Pull request review event: 3
- Pull request event: 127
- Fork event: 7
Last Year
- Create event: 58
- Commit comment event: 2
- Release event: 12
- Issues event: 27
- Watch event: 49
- Delete event: 48
- Issue comment event: 81
- Push event: 67
- Pull request review event: 2
- Pull request review comment event: 2
- Pull request event: 110
- Fork event: 6
Committers metadata
Last synced: 1 day ago
Total Commits: 890
Total Committers: 39
Avg Commits per committer: 22.821
Development Distribution Score (DDS): 0.448
Commits in past year: 96
Committers in past year: 7
Avg Commits per committer in past year: 13.714
Development Distribution Score (DDS) in past year: 0.552
| Name | Commits | |
|---|---|---|
| Garen J. Torikian | g****n | 491 |
| Ashe Connor | a****e@k****e | 95 |
| dependabot[bot] | 4****] | 75 |
| Yuki Izumi | k****k@g****m | 48 |
| John MacFarlane | j****m@b****u | 47 |
| Yuki Izumi | y****i@k****e | 46 |
| Actions Auto Build | a****s@g****m | 18 |
| Phill MV | p****v@g****m | 9 |
| ojab | o****b@o****u | 8 |
| digitalMoksha | b****t@d****m | 6 |
| Nick Wellnhofer | w****r@a****e | 5 |
| Aaron Harpole | a****e@g****m | 4 |
| Olle Jonsson | o****n@g****m | 3 |
| noraj | a****i@e****m | 3 |
| FUJI Goro (gfx) | g****i@c****g | 2 |
| ppworks | n****9@g****m | 2 |
| Tomoya Chiba | t****p@g****m | 2 |
| Steven Laidlaw | s****n@s****m | 2 |
| Danny Ben Shitrit | db@d****m | 2 |
| Ben Woosley | b****y@g****m | 2 |
| Andrew Anderson | g****w@g****m | 2 |
| stellarpower | s****r@g****m | 1 |
| hagiya0121 | k****1@g****m | 1 |
| diachini | d****y@j****m | 1 |
| Vitaliy Klachkov | b****u@g****m | 1 |
| Ross Kaffenberger | r****f@g****m | 1 |
| Roberto Hidalgo | un@r****x | 1 |
| Peter Goldstein | p****n@g****m | 1 |
| Naoto Kaneko | n****k@g****m | 1 |
| Mu-An ✌️ Chiou | m****n@g****m | 1 |
| and 9 more... | ||
Committer domains:
- github.com: 8
- kivikakk.ee: 2
- dio.jp: 1
- ninegw.sakura.ne.jp: 1
- zitec.com: 1
- inqk.net: 1
- rob.mx: 1
- jetpackworkflow.com: 1
- dannyben.com: 1
- stevenlaidlaw.com: 1
- cpan.org: 1
- europe.com: 1
- aevum.de: 1
- digitalmoksha.com: 1
- ojab.ru: 1
- berkeley.edu: 1
Issue and Pull Request metadata
Last synced: 3 days ago
Total issues: 85
Total pull requests: 252
Average time to close issues: 4 months
Average time to close pull requests: 6 days
Total issue authors: 71
Total pull request authors: 30
Average comments per issue: 3.42
Average comments per pull request: 0.56
Merged pull request: 207
Bot issues: 1
Bot pull requests: 141
Past year issues: 16
Past year pull requests: 92
Past year average time to close issues: 4 days
Past year average time to close pull requests: 1 day
Past year issue authors: 16
Past year pull request authors: 10
Past year average comments per issue: 2.0
Past year average comments per pull request: 0.4
Past year merged pull request: 70
Past year bot issues: 0
Past year bot pull requests: 63
Top Issue Authors
- gjtorikian (5)
- DannyBen (3)
- grosser (2)
- digitalmoksha (2)
- monkeyWzr (2)
- mvz (2)
- noraj (2)
- igorkasyanchuk (2)
- fukayatsu (2)
- GabeIsman (2)
- oboxodo (1)
- zachahn (1)
- amshkv (1)
- ahamelers (1)
- sstur (1)
Top Pull Request Authors
- dependabot[bot] (113)
- gjtorikian (56)
- github-actions[bot] (28)
- kivikakk (11)
- anticomputer (4)
- phillmv (3)
- marius-balteanu (2)
- monkeyWzr (2)
- stellarpower (2)
- ohakutsu (2)
- ppworks (2)
- olleolleolle (2)
- ojab (2)
- JamieMagee (2)
- jhawthorn (2)
Top Issue Labels
- TODO (2)
- help wanted (2)
- breaking (1)
- docs (1)
- bug (1)
- enhancement (1)
- comrak (1)
- release (1)
Top Pull Request Labels
- dependencies (113)
- rust (107)
- release (28)
- github_actions (5)
- ruby (1)
Package metadata
- Total packages: 4
-
Total downloads:
- rubygems: 167,445,484 total
- Total docker downloads: 1,331,685,134
- Total dependent packages: 71 (may contain duplicates)
- Total dependent repositories: 317,895 (may contain duplicates)
- Total versions: 772
- Total maintainers: 2
- Total advisories: 6
gem.coop: commonmarker
A fast, safe, extensible parser for CommonMark. This wraps the comrak Rust crate.
- Homepage: https://github.com/gjtorikian/commonmarker
- Documentation: http://www.rubydoc.info/gems/commonmarker/
- Licenses: MIT
- Latest release: 2.6.0 (published about 1 month ago)
- Last Synced: 2026-01-04T21:01:53.501Z (2 days ago)
- Versions: 334
- Dependent Packages: 0
- Dependent Repositories: 0
- Downloads: 83,698,972 Total
- Docker Downloads: 665,842,567
-
Rankings:
- Dependent repos count: 0.0%
- Dependent packages count: 0.0%
- Average: 0.123%
- Docker downloads count: 0.136%
- Downloads: 0.357%
- Maintainers (2)
-
Funding:
- https://github.com/sponsors/gjtorikian/
rubygems.org: commonmarker
A fast, safe, extensible parser for CommonMark. This wraps the comrak Rust crate.
- Homepage: https://github.com/gjtorikian/commonmarker
- Documentation: http://www.rubydoc.info/gems/commonmarker/
- Licenses: MIT
- Latest release: 2.6.0 (published about 1 month ago)
- Last Synced: 2026-01-05T20:59:09.233Z (1 day ago)
- Versions: 334
- Dependent Packages: 69
- Dependent Repositories: 317,893
- Downloads: 83,746,512 Total
- Docker Downloads: 665,842,567
-
Rankings:
- Dependent repos count: 0.079%
- Docker downloads count: 0.18%
- Dependent packages count: 0.443%
- Downloads: 0.463%
- Average: 1.129%
- Forks count: 2.738%
- Stargazers count: 2.869%
- Maintainers (2)
-
Funding:
- https://github.com/sponsors/gjtorikian/
-
Advisories:
- Duplicate Advisory: Integer overflow in cmark-gfm table parsing extension leads to heap memory corruption
- Several quadratic complexity bugs may lead to denial of service in Commonmarker
- Commonmarker vulnerable to to several quadratic complexity bugs that may lead to denial of service
- Several quadratic complexity bugs may lead to denial of service in Commonmarker
- Unbounded resource exhaustion in cmark-gfm autolink extension may lead to denial of service
- Integer overflow in cmark-gfm table parsing extension leads to heap memory corruption
proxy.golang.org: github.com/gjtorikian/commonmarker
- Homepage:
- Documentation: https://pkg.go.dev/github.com/gjtorikian/commonmarker#section-documentation
- Licenses: mit
- Latest release: v2.6.0+incompatible (published about 1 month ago)
- Last Synced: 2026-01-03T20:03:30.085Z (3 days ago)
- Versions: 101
- Dependent Packages: 0
- Dependent Repositories: 0
-
Rankings:
- Forks count: 2.681%
- Stargazers count: 2.88%
- Average: 6.075%
- Dependent packages count: 8.466%
- Dependent repos count: 10.274%
conda-forge.org: rb-commonmarker
- Homepage: https://rubygems.org/gems/commonmarker
- Licenses: MIT
- Latest release: 0.20.2 (published about 6 years ago)
- Last Synced: 2026-01-03T20:03:29.503Z (3 days ago)
- Versions: 3
- Dependent Packages: 2
- Dependent Repositories: 2
-
Rankings:
- Dependent packages count: 19.607%
- Forks count: 20.041%
- Average: 20.143%
- Dependent repos count: 20.265%
- Stargazers count: 20.66%
Dependencies
- benchmark-ips >= 0 development
- kramdown >= 0 development
- redcarpet >= 0 development
- awesome_print >= 0 development
- json ~> 2.3 development
- minitest ~> 5.6 development
- minitest-focus ~> 1.1 development
- rake >= 0 development
- rake-compiler ~> 0.9 development
- rdoc ~> 6.2 development
- rubocop >= 0 development
- rubocop-standard >= 0 development
- dependabot/fetch-metadata v1 composite
- actions/checkout v3 composite
- actions/download-artifact v3 composite
- actions/upload-artifact v3 composite
- oxidize-rb/actions/setup-ruby-and-rust main composite
- oxidize-rb/cross-gem-action main composite
- ruby/setup-ruby v1 composite
- actions/checkout v3 composite
- ruby/setup-ruby v1 composite
- actions/checkout v3 composite
- actions/download-artifact v3 composite
- oxidize-rb/actions/setup-ruby-and-rust main composite
- oxidize-rb/cross-gem-action main composite
- ruby/setup-ruby v1 composite
- actions/checkout v3 composite
- gjtorikian/actions/setup-ruby-and-rust main composite
- 119 dependencies
Score: 31.051507409376093