{"id":13880559,"url":"https://github.com/gjtorikian/commonmarker","last_synced_at":"2025-05-13T20:22:20.018Z","repository":{"id":31632808,"uuid":"35197979","full_name":"gjtorikian/commonmarker","owner":"gjtorikian","description":"Ruby wrapper for the comrak (CommonMark parser) Rust crate","archived":false,"fork":false,"pushed_at":"2025-05-05T13:20:17.000Z","size":4310,"stargazers_count":465,"open_issues_count":3,"forks_count":87,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-05-05T14:35:24.404Z","etag":null,"topics":["commonmark","html","libcmark"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gjtorikian.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.txt","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"gjtorikian"}},"created_at":"2015-05-07T04:06:29.000Z","updated_at":"2025-05-05T13:20:20.000Z","dependencies_parsed_at":"2023-12-23T19:12:52.733Z","dependency_job_id":"bfb549de-a6bd-401d-a8c1-cfd49dcf32df","html_url":"https://github.com/gjtorikian/commonmarker","commit_stats":{"total_commits":765,"total_committers":41,"mean_commits":"18.658536585365855","dds":0.7084967320261437,"last_synced_commit":"58d4c910112df2aab84e193841051b616ea08e6e"},"previous_names":[],"tags_count":124,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gjtorikian%2Fcommonmarker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gjtorikian%2Fcommonmarker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gjtorikian%2Fcommonmarker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gjtorikian%2Fcommonmarker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gjtorikian","download_url":"https://codeload.github.com/gjtorikian/commonmarker/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252532588,"owners_count":21763433,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commonmark","html","libcmark"],"created_at":"2024-08-06T08:03:12.437Z","updated_at":"2025-05-13T20:22:19.983Z","avatar_url":"https://github.com/gjtorikian.png","language":"Rust","funding_links":["https://github.com/sponsors/gjtorikian"],"categories":["Rust"],"sub_categories":[],"readme":"# Commonmarker\n\nRuby wrapper for Rust's [comrak](https://github.com/kivikakk/comrak) crate.\n\nIt 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](http://github.github.com/gfm/), such as support for tables, strikethroughs, and autolinking.\n\n\u003e [!NOTE]\n\u003e By default, several extensions not in any spec have been enabled, for the sake of end user convenience when generating HTML.\n\u003e\n\u003e For more information on the available options and extensions, see [the documentation below](#options-and-plugins).\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n    gem 'commonmarker'\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install commonmarker\n\n## Usage\n\nThis gem expects to receive UTF-8 strings. Ensure your strings are the right encoding before passing them into `Commonmarker`.\n\n### Converting to HTML\n\nCall `to_html` on a string to convert it to HTML:\n\n```ruby\nrequire 'commonmarker'\nCommonmarker.to_html('\"Hi *there*\"', options: {\n    parse: { smart: true }\n})\n# =\u003e \u003cp\u003e“Hi \u003cem\u003ethere\u003c/em\u003e”\u003c/p\u003e\\n\n```\n\n(The second argument is optional--[see below](#options-and-plugins) for more information.)\n\n### Generating a document\n\nYou 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:\n\n```ruby\nrequire 'commonmarker'\n\ndoc = Commonmarker.parse(\"*Hello* world\", options: {\n    parse: { smart: true }\n})\nputs(doc.to_html) # =\u003e \u003cp\u003e\u003cem\u003eHello\u003c/em\u003e world\u003c/p\u003e\\n\n\ndoc.walk do |node|\n  puts node.type # =\u003e [:document, :paragraph, :emph, :text, :text]\nend\n```\n\n(The second argument is optional--[see below](#options-and-plugins) for more information.)\n\nWhen it comes to modifying the document, you can perform the following operations:\n\n- `insert_before`\n- `insert_after`\n- `prepend_child`\n- `append_child`\n- `delete`\n\nYou can also get the source position of a node by calling `source_position`:\n\n```ruby\ndoc = Commonmarker.parse(\"*Hello* world\")\nputs doc.first_child.first_child.source_position\n# =\u003e {:start_line=\u003e1, :start_column=\u003e1, :end_line=\u003e1, :end_column=\u003e7}\n```\n\nYou can also modify the following attributes:\n\n- `url`\n- `title`\n- `header_level`\n- `list_type`\n- `list_start`\n- `list_tight`\n- `fence_info`\n\n#### Example: Walking the AST\n\nYou can use `walk` or `each` to iterate over nodes:\n\n- `walk` will iterate on a node and recursively iterate on a node's children.\n- `each` will iterate on a node's direct children, but no further.\n\n```ruby\nrequire 'commonmarker'\n\n# parse some string\ndoc = Commonmarker.parse(\"# The site\\n\\n [GitHub](https://www.github.com)\")\n\n# Walk tree and print out URLs for links\ndoc.walk do |node|\n  if node.type == :link\n    printf(\"URL = %s\\n\", node.url)\n  end\nend\n# =\u003e URL = https://www.github.com\n\n# Transform links to regular text\ndoc.walk do |node|\n  if node.type == :link\n    node.insert_before(node.first_child)\n    node.delete\n  end\nend\n# =\u003e \u003ch1\u003e\u003ca href=\\\"#the-site\\\"\u003e\u003c/a\u003eThe site\u003c/h1\u003e\\n\u003cp\u003eGitHub\u003c/p\u003e\\n\n```\n\n#### Example: Converting a document back into raw CommonMark\n\nYou can use `to_commonmark` on a node to render it as raw text:\n\n```ruby\nrequire 'commonmarker'\n\n# parse some string\ndoc = Commonmarker.parse(\"# The site\\n\\n [GitHub](https://www.github.com)\")\n\n# Transform links to regular text\ndoc.walk do |node|\n  if node.type == :link\n    node.insert_before(node.first_child)\n    node.delete\n  end\nend\n\ndoc.to_commonmark\n# =\u003e # The site\\n\\nGitHub\\n\n```\n\n## Options and plugins\n\n### Options\n\nCommonmarker accepts the same parse, render, and extensions options that comrak does, as a hash dictionary with symbol keys:\n\n```ruby\nCommonmarker.to_html('\"Hi *there*\"', options:{\n  parse: { smart: true },\n  render: { hardbreaks: false}\n})\n```\n\nNote 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`.\n\n### Parse options\n\n| Name                        | Description                                                                                                                                 | Default |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------- |\n| `smart`                     | Punctuation (quotes, full-stops and hyphens) are converted into 'smart' punctuation.                                                        | `false` |\n| `default_info_string`       | The default info string for fenced code blocks.                                                                                             | `\"\"`    |\n| `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` |\n| `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` |\n\n### Render options\n\n| Name                 | Description                                                                                            | Default |\n| -------------------- | ------------------------------------------------------------------------------------------------------ | ------- |\n| `hardbreaks`         | [Soft line breaks](http://spec.commonmark.org/0.27/#soft-line-breaks) translate into hard line breaks. | `true`  |\n| `github_pre_lang`    | GitHub-style `\u003cpre lang=\"xyz\"\u003e` is used for fenced code blocks with info tags.                         | `true`  |\n| `full_info_string`   | Gives info string data after a space in a `data-meta` attribute on code blocks.                        | `false` |\n| `width`              | The wrap column when outputting CommonMark.                                                            | `80`    |\n| `unsafe`             | Allow rendering of raw HTML and potentially dangerous links.                                           | `false` |\n| `escape`             | Escape raw HTML instead of clobbering it.                                                              | `false` |\n| `sourcepos`          | Include source position attribute in HTML and XML output.                                              | `false` |\n| `escaped_char_spans` | Wrap escaped characters in span tags.                                                                  | `true`  |\n| `ignore_setext`      | Ignores setext-style headings.                                                                         | `false` |\n| `ignore_empty_links` | Ignores empty links, leaving the Markdown text in place.                                               | `false` |\n| `gfm_quirks`         | Outputs HTML with GFM-style quirks; namely, not nesting `\u003cstrong\u003e` inlines.                            | `false` |\n| `prefer_fenced`      | Always output fenced code blocks, even where an indented one could be used.                            | `false` |\n| `tasklist_classes`   | Add CSS classes to the HTML output of the tasklist extension                                           | `false` |\n\nAs well, there are several extensions which you can toggle in the same manner:\n\n```ruby\nCommonmarker.to_html('\"Hi *there*\"', options: {\n    extension: { footnotes: true, description_lists: true },\n    render: { hardbreaks: false }\n})\n```\n\n### Extension options\n\n| Name                          | Description                                                                                                         | Default |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------- |\n| `strikethrough`               | Enables the [strikethrough extension](https://github.github.com/gfm/#strikethrough-extension-) from the GFM spec.   | `true`  |\n| `tagfilter`                   | Enables the [tagfilter extension](https://github.github.com/gfm/#disallowed-raw-html-extension-) from the GFM spec. | `true`  |\n| `table`                       | Enables the [table extension](https://github.github.com/gfm/#tables-extension-) from the GFM spec.                  | `true`  |\n| `autolink`                    | Enables the [autolink extension](https://github.github.com/gfm/#autolinks-extension-) from the GFM spec.            | `true`  |\n| `tasklist`                    | Enables the [task list extension](https://github.github.com/gfm/#task-list-items-extension-) from the GFM spec.     | `true`  |\n| `superscript`                 | Enables the superscript Comrak extension.                                                                           | `false` |\n| `header_ids`                  | Enables the header IDs Comrak extension. from the GFM spec.                                                         | `\"\"`    |\n| `footnotes`                   | Enables the footnotes extension per `cmark-gfm`.                                                                    | `false` |\n| `description_lists`           | Enables the description lists extension.                                                                            | `false` |\n| `front_matter_delimiter`      | Enables the front matter extension.                                                                                 | `\"\"`    |\n| `multiline_block_quotes`      | Enables the multiline block quotes extension.                                                                       | `false` |\n| `math_dollars`, `math_code`   | Enables the math extension.                                                                                         | `false` |\n| `shortcodes`                  | Enables the shortcodes extension.                                                                                   | `true`  |\n| `wikilinks_title_before_pipe` | Enables the wikilinks extension, placing the title before the dividing pipe.                                        | `false` |\n| `wikilinks_title_after_pipe`  | Enables the shortcodes extension, placing the title after the dividing pipe.                                        | `false` |\n| `underline`                   | Enables the underline extension.                                                                                    | `false` |\n| `spoiler`                     | Enables the spoiler extension.                                                                                      | `false` |\n| `greentext`                   | Enables the greentext extension.                                                                                    | `false` |\n| `subscript`                   | Enables the subscript extension.                                                                                    | `false` |\n| `alerts`                      | Enables the alerts extension.                                                                                       | `false` |\n\nFor more information on these options, see [the comrak documentation](https://github.com/kivikakk/comrak#usage).\n\n### Plugins\n\nIn addition to the possibilities provided by generic CommonMark rendering, Commonmarker also supports plugins as a means of\nproviding further niceties.\n\n#### Syntax Highlighter Plugin\n\nThe library comes with [a set of pre-existing themes](https://docs.rs/syntect/5.0.0/syntect/highlighting/struct.ThemeSet.html#implementations) for highlighting code:\n\n- `\"base16-ocean.dark\"`\n- `\"base16-eighties.dark\"`\n- `\"base16-mocha.dark\"`\n- `\"base16-ocean.light\"`\n- `\"InspiredGitHub\"`\n- `\"Solarized (dark)\"`\n- `\"Solarized (light)\"`\n\n````ruby\ncode = \u003c\u003c~CODE\n  ```ruby\n  def hello\n    puts \"hello\"\n  end\n  ```\nCODE\n\n# pass in a theme name from a pre-existing set\nputs Commonmarker.to_html(code, plugins: { syntax_highlighter: { theme: \"InspiredGitHub\" } })\n\n# \u003cpre style=\"background-color:#ffffff;\" lang=\"ruby\"\u003e\u003ccode\u003e\n# \u003cspan style=\"font-weight:bold;color:#a71d5d;\"\u003edef \u003c/span\u003e\u003cspan style=\"font-weight:bold;color:#795da3;\"\u003ehello\n# \u003c/span\u003e\u003cspan style=\"color:#62a35c;\"\u003eputs \u003c/span\u003e\u003cspan style=\"color:#183691;\"\u003e\u0026quot;hello\u0026quot;\n# \u003c/span\u003e\u003cspan style=\"font-weight:bold;color:#a71d5d;\"\u003eend\n# \u003c/span\u003e\n# \u003c/code\u003e\u003c/pre\u003e\n````\n\nBy default, the plugin uses the `\"base16-ocean.dark\"` theme to syntax highlight code.\n\nTo disable this plugin, set the value to `nil`:\n\n````ruby\ncode = \u003c\u003c~CODE\n  ```ruby\n  def hello\n    puts \"hello\"\n  end\n  ```\nCODE\n\nCommonmarker.to_html(code, plugins: { syntax_highlighter: nil })\n\n# \u003cpre lang=\"ruby\"\u003e\u003ccode\u003edef hello\n#   puts \u0026quot;hello\u0026quot;\n# end\n# \u003c/code\u003e\u003c/pre\u003e\n````\n\nTo output CSS classes instead of `style` attributes, set the `theme` key to `\"\"`:\n\n````ruby\ncode = \u003c\u003c~CODE\n  ```ruby\n  def hello\n    puts \"hello\"\n  end\nCODE\n\nCommonmarker.to_html(code, plugins: { syntax_highlighter: { theme: \"\" } })\n\n# \u003cpre class=\"syntax-highlighting\"\u003e\u003ccode\u003e\u003cspan class=\"source ruby\"\u003e\u003cspan class=\"meta function ruby\"\u003e\u003cspan class=\"keyword control def ruby\"\u003edef\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"meta function ruby\"\u003e # \u003cspan class=\"entity name function ruby\"\u003ehello\u003c/span\u003e\u003c/span\u003e\n#   \u003cspan class=\"support function builtin ruby\"\u003eputs\u003c/span\u003e \u003cspan class=\"string quoted double ruby\"\u003e\u003cspan class=\"punctuation definition string begin ruby\"\u003e\u0026quot;\u003c/span\u003ehello\u003cspan class=\"punctuation definition string end ruby\"\u003e\u0026quot;\u003c/span\u003e\u003c/span\u003e\n# \u003cspan class=\"keyword control ruby\"\u003eend\u003c/span\u003e\\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n````\n\nTo use a custom theme, you can provide a `path` to a directory containing `.tmtheme` files to load:\n\n```ruby\nCommonmarker.to_html(code, plugins: { syntax_highlighter: { theme: \"Monokai\", path: \"./themes\" } })\n```\n\n## Output formats\n\nCommonmarker can currently only generate output in one format: HTML.\n\n### HTML\n\n```ruby\nputs Commonmarker.to_html('*Hello* world!')\n\n# \u003cp\u003e\u003cem\u003eHello\u003c/em\u003e world!\u003c/p\u003e\n```\n\n## Developing locally\n\nAfter cloning the repo:\n\n```\nscript/bootstrap\nbundle exec rake compile\n```\n\nIf there were no errors, you're done! Otherwise, make sure to follow the comrak dependency instructions.\n\n## Benchmarks\n\n```\n❯ bundle exec rake benchmark\ninput size = 11064832 bytes\n\nruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]\nWarming up --------------------------------------\n  Markly.render_html     1.000 i/100ms\nMarkly::Node#to_html     1.000 i/100ms\nCommonmarker.to_html     1.000 i/100ms\nCommonmarker::Node.to_html\n                         1.000 i/100ms\nKramdown::Document#to_html\n                         1.000 i/100ms\nCalculating -------------------------------------\n  Markly.render_html     15.606 (±25.6%) i/s -     71.000 in   5.047132s\nMarkly::Node#to_html     15.692 (±25.5%) i/s -     72.000 in   5.095810s\nCommonmarker.to_html      4.482 (± 0.0%) i/s -     23.000 in   5.137680s\nCommonmarker::Node.to_html\n                          5.092 (±19.6%) i/s -     25.000 in   5.072220s\nKramdown::Document#to_html\n                          0.379 (± 0.0%) i/s -      2.000 in   5.277770s\n\nComparison:\nMarkly::Node#to_html:       15.7 i/s\n  Markly.render_html:       15.6 i/s - same-ish: difference falls within error\nCommonmarker::Node.to_html:        5.1 i/s - 3.08x  slower\nCommonmarker.to_html:        4.5 i/s - 3.50x  slower\nKramdown::Document#to_html:        0.4 i/s - 41.40x  slower\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgjtorikian%2Fcommonmarker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgjtorikian%2Fcommonmarker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgjtorikian%2Fcommonmarker/lists"}