CommonMark + GFM compatible Markdown parser and renderer
Clone or download
kivikakk add example from readme
Good to know that it'll pass.
Latest commit 5b375c2 Nov 26, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples add example from readme Nov 27, 2018
hooks Only run precommit if demanded Apr 11, 2017
script add example from readme Nov 27, 2018
src correct most strikethrough cases Nov 26, 2018
vendor pull more lenient upstream Nov 27, 2018
.editorconfig Add clippy, clean up lots Apr 15, 2017
.gitignore initial Nov 17, 2016
.gitmodules update submodules Jun 20, 2018
.travis.yml Try limiting Travis spam? Sep 14, 2017
COPYING copyright year extension Jan 19, 2018
Cargo.toml 0.4.0 Nov 27, 2018
Makefile prepare-regexes not needed with pest Jan 21, 2018
README.md 0.4.0 Nov 27, 2018
changelog.txt 0.4.0 Nov 27, 2018
rustfmt.toml rustfmt_skip Nov 9, 2017
spec_out.txt up to date with latest spec Oct 4, 2018

README.md

Build Status Spec Status: 654/654 crates.io version docs.rs

Rust port of github's cmark-gfm.

Installation

Specify it as a requirement in Cargo.toml:

[dependencies]
comrak = "0.4"

Usage

A binary is included which does everything you typically want:

$ comrak --help
comrak 0.4.0
Ashe Connor <kivikakk@github.com>
A 100% CommonMark-compatible GitHub Flavored Markdown parser and formatter

USAGE:
    comrak [FLAGS] [OPTIONS] [--] [FILE]...

FLAGS:
        --github-pre-lang    Use GitHub-style <pre lang> for code blocks
        --hardbreaks         Treat newlines as hard line breaks
    -h, --help               Prints help information
        --smart              Use smart punctuation
        --unsafe             Allow raw HTML and dangerous URLs
    -V, --version            Prints version information

OPTIONS:
        --default-info-string <INFO>    Default value for fenced code block's info strings if none is given
    -e, --extension <EXTENSION>...      Specify an extension name to use [possible values: strikethrough, tagfilter,
                                        table, autolink, tasklist, superscript, footnotes, description-lists]
    -t, --to <FORMAT>                   Specify output format [default: html]  [possible values: html, commonmark]
        --header-ids <PREFIX>           Use the Comrak header IDs extension, with the given ID prefix
        --width <WIDTH>                 Specify wrap width (0 = nowrap) [default: 0]

ARGS:
    <FILE>...    The CommonMark file to parse; or standard input if none passed

And there's a Rust interface. You can use comrak::markdown_to_html directly:

use comrak::{markdown_to_html, ComrakOptions};
assert_eq!(markdown_to_html("Hello, **世界**!", &ComrakOptions::default()),
           "<p>Hello, <strong>世界</strong>!</p>\n");

Or you can parse the input into an AST yourself, manipulate it, and then use your desired formatter:

extern crate comrak;
use comrak::{parse_document, format_html, Arena, ComrakOptions};
use comrak::nodes::{AstNode, NodeValue};

// The returned nodes are created in the supplied Arena, and are bound by its lifetime.
let arena = Arena::new();

let root = parse_document(
    &arena,
    "This is my input.\n\n1. Also my input.\n2. Certainly my input.\n",
    &ComrakOptions::default());

fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &F)
    where F : Fn(&'a AstNode<'a>) {
    f(node);
    for c in node.children() {
        iter_nodes(c, f);
    }
}

iter_nodes(root, &|node| {
    match &mut node.data.borrow_mut().value {
        &mut NodeValue::Text(ref mut text) => {
            let orig = std::mem::replace(text, vec![]);
            *text = String::from_utf8(orig).unwrap().replace("my", "your").as_bytes().to_vec();
        }
        _ => (),
    }
});

let mut html = vec![];
format_html(root, &ComrakOptions::default(), &mut html).unwrap();

assert_eq!(
    String::from_utf8(html).unwrap(),
    "<p>This is your input.</p>\n\
     <ol>\n\
     <li>Also your input.</li>\n\
     <li>Certainly your input.</li>\n\
     </ol>\n");

Security

As with cmark-gfm, Comrak will scrub raw HTML and potentially dangerous links. This change was introduced in Comrak 0.4.0 in support of a safe-by-default posture.

To allow these, use the unsafe_ option (or --unsafe with the command line program). If doing so, we recommend the use of a sanitisation library like ammonia configured specific to your needs.

Extensions

Comrak supports the five extensions to CommonMark defined in the GitHub Flavored Markdown Spec:

as well as superscript, footnotes, and description lists.

By default none are enabled; they are individually enabled with each parse by setting the appropriate values in the ComrakOptions struct.

Related projects

Comrak's design goal is to model the upstream cmark-gfm as closely as possible in terms of code structure. The upside of this is that a change in cmark-gfm has a very predictable change in Comrak. It helps that I maintain both, and tend to update Comrak in lock-step with cmark-gfm. Likewise, any bug in cmark-gfm is likely to be reproduced in Comrak. This could be considered a pro or a con, depending on your use case.

The downside, of course, is that the code is not what I'd call idiomatic Rust (so many RefCells), and while contributors and I have made it as fast as possible, it simply won't be as fast as some other CommonMark parsers depending on your use-case. Here are some other projects to consider:

  • Raph Levien's pulldown-cmark. It's very fast, uses a novel parsing algorithm, and doesn't construct an AST (but you can use it to make one if you want). Recent cargo doc uses this, as do many other projects in the ecosystem. It's not quite at 100% spec compatibility yet.
  • Ben Navetta's rcmark is a set of bindings to libcmark. It hasn't been updated in a while, though there's an open pull request.
  • Know of another library? Please add it!

As far as I know, Comrak is the only library to implement all of the GitHub Flavored Markdown extensions to the spec, but this tends to only be important if you want to reproduce GitHub's Markdown rendering exactly, e.g. in a GitHub client app.

Contributors

Thank you for PRs and issues opened!

Legal

Copyright (c) 2017–2018, Ashe Connor. Licensed under the 2-Clause BSD License.

cmark itself is is copyright (c) 2014, John MacFarlane.

See COPYING for all the details.