diff options
-rw-r--r-- | man/man3/cmark.3 | 362 | ||||
-rw-r--r-- | src/cmark.h | 2 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/man.c | 284 |
4 files changed, 311 insertions, 339 deletions
diff --git a/man/man3/cmark.3 b/man/man3/cmark.3 index 6521126..c685dae 100644 --- a/man/man3/cmark.3 +++ b/man/man3/cmark.3 @@ -1,95 +1,95 @@ -.TH cmark 3 "July 03, 2015" "LOCAL" "Library Functions Manual" -.SH +.TH cmark 3 "July 12, 2015" "LOCAL" "Library Functions Manual" +\&.SH NAME -.PP -\f[B]cmark\f[] \- CommonMark parsing, manipulating, and rendering +\&.PP +\ef[B]cmark\ef[] \- CommonMark parsing, manipulating, and rendering -.SH +\&.SH DESCRIPTION -.SS +\&.SS Simple Interface .PP \fIchar *\f[] \fBcmark_markdown_to_html\f[](\fIconst char *text\f[], \fIsize_t len\f[], \fIint options\f[]) -.PP -Convert \f[I]text\f[] (assumed to be a UTF\-8 encoded string with length -\f[I]len\f[] from CommonMark Markdown to HTML, returning a null\-terminated, +\&.PP +Convert \ef[I]text\ef[] (assumed to be a UTF\-8 encoded string with length +\ef[I]len\ef[] from CommonMark Markdown to HTML, returning a null\-terminated, UTF\-8\-encoded string. -.SS +\&.SS Node Structure -.SS +\&.SS Creating and Destroying Nodes .PP \fIcmark_node*\f[] \fBcmark_node_new\f[](\fIcmark_node_type type\f[]) -.PP -Creates a new node of type \f[I]type\f[]\&. Note that the node may have +\&.PP +Creates a new node of type \ef[I]type\ef[]. Note that the node may have other required properties, which it is the caller's responsibility to assign. .PP \fIvoid\f[] \fBcmark_node_free\f[](\fIcmark_node *node\f[]) -.PP +\&.PP Frees the memory allocated for a node. -.SS +\&.SS Tree Traversal .PP \fIcmark_node*\f[] \fBcmark_node_next\f[](\fIcmark_node *node\f[]) -.PP -Returns the next node in the sequence after \f[I]node\f[], or NULL if +\&.PP +Returns the next node in the sequence after \ef[I]node\ef[], or NULL if there is none. .PP \fIcmark_node*\f[] \fBcmark_node_previous\f[](\fIcmark_node *node\f[]) -.PP -Returns the previous node in the sequence after \f[I]node\f[], or NULL if +\&.PP +Returns the previous node in the sequence after \ef[I]node\ef[], or NULL if there is none. .PP \fIcmark_node*\f[] \fBcmark_node_parent\f[](\fIcmark_node *node\f[]) -.PP -Returns the parent of \f[I]node\f[], or NULL if there is none. +\&.PP +Returns the parent of \ef[I]node\ef[], or NULL if there is none. .PP \fIcmark_node*\f[] \fBcmark_node_first_child\f[](\fIcmark_node *node\f[]) -.PP -Returns the first child of \f[I]node\f[], or NULL if \f[I]node\f[] has no children. +\&.PP +Returns the first child of \ef[I]node\ef[], or NULL if \ef[I]node\ef[] has no children. .PP \fIcmark_node*\f[] \fBcmark_node_last_child\f[](\fIcmark_node *node\f[]) -.PP -Returns the last child of \f[I]node\f[], or NULL if \f[I]node\f[] has no children. +\&.PP +Returns the last child of \ef[I]node\ef[], or NULL if \ef[I]node\ef[] has no children. -.SS +\&.SS Iterator -.PP +\&.PP An iterator will walk through a tree of nodes, starting from a root node, returning one node at a time, together with information 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 +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 \f[I]cmark_event_type\f[] of \f[C]CMARK_EVENT_EXIT\f[]). The iterator will -return \f[C]CMARK_EVENT_DONE\f[] when it reaches the root node again. -One natural application is an HTML renderer, where an \f[C]ENTER\f[] event -outputs an open tag and an \f[C]EXIT\f[] event outputs a close tag. +a \ef[I]cmark_event_type\ef[] of \ef[C]CMARK_EVENT_EXIT\ef[]). The iterator will +return \ef[C]CMARK_EVENT_DONE\ef[] when it reaches the root node again. +One natural application is an HTML renderer, where an \ef[C]ENTER\ef[] event +outputs an open tag and an \ef[C]EXIT\ef[] 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 headers into regular paragraphs. -.IP -.nf -\f[C] +\&.IP +\&.nf +\ef[C] void usage_example(cmark_node *root) { cmark_event_type ev_type; @@ -102,304 +102,304 @@ usage_example(cmark_node *root) { cmark_iter_free(iter); } -\f[] -.fi -.PP -Iterators will never return \f[C]EXIT\f[] events for leaf nodes, which are nodes +\ef[] +\&.fi +\&.PP +Iterators will never return \ef[C]EXIT\ef[] events for leaf nodes, which are nodes of type: -.IP \[bu] 2 +\&.IP \e[bu] 2 CMARK_NODE_HTML -.IP \[bu] 2 +\&.IP \e[bu] 2 CMARK_NODE_HRULE -.IP \[bu] 2 +\&.IP \e[bu] 2 CMARK_NODE_CODE_BLOCK -.IP \[bu] 2 +\&.IP \e[bu] 2 CMARK_NODE_TEXT -.IP \[bu] 2 +\&.IP \e[bu] 2 CMARK_NODE_SOFTBREAK -.IP \[bu] 2 +\&.IP \e[bu] 2 CMARK_NODE_LINEBREAK -.IP \[bu] 2 +\&.IP \e[bu] 2 CMARK_NODE_CODE -.IP \[bu] 2 +\&.IP \e[bu] 2 CMARK_NODE_INLINE_HTML -.PP -Nodes must only be modified after an \f[C]EXIT\f[] event, or an \f[C]ENTER\f[] event for +\&.PP +Nodes must only be modified after an \ef[C]EXIT\ef[] event, or an \ef[C]ENTER\ef[] event for leaf nodes. .PP \fIcmark_iter*\f[] \fBcmark_iter_new\f[](\fIcmark_node *root\f[]) -.PP -Creates a new iterator starting at \f[I]root\f[]\&. The current node and event -type are undefined until \f[C]cmark_iter_next\f[] is called for the first time. +\&.PP +Creates a new iterator starting at \ef[I]root\ef[]. The current node and event +type are undefined until \ef[C]cmark_iter_next\ef[] is called for the first time. .PP \fIvoid\f[] \fBcmark_iter_free\f[](\fIcmark_iter *iter\f[]) -.PP +\&.PP Frees the memory allocated for an iterator. .PP \fIcmark_event_type\f[] \fBcmark_iter_next\f[](\fIcmark_iter *iter\f[]) -.PP -Advances to the next node and returns the event type (\f[C]CMARK_EVENT_ENTER\f[], -\f[C]CMARK_EVENT_EXIT\f[] or \f[C]CMARK_EVENT_DONE\f[]). +\&.PP +Advances to the next node and returns the event type (\ef[C]CMARK_EVENT_ENTER\ef[], +\ef[C]CMARK_EVENT_EXIT\ef[] or \ef[C]CMARK_EVENT_DONE\ef[]). .PP \fIcmark_node*\f[] \fBcmark_iter_get_node\f[](\fIcmark_iter *iter\f[]) -.PP +\&.PP Returns the current node. .PP \fIcmark_event_type\f[] \fBcmark_iter_get_event_type\f[](\fIcmark_iter *iter\f[]) -.PP +\&.PP Returns the current event type. .PP \fIcmark_node*\f[] \fBcmark_iter_get_root\f[](\fIcmark_iter *iter\f[]) -.PP +\&.PP Returns the root node. .PP \fIvoid\f[] \fBcmark_iter_reset\f[](\fIcmark_iter *iter\f[], \fIcmark_node *current\f[], \fIcmark_event_type event_type\f[]) -.PP -Resets the iterator so that the current node is \f[I]current\f[] and -the event type is \f[I]event_type\f[]\&. The new current node must be a +\&.PP +Resets the iterator so that the current node is \ef[I]current\ef[] and +the event type is \ef[I]event_type\ef[]. The new current node must be a descendant of the root node or the root node itself. -.SS +\&.SS Accessors .PP \fIvoid*\f[] \fBcmark_node_get_user_data\f[](\fIcmark_node *node\f[]) -.PP -Returns the user data of \f[I]node\f[]\&. +\&.PP +Returns the user data of \ef[I]node\ef[]. .PP \fIint\f[] \fBcmark_node_set_user_data\f[](\fIcmark_node *node\f[], \fIvoid *user_data\f[]) -.PP -Sets arbitrary user data for \f[I]node\f[]\&. Returns 1 on success, +\&.PP +Sets arbitrary user data for \ef[I]node\ef[]. Returns 1 on success, 0 on failure. .PP \fIcmark_node_type\f[] \fBcmark_node_get_type\f[](\fIcmark_node *node\f[]) -.PP -Returns the type of \f[I]node\f[], or \f[C]CMARK_NODE_NONE\f[] on error. +\&.PP +Returns the type of \ef[I]node\ef[], or \ef[C]CMARK_NODE_NONE\ef[] on error. .PP \fIconst char*\f[] \fBcmark_node_get_type_string\f[](\fIcmark_node *node\f[]) -.PP -Like \f[I]cmark_node_get_type\f[], but returns a string representation -of the type, or \f[C]"<unknown>"\f[]\&. +\&.PP +Like \ef[I]cmark_node_get_type\ef[], but returns a string representation +of the type, or \ef[C]"<unknown>"\ef[]. .PP \fIconst char*\f[] \fBcmark_node_get_literal\f[](\fIcmark_node *node\f[]) -.PP -Returns the string contents of \f[I]node\f[], or NULL if none. +\&.PP +Returns the string contents of \ef[I]node\ef[], or NULL if none. .PP \fIint\f[] \fBcmark_node_set_literal\f[](\fIcmark_node *node\f[], \fIconst char *content\f[]) -.PP -Sets the string contents of \f[I]node\f[]\&. Returns 1 on success, +\&.PP +Sets the string contents of \ef[I]node\ef[]. Returns 1 on success, 0 on failure. .PP \fIint\f[] \fBcmark_node_get_header_level\f[](\fIcmark_node *node\f[]) -.PP -Returns the header level of \f[I]node\f[], or 0 if \f[I]node\f[] is not a header. +\&.PP +Returns the header level of \ef[I]node\ef[], or 0 if \ef[I]node\ef[] is not a header. .PP \fIint\f[] \fBcmark_node_set_header_level\f[](\fIcmark_node *node\f[], \fIint level\f[]) -.PP -Sets the header level of \f[I]node\f[], returning 1 on success and 0 on error. +\&.PP +Sets the header level of \ef[I]node\ef[], returning 1 on success and 0 on error. .PP \fIcmark_list_type\f[] \fBcmark_node_get_list_type\f[](\fIcmark_node *node\f[]) -.PP -Returns the list type of \f[I]node\f[], or \f[C]CMARK_NO_LIST\f[] if \f[I]node\f[] +\&.PP +Returns the list type of \ef[I]node\ef[], or \ef[C]CMARK_NO_LIST\ef[] if \ef[I]node\ef[] is not a list. .PP \fIint\f[] \fBcmark_node_set_list_type\f[](\fIcmark_node *node\f[], \fIcmark_list_type type\f[]) -.PP -Sets the list type of \f[I]node\f[], returning 1 on success and 0 on error. +\&.PP +Sets the list type of \ef[I]node\ef[], returning 1 on success and 0 on error. .PP \fIcmark_delim_type\f[] \fBcmark_node_get_list_delim\f[](\fIcmark_node *node\f[]) -.PP -Returns the list delimiter type of \f[I]node\f[], or \f[C]CMARK_NO_DELIM\f[] if \f[I]node\f[] +\&.PP +Returns the list delimiter type of \ef[I]node\ef[], or \ef[C]CMARK_NO_DELIM\ef[] if \ef[I]node\ef[] is not a list. .PP \fIint\f[] \fBcmark_node_set_list_delim\f[](\fIcmark_node *node\f[], \fIcmark_delim_type delim\f[]) -.PP -Sets the list delimiter type of \f[I]node\f[], returning 1 on success and 0 +\&.PP +Sets the list delimiter type of \ef[I]node\ef[], returning 1 on success and 0 on error. .PP \fIint\f[] \fBcmark_node_get_list_start\f[](\fIcmark_node *node\f[]) -.PP -Returns starting number of \f[I]node\f[], if it is an ordered list, otherwise 0. +\&.PP +Returns starting number of \ef[I]node\ef[], if it is an ordered list, otherwise 0. .PP \fIint\f[] \fBcmark_node_set_list_start\f[](\fIcmark_node *node\f[], \fIint start\f[]) -.PP -Sets starting number of \f[I]node\f[], if it is an ordered list. Returns 1 +\&.PP +Sets starting number of \ef[I]node\ef[], if it is an ordered list. Returns 1 on success, 0 on failure. .PP \fIint\f[] \fBcmark_node_get_list_tight\f[](\fIcmark_node *node\f[]) -.PP -Returns 1 if \f[I]node\f[] is a tight list, 0 otherwise. +\&.PP +Returns 1 if \ef[I]node\ef[] is a tight list, 0 otherwise. .PP \fIint\f[] \fBcmark_node_set_list_tight\f[](\fIcmark_node *node\f[], \fIint tight\f[]) -.PP -Sets the "tightness" of a list. Returns 1 on success, 0 on failure. +\&.PP +Sets the "tightness" of a list. Returns 1 on success, 0 on failure. .PP \fIconst char*\f[] \fBcmark_node_get_fence_info\f[](\fIcmark_node *node\f[]) -.PP +\&.PP Returns the info string from a fenced code block, or NULL if none. .PP \fIint\f[] \fBcmark_node_set_fence_info\f[](\fIcmark_node *node\f[], \fIconst char *info\f[]) -.PP +\&.PP Sets the info string in a fenced code block, returning 1 on success and 0 on failure. .PP \fIconst char*\f[] \fBcmark_node_get_url\f[](\fIcmark_node *node\f[]) -.PP -Gets the URL of a link or image \f[I]node\f[], or NULL if none. +\&.PP +Gets the URL of a link or image \ef[I]node\ef[], or NULL if none. .PP \fIint\f[] \fBcmark_node_set_url\f[](\fIcmark_node *node\f[], \fIconst char *url\f[]) -.PP -Sets the URL of a link or image \f[I]node\f[]\&. Returns 1 on success, +\&.PP +Sets the URL of a link or image \ef[I]node\ef[]. Returns 1 on success, 0 on failure. .PP \fIconst char*\f[] \fBcmark_node_get_title\f[](\fIcmark_node *node\f[]) -.PP -Gets the title of a link or image \f[I]node\f[], or NULL if none. +\&.PP +Gets the title of a link or image \ef[I]node\ef[], or NULL if none. .PP \fIint\f[] \fBcmark_node_set_title\f[](\fIcmark_node *node\f[], \fIconst char *title\f[]) -.PP -Sets the title of a link or image \f[I]node\f[]\&. Returns 1 on success, +\&.PP +Sets the title of a link or image \ef[I]node\ef[]. Returns 1 on success, 0 on failure. .PP \fIint\f[] \fBcmark_node_get_start_line\f[](\fIcmark_node *node\f[]) -.PP -Returns the line on which \f[I]node\f[] begins. +\&.PP +Returns the line on which \ef[I]node\ef[] begins. .PP \fIint\f[] \fBcmark_node_get_start_column\f[](\fIcmark_node *node\f[]) -.PP -Returns the column at which \f[I]node\f[] begins. +\&.PP +Returns the column at which \ef[I]node\ef[] begins. .PP \fIint\f[] \fBcmark_node_get_end_line\f[](\fIcmark_node *node\f[]) -.PP -Returns the line on which \f[I]node\f[] ends. +\&.PP +Returns the line on which \ef[I]node\ef[] ends. .PP \fIint\f[] \fBcmark_node_get_end_column\f[](\fIcmark_node *node\f[]) -.PP -Returns the column at which \f[I]node\f[] ends. +\&.PP +Returns the column at which \ef[I]node\ef[] ends. -.SS +\&.SS Tree Manipulation .PP \fIvoid\f[] \fBcmark_node_unlink\f[](\fIcmark_node *node\f[]) -.PP -Unlinks a \f[I]node\f[], removing it from the tree, but not freeing its -memory. (Use \f[I]cmark_node_free\f[] for that.) +\&.PP +Unlinks a \ef[I]node\ef[], removing it from the tree, but not freeing its +memory. (Use \ef[I]cmark_node_free\ef[] for that.) .PP \fIint\f[] \fBcmark_node_insert_before\f[](\fIcmark_node *node\f[], \fIcmark_node *sibling\f[]) -.PP -Inserts \f[I]sibling\f[] before \f[I]node\f[]\&. Returns 1 on success, 0 on failure. +\&.PP +Inserts \ef[I]sibling\ef[] before \ef[I]node\ef[]. Returns 1 on success, 0 on failure. .PP \fIint\f[] \fBcmark_node_insert_after\f[](\fIcmark_node *node\f[], \fIcmark_node *sibling\f[]) -.PP -Inserts \f[I]sibling\f[] after \f[I]node\f[]\&. Returns 1 on success, 0 on failure. +\&.PP +Inserts \ef[I]sibling\ef[] after \ef[I]node\ef[]. Returns 1 on success, 0 on failure. .PP \fIint\f[] \fBcmark_node_prepend_child\f[](\fIcmark_node *node\f[], \fIcmark_node *child\f[]) -.PP -Adds \f[I]child\f[] to the beginning of the children of \f[I]node\f[]\&. +\&.PP +Adds \ef[I]child\ef[] to the beginning of the children of \ef[I]node\ef[]. Returns 1 on success, 0 on failure. .PP \fIint\f[] \fBcmark_node_append_child\f[](\fIcmark_node *node\f[], \fIcmark_node *child\f[]) -.PP -Adds \f[I]child\f[] to the end of the children of \f[I]node\f[]\&. +\&.PP +Adds \ef[I]child\ef[] to the end of the children of \ef[I]node\ef[]. Returns 1 on success, 0 on failure. .PP \fIvoid\f[] \fBcmark_consolidate_text_nodes\f[](\fIcmark_node *root\f[]) -.PP +\&.PP Consolidates adjacent text nodes. -.SS +\&.SS Parsing -.PP +\&.PP Simple interface: -.IP -.nf -\f[C] +\&.IP +\&.nf +\ef[C] cmark_node *document = cmark_parse_document("Hello *world*", 12, CMARK_OPT_DEFAULT); -\f[] -.fi -.PP +\ef[] +\&.fi +\&.PP Streaming interface: -.IP -.nf -\f[C] +\&.IP +\&.nf +\ef[C] cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); FILE *fp = fopen("myfile.md", "r"); while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { @@ -410,80 +410,80 @@ while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { } document = cmark_parser_finish(parser); cmark_parser_free(parser); -\f[] -.fi +\ef[] +\&.fi .PP \fIcmark_parser *\f[] \fBcmark_parser_new\f[](\fIint options\f[]) -.PP +\&.PP Creates a new parser object. .PP \fIvoid\f[] \fBcmark_parser_free\f[](\fIcmark_parser *parser\f[]) -.PP +\&.PP Frees memory allocated for a parser object. .PP \fIvoid\f[] \fBcmark_parser_feed\f[](\fIcmark_parser *parser\f[], \fIconst char *buffer\f[], \fIsize_t len\f[]) -.PP -Feeds a string of length \f[I]len\f[] to \f[I]parser\f[]\&. +\&.PP +Feeds a string of length \ef[I]len\ef[] to \ef[I]parser\ef[]. .PP \fIcmark_node *\f[] \fBcmark_parser_finish\f[](\fIcmark_parser *parser\f[]) -.PP +\&.PP Finish parsing and return a pointer to a tree of nodes. .PP \fIcmark_node *\f[] \fBcmark_parse_document\f[](\fIconst char *buffer\f[], \fIsize_t len\f[], \fIint options\f[]) -.PP -Parse a CommonMark document in \f[I]buffer\f[] of length \f[I]len\f[]\&. +\&.PP +Parse a CommonMark document in \ef[I]buffer\ef[] of length \ef[I]len\ef[]. Returns a pointer to a tree of nodes. .PP \fIcmark_node *\f[] \fBcmark_parse_file\f[](\fIFILE *f\f[], \fIint options\f[]) -.PP -Parse a CommonMark document in file \f[I]f\f[], returning a pointer to +\&.PP +Parse a CommonMark document in file \ef[I]f\ef[], returning a pointer to a tree of nodes. -.SS +\&.SS Rendering .PP \fIchar *\f[] \fBcmark_render_xml\f[](\fIcmark_node *root\f[], \fIint options\f[]) -.PP -Render a \f[I]node\f[] tree as XML. +\&.PP +Render a \ef[I]node\ef[] tree as XML. .PP \fIchar *\f[] \fBcmark_render_html\f[](\fIcmark_node *root\f[], \fIint options\f[]) -.PP -Render a \f[I]node\f[] tree as an HTML fragment. It is up to the user +\&.PP +Render a \ef[I]node\ef[] tree as an HTML fragment. It is up to the user to add an appropriate header and footer. .PP -\fIchar *\f[] \fBcmark_render_man\f[](\fIcmark_node *root\f[], \fIint options\f[]) +\fIchar *\f[] \fBcmark_render_man\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[]) -.PP -Render a \f[I]node\f[] tree as a groff man page, without the header. +\&.PP +Render a \ef[I]node\ef[] tree as a groff man page, without the header. .PP \fIchar *\f[] \fBcmark_render_commonmark\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[]) -.PP -Render a \f[I]node\f[] tree as a commonmark document. +\&.PP +Render a \ef[I]node\ef[] tree as a commonmark document. .PP \fIchar *\f[] \fBcmark_render_latex\f[](\fIcmark_node *root\f[], \fIint options\f[], \fIint width\f[]) -.PP -Render a \f[I]node\f[] tree as a LaTeX document. +\&.PP +Render a \ef[I]node\ef[] tree as a LaTeX document. .PP .nf @@ -494,7 +494,7 @@ Render a \f[I]node\f[] tree as a LaTeX document. \f[] .fi -.PP +\&.PP Default writer options. .PP @@ -506,8 +506,8 @@ Default writer options. \f[] .fi -.PP -Include a \f[C]data\-sourcepos\f[] attribute on all block elements. +\&.PP +Include a \ef[C]data\-sourcepos\ef[] attribute on all block elements. .PP .nf @@ -518,8 +518,8 @@ Include a \f[C]data\-sourcepos\f[] attribute on all block elements. \f[] .fi -.PP -Render \f[C]softbreak\f[] elements as hard line breaks. +\&.PP +Render \ef[C]softbreak\ef[] elements as hard line breaks. .PP .nf @@ -530,7 +530,7 @@ Render \f[C]softbreak\f[] elements as hard line breaks. \f[] .fi -.PP +\&.PP Normalize tree by consolidating adjacent text nodes. .PP @@ -542,7 +542,7 @@ Normalize tree by consolidating adjacent text nodes. \f[] .fi -.PP +\&.PP Convert straight quotes to curly, \-\-\- to em dashes, \-\- to en dashes. .PP @@ -554,37 +554,37 @@ Convert straight quotes to curly, \-\-\- to em dashes, \-\- to en dashes. \f[] .fi -.PP +\&.PP Validate UTF\-8 in the input before parsing, replacing illegal sequences with the replacement character U+FFFD. -.SS +\&.SS Version information .PP \fIint\f[] \fBcmark_version\f[](\fI\f[]) -.PP +\&.PP The library version as integer for runtime checks. Also available as macro CMARK_VERSION for compile time checks. -.IP \[bu] 2 +\&.IP \e[bu] 2 Bits 16\-23 contain the major version. -.IP \[bu] 2 +\&.IP \e[bu] 2 Bits 8\-15 contain the minor version. -.IP \[bu] 2 +\&.IP \e[bu] 2 Bits 0\-7 contain the patchlevel. -.PP +\&.PP In hexadecimal format, the number 0x010203 represents version 1.2.3. .PP \fIconst char *\f[] \fBcmark_version_string\f[](\fI\f[]) -.PP +\&.PP The library version string for runtime checks. Also available as macro CMARK_VERSION_STRING for compile time checks. -.SH +\&.SH AUTHORS -.PP -John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer. +\&.PP +John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer. diff --git a/src/cmark.h b/src/cmark.h index 6618301..7ae6d36 100644 --- a/src/cmark.h +++ b/src/cmark.h @@ -479,7 +479,7 @@ char *cmark_render_html(cmark_node *root, int options); /** Render a 'node' tree as a groff man page, without the header. */ CMARK_EXPORT -char *cmark_render_man(cmark_node *root, int options); +char *cmark_render_man(cmark_node *root, int options, int width); /** Render a 'node' tree as a commonmark document. */ @@ -47,7 +47,7 @@ static void print_document(cmark_node *document, writer_format writer, result = cmark_render_xml(document, options); break; case FORMAT_MAN: - result = cmark_render_man(document, options); + result = cmark_render_man(document, options, width); break; case FORMAT_COMMONMARK: result = cmark_render_commonmark(document, options, width); @@ -8,110 +8,93 @@ #include "node.h" #include "buffer.h" #include "utf8.h" +#include "render.h" -// Functions to convert cmark_nodes to groff man strings. +#define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping) +#define LIT(s) renderer->out(renderer, s, false, LITERAL) +#define CR() renderer->cr(renderer) +#define BLANKLINE() renderer->blankline(renderer) -static void escape_man(cmark_strbuf *dest, const unsigned char *source, int length) +// Functions to convert cmark_nodes to groff man strings. +static +void S_outc(cmark_renderer *renderer, + cmark_escaping escape, + int32_t c, + unsigned char nextc) { - int32_t c; - int i = 0; - int len; - bool beginLine = true; - - while (i < length) { - len = utf8proc_iterate(source + i, length - i, &c); - if (len == -1) { // error condition - return; // return without rendering anything + (void)(escape); // avoid unused parameter warning + (void)(nextc); + + switch(c) { + case 46: + if (renderer->begin_line) { + cmark_strbuf_puts(renderer->buffer, "\\&."); + renderer->column += 3; + } else { + utf8proc_encode_char(c, renderer->buffer); + renderer->column += 1; } - switch(c) { - case 46: - if (beginLine) { - cmark_strbuf_puts(dest, "\\&."); - } else { - utf8proc_encode_char(c, dest); - } - break; - case 39: - if (beginLine) { - cmark_strbuf_puts(dest, "\\&'"); - } else { - utf8proc_encode_char(c, dest); - } - break; - case 45: - cmark_strbuf_puts(dest, "\\-"); - break; - case 92: - cmark_strbuf_puts(dest, "\\e"); - break; - case 8216: // left single quote - cmark_strbuf_puts(dest, "\\[oq]"); - break; - case 8217: // right single quote - cmark_strbuf_puts(dest, "\\[cq]"); - break; - case 8220: // left double quote - cmark_strbuf_puts(dest, "\\[lq]"); - break; - case 8221: // right double quote - cmark_strbuf_puts(dest, "\\[rq]"); - break; - case 8212: // em dash - cmark_strbuf_puts(dest, "\\[em]"); - break; - case 8211: // en dash - cmark_strbuf_puts(dest, "\\[en]"); - break; - default: - utf8proc_encode_char(c, dest); + break; + case 39: + if (renderer->begin_line) { + cmark_strbuf_puts(renderer->buffer, "\\&'"); + renderer->column += 3; + } else { + utf8proc_encode_char(c, renderer->buffer); + renderer->column += 1; } - beginLine = (c == 10); - i += len; + break; + case 45: + cmark_strbuf_puts(renderer->buffer, "\\-"); + renderer->column += 2; + break; + case 92: + cmark_strbuf_puts(renderer->buffer, "\\e"); + renderer->column += 2; + break; + case 8216: // left single quote + cmark_strbuf_puts(renderer->buffer, "\\[oq]"); + renderer->column += 5; + break; + case 8217: // right single quote + cmark_strbuf_puts(renderer->buffer, "\\[cq]"); + renderer->column += 5; + break; + case 8220: // left double quote + cmark_strbuf_puts(renderer->buffer, "\\[lq]"); + renderer->column += 5; + break; + case 8221: // right double quote + cmark_strbuf_puts(renderer->buffer, "\\[rq]"); + renderer->column += 5; + break; + case 8212: // em dash + cmark_strbuf_puts(renderer->buffer, "\\[em]"); + renderer->column += 5; + break; + case 8211: // en dash + cmark_strbuf_puts(renderer->buffer, "\\[en]"); + renderer->column += 5; + break; + default: + utf8proc_encode_char(c, renderer->buffer); + renderer->column += 1; } + renderer->begin_line = (c == 10); } -static inline void cr(cmark_strbuf *man) -{ - if (man->size && man->ptr[man->size - 1] != '\n') - cmark_strbuf_putc(man, '\n'); -} - -struct render_state { - cmark_strbuf* man; - cmark_node *plain; -}; - static int -S_render_node(cmark_node *node, cmark_event_type ev_type, - struct render_state *state) +S_render_node(cmark_renderer *renderer, + cmark_node *node, + cmark_event_type ev_type, + int options) { cmark_node *tmp; - cmark_strbuf *man = state->man; int list_number; bool entering = (ev_type == CMARK_EVENT_ENTER); - if (state->plain == node) { // back at original node - state->plain = NULL; - } - - if (state->plain != NULL) { - switch(node->type) { - case CMARK_NODE_TEXT: - case CMARK_NODE_CODE: - escape_man(man, node->as.literal.data, - node->as.literal.len); - break; - - case CMARK_NODE_LINEBREAK: - case CMARK_NODE_SOFTBREAK: - cmark_strbuf_putc(man, ' '); - break; - - default: - break; - } - return 1; - } + // avoid unused parameter error: + (void)(options); switch (node->type) { case CMARK_NODE_DOCUMENT: @@ -119,13 +102,13 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, case CMARK_NODE_BLOCK_QUOTE: if (entering) { - cr(man); - cmark_strbuf_puts(man, ".RS"); - cr(man); + CR(); + LIT(".RS"); + CR(); } else { - cr(man); - cmark_strbuf_puts(man, ".RE"); - cr(man); + CR(); + LIT(".RE"); + CR(); } break; @@ -134,11 +117,11 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, case CMARK_NODE_ITEM: if (entering) { - cr(man); - cmark_strbuf_puts(man, ".IP "); + CR(); + LIT(".IP "); if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) { - cmark_strbuf_puts(man, "\\[bu] 2"); + LIT("\\[bu] 2"); } else { list_number = cmark_node_get_list_start(node->parent); tmp = node; @@ -146,43 +129,45 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, tmp = tmp->prev; list_number += 1; } - cmark_strbuf_printf(man, "\"%d.\" 4", list_number); + char list_number_s[20]; + sprintf(list_number_s, "\"%d.\" 4", list_number); + LIT(list_number_s); } - cr(man); + CR(); } else { - cr(man); + CR(); } break; case CMARK_NODE_HEADER: if (entering) { - cr(man); - cmark_strbuf_puts(man, - cmark_node_get_header_level(node) == 1 ? + CR(); + LIT(cmark_node_get_header_level(node) == 1 ? ".SH" : ".SS"); - cr(man); + CR(); } else { - cr(man); + CR(); } break; case CMARK_NODE_CODE_BLOCK: - cr(man); - cmark_strbuf_puts(man, ".IP\n.nf\n\\f[C]\n"); - escape_man(man, node->as.code.literal.data, - node->as.code.literal.len); - cr(man); - cmark_strbuf_puts(man, "\\f[]\n.fi"); - cr(man); + CR(); + LIT(".IP\n.nf\n\\f[C]\n"); + OUT(cmark_node_get_literal(node), + false, + NORMAL); + CR(); + LIT("\\f[]\n.fi"); + CR(); break; case CMARK_NODE_HTML: break; case CMARK_NODE_HRULE: - cr(man); - cmark_strbuf_puts(man, ".PP\n * * * * *"); - cr(man); + CR(); + LIT(".PP\n * * * * *"); + CR(); break; case CMARK_NODE_PARAGRAPH: @@ -193,32 +178,36 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, node->prev == NULL) { // no blank line or .PP } else { - cr(man); - cmark_strbuf_puts(man, ".PP\n"); + CR(); + LIT(".PP"); + CR(); } } else { - cr(man); + CR(); } break; case CMARK_NODE_TEXT: - escape_man(man, node->as.literal.data, - node->as.literal.len); + OUT(cmark_node_get_literal(node), true, NORMAL); break; case CMARK_NODE_LINEBREAK: - cmark_strbuf_puts(man, ".PD 0\n.P\n.PD"); - cr(man); + LIT(".PD 0\n.P\n.PD"); + CR(); break; case CMARK_NODE_SOFTBREAK: - cmark_strbuf_putc(man, '\n'); + if (renderer->width == 0) { + CR(); + } else { + OUT(" ", true, LITERAL); + } break; case CMARK_NODE_CODE: - cmark_strbuf_puts(man, "\\f[C]"); - escape_man(man, node->as.literal.data, node->as.literal.len); - cmark_strbuf_puts(man, "\\f[]"); + LIT("\\f[C]"); + OUT(cmark_node_get_literal(node), true, NORMAL); + LIT("\\f[]"); break; case CMARK_NODE_INLINE_HTML: @@ -226,33 +215,33 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, case CMARK_NODE_STRONG: if (entering) { - cmark_strbuf_puts(man, "\\f[B]"); + LIT("\\f[B]"); } else { - cmark_strbuf_puts(man, "\\f[]"); + LIT("\\f[]"); } break; case CMARK_NODE_EMPH: if (entering) { - cmark_strbuf_puts(man, "\\f[I]"); + LIT("\\f[I]"); } else { - cmark_strbuf_puts(man, "\\f[]"); + LIT("\\f[]"); } break; case CMARK_NODE_LINK: if (!entering) { - cmark_strbuf_printf(man, " (%s)", - cmark_node_get_url(node)); + LIT(" ("); + OUT(cmark_node_get_url(node), true, URL); + LIT(")"); } break; case CMARK_NODE_IMAGE: if (entering) { - cmark_strbuf_puts(man, "[IMAGE: "); - state->plain = node; + LIT("[IMAGE: "); } else { - cmark_strbuf_puts(man, "]"); + LIT("]"); } break; @@ -261,27 +250,10 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, break; } - // cmark_strbuf_putc(man, 'x'); return 1; } -char *cmark_render_man(cmark_node *root, int options) +char *cmark_render_man(cmark_node *root, int options, int width) { - char *result; - cmark_strbuf man = GH_BUF_INIT; - struct render_state state = { &man, NULL }; - cmark_node *cur; - cmark_event_type ev_type; - cmark_iter *iter = cmark_iter_new(root); - - if (options == 0) options = 0; // avoid warning about unused parameters - - while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { - cur = cmark_iter_get_node(iter); - S_render_node(cur, ev_type, &state); - } - result = (char *)cmark_strbuf_detach(&man); - - cmark_iter_free(iter); - return result; + return cmark_render(root, options, width, S_outc, S_render_node); } |