cmark(3)
β¨ cmark(3) β¨ β Library Functions Manual π
okay bestie, sit down, sip ur matcha π΅, because this is the page for cmark, the library that does CommonMark parsing, manipulating, and rendering. it's a C library. it's giving main character energy. and you're gonna understand every single bit of it. no cap. π«Ά
πΈ NAME πΈ
cmark β CommonMark parsing, manipulating, and rendering β¨
π DESCRIPTION π
π Simple Interface π
char * cmark_markdown_to_html(const char *text, size_t len, int options)
this one is the glow-up button, fr fr. it takes text (which we assume is a UTF-8 encoded string, with length len) and converts it from CommonMark Markdown into HTML, handing you back a null-terminated, UTF-8-encoded string. π¦
β οΈ bestie listen β it is the caller's responsibility to free the returned buffer. that memory is yours now. take care of it. π
π Node Structure π
here's the whole taxonomy of nodes, the family tree of the document, if you will:
typedef enum {
/* Error status */
CMARK_NODE_NONE,
/* Block */
CMARK_NODE_DOCUMENT,
CMARK_NODE_BLOCK_QUOTE,
CMARK_NODE_LIST,
CMARK_NODE_ITEM,
CMARK_NODE_CODE_BLOCK,
CMARK_NODE_HTML_BLOCK,
CMARK_NODE_CUSTOM_BLOCK,
CMARK_NODE_PARAGRAPH,
CMARK_NODE_HEADING,
CMARK_NODE_THEMATIC_BREAK,
CMARK_NODE_FIRST_BLOCK = CMARK_NODE_DOCUMENT,
CMARK_NODE_LAST_BLOCK = CMARK_NODE_THEMATIC_BREAK,
/* Inline */
CMARK_NODE_TEXT,
CMARK_NODE_SOFTBREAK,
CMARK_NODE_LINEBREAK,
CMARK_NODE_CODE,
CMARK_NODE_HTML_INLINE,
CMARK_NODE_CUSTOM_INLINE,
CMARK_NODE_EMPH,
CMARK_NODE_STRONG,
CMARK_NODE_LINK,
CMARK_NODE_IMAGE,
CMARK_NODE_FIRST_INLINE = CMARK_NODE_TEXT,
CMARK_NODE_LAST_INLINE = CMARK_NODE_IMAGE
} cmark_node_type;
and then the two lil side-enums that describe lists and their delimiters:
typedef enum {
CMARK_NO_LIST,
CMARK_BULLET_LIST,
CMARK_ORDERED_LIST
} cmark_list_type;
typedef enum {
CMARK_NO_DELIM,
CMARK_PERIOD_DELIM,
CMARK_PAREN_DELIM
} cmark_delim_type;
π§ Custom memory allocator support π§
if you're the type of girlie who likes to control her own memory (respect π), here's the struct:
typedef struct cmark_mem {
void *(*calloc)(size_t, size_t);
void *(*realloc)(void *, size_t);
void (*free)(void *);
} cmark_mem;
it defines the memory allocation functions to be used by CMark when parsing and allocating a document tree. π
cmark_mem * cmark_get_default_mem_allocator(void)β returns a pointer to the default memory allocator. easy. iconic. no notes. β¨
π Creating and Destroying Nodes π
cmark_node * cmark_node_new(cmark_node_type type)β creates a new node of typetype. heads up though: the node may have other required properties, and it's your job as the caller to assign them. don't leave it half-dressed bestie πcmark_node * cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem)β same ascmark_node_new, but it explicitly lists the memory allocator used to allocate the node. π
β οΈ note: be sure to use the same allocator for every node in a tree, or bad things can happen. we do not want the bad things. π
void cmark_node_free(cmark_node *node)β frees the memory allocated for a node and any children. the whole bloodline. gone. π
π¦ Tree Traversal π¦
cmark_node * cmark_node_next(cmark_node *node)β returns the next node in the sequence afternode, orNULLif there is none.cmark_node * cmark_node_previous(cmark_node *node)β returns the previous node in the sequence afternode, orNULLif there is none.cmark_node * cmark_node_parent(cmark_node *node)β returns the parent ofnode, orNULLif there is none.cmark_node * cmark_node_first_child(cmark_node *node)β returns the first child ofnode, orNULLifnodehas no children.cmark_node * cmark_node_last_child(cmark_node *node)β returns the last child ofnode, orNULLifnodehas no children.
π Iterator π
okay so an iterator will walk through a tree of nodes, starting from a root node, returning one node at a time, together with info about whether the node is being entered or exited. πΆβοΈ
the iterator will first descend to a child node, if there is one. when there is no child, the iterator will go to the next sibling. when there is no next sibling, the iterator will return to the parent β but with a cmark_event_type of CMARK_EVENT_EXIT. and it returns CMARK_EVENT_DONE when it reaches the root node again. π
one natural application is an HTML renderer, where an ENTER event outputs an open tag and an EXIT event outputs a close tag. an iterator might also be used to transform an AST in some systematic way β for example, turning all level-3 headings into regular paragraphs. obsessed. π
void
usage_example(cmark_node *root) {
cmark_event_type ev_type;
cmark_iter *iter = cmark_iter_new(root);
while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
cmark_node *cur = cmark_iter_get_node(iter);
// Do something with `cur` and `ev_type`
}
cmark_iter_free(iter);
}
β οΈ iterators will never return EXIT events for leaf nodes, which are nodes of type:
CMARK_NODE_HTML_BLOCKCMARK_NODE_THEMATIC_BREAKCMARK_NODE_CODE_BLOCKCMARK_NODE_TEXTCMARK_NODE_SOFTBREAKCMARK_NODE_LINEBREAKCMARK_NODE_CODECMARK_NODE_HTML_INLINE
π¨ and nodes must only be modified after anEXITevent, or anENTERevent for leaf nodes. that's the rule, bestie. don't test it. π
typedef enum {
CMARK_EVENT_NONE,
CMARK_EVENT_DONE,
CMARK_EVENT_ENTER,
CMARK_EVENT_EXIT
} cmark_event_type;
cmark_iter * cmark_iter_new(cmark_node *root)β creates a new iterator starting atroot. the current node and event type are undefined untilcmark_iter_nextis called for the first time. and you should release the memory allocated for the iterator usingcmark_iter_freewhen you're done with it. β¨void cmark_iter_free(cmark_iter *iter)β frees the memory allocated for an iterator. bye girlie πcmark_event_type cmark_iter_next(cmark_iter *iter)β advances to the next node and returns the event type (CMARK_EVENT_ENTER,CMARK_EVENT_EXITorCMARK_EVENT_DONE).cmark_node * cmark_iter_get_node(cmark_iter *iter)β returns the current node.cmark_event_type cmark_iter_get_event_type(cmark_iter *iter)β returns the current event type.cmark_node * cmark_iter_get_root(cmark_iter *iter)β returns the root node.void cmark_iter_reset(cmark_iter *iter, cmark_node *current, cmark_event_type event_type)β resets the iterator so that the current node iscurrentand the event type isevent_type. heads up: the new current node must be a descendant of the root node or the root node itself. no jumping ship π
π«Ά Accessors π«Ά
these are the lil getters and setters, the whole gossip network of the tree π¬
void * cmark_node_get_user_data(cmark_node *node)β returns the user data ofnode.int cmark_node_set_user_data(cmark_node *node, void *user_data)β sets arbitrary user data fornode. returns1on success,0on failure.cmark_node_type cmark_node_get_type(cmark_node *node)β returns the type ofnode, orCMARK_NODE_NONEon error.const char * cmark_node_get_type_string(cmark_node *node)β likecmark_node_get_type, but returns a string representation of the type, or"<unknown>". πconst char * cmark_node_get_literal(cmark_node *node)β returns the string contents ofnode, or an empty string if none is set. returnsNULLif called on a node that does not have string content.int cmark_node_set_literal(cmark_node *node, const char *content)β sets the string contents ofnode. returns1on success,0on failure.int cmark_node_get_heading_level(cmark_node *node)β returns the heading level ofnode, or0ifnodeis not a heading.int cmark_node_set_heading_level(cmark_node *node, int level)β sets the heading level ofnode, returning1on success and0on error.cmark_list_type cmark_node_get_list_type(cmark_node *node)β returns the list type ofnode, orCMARK_NO_LISTifnodeis not a list.int cmark_node_set_list_type(cmark_node *node, cmark_list_type type)β sets the list type ofnode, returning1on success and0on error.cmark_delim_type cmark_node_get_list_delim(cmark_node *node)β returns the list delimiter type ofnode, orCMARK_NO_DELIMifnodeis not a list.int cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim)β sets the list delimiter type ofnode, returning1on success and0on error.int cmark_node_get_list_start(cmark_node *node)β returns starting number ofnode, if it is an ordered list, otherwise0.int cmark_node_set_list_start(cmark_node *node, int start)β sets starting number ofnode, if it is an ordered list. returns1on success,0on failure.int cmark_node_get_list_tight(cmark_node *node)β returns1ifnodeis a tight list,0otherwise.int cmark_node_set_list_tight(cmark_node *node, int tight)β sets the "tightness" of a list. returns1on success,0on failure. the tightness bestie. the vibe check of lists. πconst char * cmark_node_get_fence_info(cmark_node *node)β returns the info string from a fenced code block.int cmark_node_set_fence_info(cmark_node *node, const char *info)β sets the info string in a fenced code block, returning1on success and0on failure.const char * cmark_node_get_url(cmark_node *node)β returns the URL of a link or image node, or an empty string if no URL is set. returnsNULLif called on a node that is not a link or image.int cmark_node_set_url(cmark_node *node, const char *url)β sets the URL of a link or image node. returns1on success,0on failure.const char * cmark_node_get_title(cmark_node *node)β returns the title of a link or image node, or an empty string if no title is set. returnsNULLif called on a node that is not a link or image.int cmark_node_set_title(cmark_node *node, const char *title)β sets the title of a link or image node. returns1on success,0on failure.const char * cmark_node_get_on_enter(cmark_node *node)β returns the literal "on enter" text for a custom node, or an empty string if noon_enteris set. returnsNULLif called on a non-custom node.int cmark_node_set_on_enter(cmark_node *node, const char *on_enter)β sets the literal text to render "on enter" for a custom node. any children of the node will be rendered after this text. returns1on success0on failure.const char * cmark_node_get_on_exit(cmark_node *node)β returns the literal "on exit" text for a custom node, or an empty string if noon_exitis set. returnsNULLif called on a non-custom node.int cmark_node_set_on_exit(cmark_node *node, const char *on_exit)β sets the literal text to render "on exit" for a custom node. any children of the node will be rendered before this text. returns1on success0on failure.int cmark_node_get_start_line(cmark_node *node)β returns the line on whichnodebegins. πint cmark_node_get_start_column(cmark_node *node)β returns the column at whichnodebegins.int cmark_node_get_end_line(cmark_node *node)β returns the line on whichnodeends.int cmark_node_get_end_column(cmark_node *node)β returns the column at whichnodeends.
π Tree Manipulation π
void cmark_node_unlink(cmark_node *node)β unlinks a node, removing it from the tree, but not freeing its memory. (usecmark_node_freefor that, bestie β they're two different jobs π )int cmark_node_insert_before(cmark_node *node, cmark_node *sibling)β insertssiblingbeforenode. returns1on success,0on failure.int cmark_node_insert_after(cmark_node *node, cmark_node *sibling)
Inserts a sibling after node. Returns 1 on success, 0 on failure. π
int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode)β Replacesoldnodewithnewnodeand unlinksoldnode(but does not free its memory). Returns1on success,0on failure. π«Άint cmark_node_prepend_child(cmark_node *node, cmark_node *child)β Addschildto the beginning of the children ofnode. Returns1on success,0on failure. β¨int cmark_node_append_child(cmark_node *node, cmark_node *child)β Addschildto the end of the children ofnode. Returns1on success,0on failure. πvoid cmark_consolidate_text_nodes(cmark_node *root)β Consolidates adjacent text nodes. π§
Parsing β¨
Simple interface, bestie:
cmark_node *document = cmark_parse_document("Hello *world*", 13,
CMARK_OPT_DEFAULT);
Streaming interface, for when you're feeding it bits at a time:
cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT);
FILE *fp = fopen("myfile.md", "rb");
while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
cmark_parser_feed(parser, buffer, bytes);
if (bytes < sizeof(buffer)) {
break;
}
}
document = cmark_parser_finish(parser);
cmark_parser_free(parser);
cmark_parser * cmark_parser_new(int options)β Creates a new parser object. πΈcmark_parser * cmark_parser_new_with_mem(int options, cmark_mem *mem)β Creates a new parser object with the given memory allocator. π
A generalization of cmark_parser_new:
cmark_parser_new(options)
is the same as:
cmark_parser_new_with_mem(options, cmark_get_default_mem_allocator())
cmark_parser * cmark_parser_new_with_mem_into_root(int options, cmark_mem *mem, cmark_node *root)β Creates a new parser object with the given node to use as the root node of the parsed AST. π
When parsing, children are always appended, not prepended; that means if root already has children, the newly-parsed children will appear after the given children. π
A generalization of cmark_parser_new_with_mem:
cmark_parser_new_with_mem(options, mem)
is approximately the same as:
cmark_parser_new_with_mem_into_root(options, mem, cmark_node_new(CMARK_NODE_DOCUMENT))
This is useful for creating a single document out of multiple parsed document fragments. π
void cmark_parser_free(cmark_parser *parser)β Frees memory allocated for a parser object. π«Άvoid cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len)β Feeds a string of lengthlentoparser. β¨cmark_node * cmark_parser_finish(cmark_parser *parser)β Finish parsing and return a pointer to a tree of nodes. πcmark_node * cmark_parse_document(const char *buffer, size_t len, int options)β Parse a CommonMark document inbufferof lengthlen. Returns a pointer to a tree of nodes. The memory allocated for the node tree should be released usingcmark_node_freewhen it is no longer needed. π§cmark_node * cmark_parse_file(FILE *f, int options)β Parse a CommonMark document in filef, returning a pointer to a tree of nodes. The memory allocated for the node tree should be released usingcmark_node_freewhen it is no longer needed. πΈ
Rendering π
char * cmark_render_xml(cmark_node *root, int options)β Render a node tree as XML. It is the caller's responsibility to free the returned buffer. πchar * cmark_render_html(cmark_node *root, int options)β Render a node tree as an HTML fragment. It is up to the user to add an appropriate header and footer. It is the caller's responsibility to free the returned buffer. πchar * cmark_render_man(cmark_node *root, int options, int width)β Render a node tree as a groff man page, without the header. It is the caller's responsibility to free the returned buffer. πchar * cmark_render_commonmark(cmark_node *root, int options, int width)β Render a node tree as a commonmark document. It is the caller's responsibility to free the returned buffer. πchar * cmark_render_latex(cmark_node *root, int options, int width)β Render a node tree as a LaTeX document. It is the caller's responsibility to free the returned buffer. π«Ά
Options β¨
#define CMARK_OPT_DEFAULT 0β Default options. β¨
Options affecting rendering π
#define CMARK_OPT_SOURCEPOS (1 << 1)β Include adata-sourceposattribute on all block elements. π#define CMARK_OPT_HARDBREAKS (1 << 2)β Render softbreak elements as hard line breaks. π§#define CMARK_OPT_SAFE (1 << 3)βCMARK_OPT_SAFEis defined here for API compatibility, but it no longer has any effect. "Safe" mode is now the default: setCMARK_OPT_UNSAFEto disable it. πΈ#define CMARK_OPT_UNSAFE (1 << 17)β Render raw HTML and unsafe links (javascript:,vbscript:,file:, anddata:, except forimage/png,image/gif,image/jpeg, orimage/webpmime types). By default, raw HTML is replaced by a placeholder HTML comment. Unsafe links are replaced by empty strings. π#define CMARK_OPT_NOBREAKS (1 << 4)β Render softbreak elements as spaces. π
Options affecting parsing π
#define CMARK_OPT_NORMALIZE (1 << 8)β Legacy option (no effect). π#define CMARK_OPT_VALIDATE_UTF8 (1 << 9)β Validate UTF-8 in the input before parsing, replacing illegal sequences with the replacement characterU+FFFD. π#define CMARK_OPT_SMART (1 << 10)β Convert straight quotes to curly,---to em dashes,--to en dashes. π«Ά
Version information π
int cmark_version(void)β The library version as integer for runtime checks. Also available as macroCMARK_VERSIONfor compile time checks. β¨- Bits 16-23 contain the major version. π
- Bits 8-15 contain the minor version. π§
- Bits 0-7 contain the patchlevel. πΈ
In hexadecimal format, the number 0x010203 represents version 1.2.3. π
const char * cmark_version_string(void)β The library version string for runtime checks. Also available as macroCMARK_VERSION_STRINGfor compile time checks. π
AUTHORS π
John MacFarlane, Vicent Marti, KΔrlis GaΕΔ£is, Nick Wellnhofer. π
That's the whole vibe from cmark 0.31.1, dated August 03, 2024, page cmark(3). Periodt. π β¨
π¦ where this page comes from
- fedora 44: cmark-devel 0.31.1-3.fc44 Β· BSD-2-Clause AND MIT
- fedora 44: cmark-devel 0.31.1-3.fc44 Β· BSD-2-Clause AND MIT
- nixos 26.05: cmark 0.31.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms