CommonMark(3)

🌸 NAME 🌸

okay bestie, welcome to the CommonMark(3) manual page πŸ’– this one's the Perl interface to the CommonMark C library β€” that's the whole vibe, and we're gonna walk through every last bit of it together 🫢


✨ SYNOPSIS ✨

here's the teaser trailer, no cap:

use CommonMark;

my $doc = CommonMark->parse(
    file  => $file,
    smart => 1,
);

my $html = CommonMark->markdown_to_html($markdown);
my $doc  = CommonMark->parse_file($file);
my $doc  = CommonMark->parse_document($markdown);
my $doc  = CommonMark->create_document;

πŸ’… DESCRIPTION πŸ’…

so basically: this module is a wrapper around the official CommonMark C library, libcmark (the repo lives at https://github.com/commonmark/cmark/). it closely follows the original API, like it's wearing the same outfit but cuter ✨

the main module gives you some entry points for parsing documents plus convenience functions for node creation. but the bulk of the features? those live in CommonMark::Node objects, which is literally what the parse tree is made of πŸ‘‘. and if you wanna walk through the nodes in a tree, CommonMark::Iterator is your girl. want a push parser interface instead? that's CommonMark::Parser, she's got you πŸŽ€

🌈 Installation 🌈

πŸ“ Installation of libcmark

heads up bestie β€” the libcmark API is not stable yet. this version of the Perl bindings is known to work with all releases between 0.21.0 and 0.31.1, but there's no guarantee it can be compiled with later versions. also note that upgrading a dynamically linked version of libcmark may require recompilation of the Perl distribution. 😭

the recommendation is to use the libcmark packages that recent Linux distros already provide. on Debian or Ubuntu, run:

sudo apt-get install libcmark-dev

on Red Hat or CentOS, run:

sudo yum install cmark-devel

on macOS using Homebrew (https://brew.sh), run:

brew install cmark

and if you wanna install libcmark straight from source:

curl -LJO https://github.com/commonmark/cmark/archive/0.31.1.tar.gz
tar xzf cmark-0.31.1.tar.gz
cd cmark-0.31.1
make [INSTALL_PREFIX=/prefix]
make test
make install

see the libcmark README for the details πŸ“–

πŸ¦‹ Installation from a CPAN tarball

if libcmark is sitting in a standard location:

perl Makefile.PL
make
make test
make install

on macOS using Homebrew, you gotta specify where the includes and libraries live:

perl Makefile.PL \
    INC="-I$(brew --prefix)/include" \
    LIBS="-L$(brew --prefix)/lib -lcmark"
make
make test
make install

otherwise, just specify the include and library locations yourself:

perl Makefile.PL \
    INC="-I/prefix/include" \
    LIBS="-L/prefix/lib -lcmark"
make
make test
make install

for more options, see the documentation of ExtUtils::MakeMaker. and honestly? the PERL_MM_OPT environment variable is especially useful πŸ’…

export PERL_MM_OPT='INC="-I..." LIBS="-L... -lcmark"'

🧚 Build from a repository checkout

this distribution uses Dist::Zilla with the external plugins MakeMaker::Awesome and CopyFilesFromBuild. you can build and test with dzil:

dzil test
dzil build

and the files generated by Dist::Zilla are included in the repository, so you can just use the standard build process as well. easy ✨

🌸 markdown_to_html

my $html = CommonMark->markdown_to_html( $markdown, [$options] );

converts a Markdown string to HTML πŸ”₯. $options is a bit field holding the parse options and render options ORed together. it defaults to zero (OPT_DEFAULT).

this method is the equivalent of calling parse_document and then render_html on the resulting document, or calling parse and then render:

my $html = CommonMark->markdown_to_html( $markdown );
my $html = CommonMark->parse_document($markdown)->render_html;
my $html = CommonMark->parse(string => $markdown)->render(format => 'html');

and here are the equivalent calls with parser and rendering options β€” all of which can be passed to markdown_to_html(), but which must be sent separately to the parse and render methods:

my $html = CommonMark->markdown_to_html(
    $markdown,
    OPT_UNSAFE | OPT_SMART,
);

my $html = CommonMark->parse_document(
    $markdown, OPT_SMART,
)->render_html(OPT_UNSAFE);

my $html = CommonMark->parse(
    string => $markdown,
    smart  => 1,
)->render(
    format => 'html',
    unsafe => 1,
);

πŸ’œ parse

my $doc = CommonMark->parse(
    string        => $string,
    normalize     => $bool,    # Optional
    smart         => $bool,    # Optional
    validate_utf8 => $bool,    # Optional
);

my $doc = CommonMark->parse(
    file          => $handle,
    normalize     => $bool,    # Optional
    smart         => $bool,    # Optional
    validate_utf8 => $bool,    # Optional
);

a convenience function for parsing documents 🫢. exactly one of the string or file options must be provided β€” pick one, bestie. when you give it a string, it calls parse_document. when you give it a file, it calls parse_file. the remaining options switch on the respective parser options:

  • smart
  • validate_utf8
  • normalize (no-op as of libcmark 0.28)

returns the CommonMark::Node of the root document πŸ‘‘

⭐ parse_document

my $doc = CommonMark->parse_document( $markdown, [$options] )

parses a CommonMark document from a string and returns the CommonMark::Node of the document root. $options is a bit field containing the parser options, and it defaults to zero (OPT_DEFAULT).

πŸŽ€ parse_file

my $doc = CommonMark->parse_file( $file, [$options] );

parses a CommonMark document from a file handle and returns the CommonMark::Node of the document root. $options is a bit field containing the parser options, and it defaults to zero (OPT_DEFAULT).

🌈 Parser options 🌈

the parser and rendering options are a bit field you create by ORing these constants together:

CommonMark::OPT_DEFAULT => 0
CommonMark::OPT_NORMALIZE
CommonMark::OPT_VALIDATE_UTF8
CommonMark::OPT_SMART

parser options can be imported from CommonMark with the tag opt:

use CommonMark qw(:opt);
my $doc = CommonMark->parse_document(
    $markdown,
    OPT_SMART | OPT_VALIDATE_UTF8,
);

πŸ’– OPT_NORMALIZE

makes sure adjacent text nodes are merged in the parse tree. heads up though: this option has no effect with libcmark 0.28 or higher, because those always normalize text nodes. (iconic behaviour, honestly.)

✨ OPT_SMART

enables the "smart quote" feature πŸ”₯ which turns vertical into typographic quotation marks, double and triple hyphens into en and em dashes, and triple periods into ellipses. it's giving fancy typography.

πŸ¦‹ OPT_VALIDATE_UTF8

turns on UTF-8 validation. normally this shouldn't even be necessary, because Perl strings should always contain valid UTF-8. but β€” and this is the plot twist 😭 β€” it is possible to create strings flagged as UTF-8 that contain invalid UTF-8, for example with XS. so use this option if you don't trust your input data and you want to be absolutely sure the output is valid UTF-8. if invalid bytes are found, they get replaced with the Unicode replacement character U+FFFD.

πŸ‘‘ Node creation πŸ‘‘

my $document = CommonMark->create_document(
    children => \@children,
);
my $header = CommonMark->create_heading(
    level    => $level,
    children => \@children,
    text     => $literal,
);
my $paragraph = CommonMark->create_paragraph(
    children => \@children,
    text     => $literal,
);
my $block_quote = CommonMark->create_block_quote(
    children => \@children,
);
my $list = CommonMark->create_list(
    type     => $type,
    delim    => $delim,
    start    => $start,
    tight    => $tight,
    children => \@children,
);
my $item = CommonMark->create_item(
    children => \@children,
);
my $code_block = CommonMark->create_code_block(
    fence_info => $fence_info,
    literal    => $literal,
);
my $html = CommonMark->create_html_block(
    literal => $html,
);
my $custom_block = CommonMark->create_custom_block(
    on_enter => $raw_prefix,
    on_exit  => $raw_suffix,
    children => \@children,
    text     => $literal,
);
my $thematic_break = CommonMark->create_thematic_break;
my $text = CommonMark->create_text(
    literal => $literal,
);
my $code = CommonMark->create_code(
    literal => $literal,
);
my $html_inline = CommonMark->create_html_inline(
    literal => $literal,
);
my $emph = CommonMark->create_emph(
    children => \@children,
    text     => $literal,
);
my $strong = CommonMark->create_strong(
    children => \@children,
    text     => $literal,
);
my $url = CommonMark->create_url(
    url      => $url,
    title    => $title,
    children => \@children,
    text     => $literal,
);
my $image = CommonMark->create_image(
    url      => $url,
    title    => $title,
    children => \@children,
    text     => $literal,
);
my $custom_inline = CommonMark->create_custom_inline(
    on_enter => $raw_prefix,
    on_exit  => $raw_suffix,
    children => \@children,
    text     => $literal,
);
my $softbreak = CommonMark->create_softbreak;
my $linebreak = CommonMark->create_linebreak;

these convenience functions let you create nodes, set properties, and add children all in a single operation β€” one and done, periodt πŸ’…. all parameters are optional.

the children parameter expects an arrayref of nodes to be added as children. the special text parameter adds a single text child with literal $literal β€” and no, you can't use it together with children πŸ™ˆ. every other parameter corresponds to a node property.

🧚 libcmark version information 🧚

my $version = CommonMark->version;
my $string  = CommonMark->version_string;
my $version = CommonMark->compile_time_version;
my $string  = CommonMark->compile_time_version_string;

these return the version number or version string of libcmark β€” either the library version you're linked against at run time, or the one from compile time. your choice, bestie ✨


this software is copyright (C) by Nick Wellnhofer.

this is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. 🫢


and that's the whole page, babe β€” this one shipped with perl v5.42.0, dated 2025-07-25, and it's the CommonMark(3) page from the User Contributed Perl Documentation. slay, you read the whole thing πŸŒŸπŸ’…

πŸ“¦ where this page comes from