markd

Language Tag Build Status


Yet another markdown parser built for speed, written in Crystal, Compliant to CommonMark specification (v0.29). Copy from commonmark.js.

Installation

Add this to your application's shard.yml:

dependencies:
  markd:
    github: icyleaf/markd

Quick start

require "markd"

markdown = <<-MD
# Hello Markd

> Yet another markdown parser built for speed, written in Crystal, Compliant to CommonMark specification.
MD

html = Markd.to_html(markdown)

Also here are options to configure the parse and render.

options = Markd::Options.new(smart: true, safe: true)
Markd.to_html(markdown, options)

Options

| Name | Type | Default value | Description | | ----------- | ------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | time | Bool | false | render parse cost time during read source, parse blocks, parse inline. | | smart | Bool | false | if true, straight quotes will be made curly,
-- will be changed to an en dash,
--- will be changed to an em dash, and
... will be changed to ellipses. | | source_pos | Bool | false | if true, source position information for block-level elements
will be rendered in the data-sourcepos attribute (for HTML) | | safe | Bool | false | if true, raw HTML will not be passed through to HTML output (it will be replaced by comments) | | prettyprint | Bool | false | if true, code tags generated by code blocks will have a prettyprint class added to them, to be used by Google code-prettify. | | gfm | Bool | false | Partial support | | autolink | Bool | false | if true, more autolinks are detected, like bare email addresses or http links | | toc | Bool | false | Not supported for now | | emoji | Bool | false | if true, convert Github style emoji chars. | | tagfilter | Bool | false | if true, escape certain HTML tags. | | base_url | URI? | nil | if not nil, relative URLs of links are resolved against this URI. It act's like HTML's <base href="base_url"> in the context of a Markdown document. |

Advanced

If you want to use a custom renderer, it can!


class CustomRenderer < Markd::Renderer

  def strong(node, entering)
  end

  # more methods following in render.
end

options = Markd::Options.new(time: true)
document = Markd::Parser.parse(markdown, options)
renderer = CustomRenderer.new(options)

html = renderer.render(document)

Use tartrazine shards to render code block.

Added and require tartrazine before markd will use it to render code block.

By default, it use formatter like following:

formatter = Tartrazine::Html.new(
  theme: Tartrazine.theme("catppuccin-macchiato"),
  line_numbers: true,
  standalone: true,
)

You can passing a formatter instead.

e.g.

require "tartrazine" # require it before markd
require "markd"

formatter = Tartrazine::Html.new(
  theme: Tartrazine.theme("emacs"),

  # Disable print line number
  line_numbers: false,

  # Set standalone to false for better performace.
  #
  # You need generate css file use `bin/tartrazine -f html -t "emacs" --css`,
  # then link it in you site.
  standalone: false,
)

html = Markd.to_html(markdown,formatter: formatter)

If you don't care about the formatter config, you can just passing a string instead.

require "tartrazine" # require it before markd
require "markd"

html = Markd.to_html(markdown, formatter: "emacs")

Currently Tartrazine supports 247 languages and 331 themes, you can retrieve the supported languages use Tartrazine::LEXERS_BY_NAME.values.uniq.sort, for now the result is:

[
  "LiquidLexer", "VelocityLexer",

  "abap", "abnf", "actionscript", "actionscript_3", "ada", "agda", "al", "alloy", "angular2",
  "antlr",   "apacheconf", "apl", "applescript", "arangodb_aql", "arduino", "armasm",
  "autohotkey", "autoit", "awk",

  "ballerina", "bash", "bash_session", "batchfile", "bbcode", "bibtex", "bicep", "blitzbasic",
  "bnf", "bqn", "brainfuck",

  "c", "c#", "c++", "cap_n_proto", "cassandra_cql", "ceylon", "cfengine3", "cfstatement",
  "chaiscript", "chapel",   "cheetah", "clojure", "cmake", "cobol", "coffeescript",
  "common_lisp", "coq", "crystal", "css", "cue", "cython",

  "d", "dart", "dax", "desktop_entry", "diff", "django_jinja", "dns", "docker", "dtd", "dylan",

  "ebnf", "elixir", "elm", "emacslisp", "erlang",

  "factor", "fennel", "fish", "forth", "fortran", "fortranfixed", "fsharp",

  "gas", "gdscript", "gdscript3", "gherkin", "gleam", "glsl", "gnuplot", "go_template",
  "graphql", "groff", "groovy",

  "handlebars", "hare", "haskell", "hcl", "hexdump", "hlb", "hlsl", "holyc", "html", "hy",

  "idris", "igor", "ini", "io", "iscdhcpd",

  "j", "java", "javascript", "json", "jsonata", "julia", "jungle",

  "kotlin",

  "lighttpd_configuration_file", "llvm", "lua",

  "makefile", "mako", "markdown", "mason", "materialize_sql_dialect", "mathematica", "matlab",
  "mcfunction", "meson", "metal", "minizinc", "mlir", "modula-2", "moinwiki", "monkeyc",
  "morrowindscript", "myghty", "mysql",

  "nasm", "natural", "ndisasm", "newspeak", "nginx_configuration_file", "nim", "nix",

  "objective-c", "objectpascal", "ocaml", "octave", "odin", "onesenterprise", "openedge_abl",
  "openscad", "org_mode",

  "pacmanconf", "perl", "php", "pig", "pkgconfig", "pl_pgsql", "plaintext", "plutus_core",
  "pony", "postgresql_sql_dialect", "postscript", "povray", "powerquery", "powershell",
  "prolog", "promela", "promql", "properties", "protocol_buffer",   "prql", "psl", "puppet",
  "python", "python_2",

  "qbasic", "qml",

  "r", "racket", "ragel", "react", "reasonml", "reg", "rego", "rexx", "rpm_spec", "rst",
  "ruby", "rust",

  "sas", "sass", "scala", "scheme", "scilab", "scss", "sed", "sieve", "smali", "smalltalk",
  "smarty", "snobol", "solidity", "sourcepawn", "sparql", "sql", "squidconf", "standard_ml",
  "stas", "stylus", "swift", "systemd", "systemverilog",

  "tablegen", "tal", "tasm", "tcl", "tcsh", "termcap", "terminfo", "terraform", "tex",
  "thrift",  "toml", "tradingview", "transact-sql", "turing", "turtle", "twig", "typescript",
  "typoscript", "typoscriptcssdata", "typoscripthtmldata",

  "ucode",

  "v", "v_shell", "vala", "vb_net", "verilog", "vhdl", "vhs", "viml", "vue", "wdte",

  "webgpu_shading_language", "whiley",

  "xml", "xorg",

  "yaml", "yang", "z80_assembly",

  "zed", "zig"
]

For details usage, check tartrazine documents.

Performance

Here is the result of a sample markdown file parse at MacBook Pro Retina 2015 (2.2 GHz):

Crystal Markdown (no longer present)   3.28k (305.29µs) (± 0.92%)       fastest
           Markd                       305.36 (  3.27ms) (± 5.52%) 10.73× slower

Recently, I'm working to compare the other popular commonmark parser, the code is stored in benchmarks.

How to Contribute

Your contributions are always welcome! Please submit a pull request or create an issue to add a new question, bug or feature to the list.

All Contributors are on the wall.

You may also like

License

MIT License © icyleaf