cmark

My personal build of CMark ✏️

Commit
9c3a7023014f961197bc27ff8360ce9e1b1d6c29
Parent
0b6805c0c544cfd8973f457142434127cac4b3a5
Author
John MacFarlane <jgm@berkeley.edu>
Date

Fixed a number of issues relating to line wrapping.

- Extend CMARK_OPT_NOBREAKS to all renderers and add `--nobreaks`. - Do not autowrap, regardless of width parameter, if CMARK_OPT_NOBREAKS is set. - Fixed CMARK_OPT_HARDBREAKS for LaTeX and man renderers. - Ensure that no auto-wrapping occurs if CMARK_OPT_NOBREAKS is enabled, or if output is CommonMark and CMARK_OPT_HARDBREAKS is enabled. - Updated man pages.

Diffstat

7 files changed, 69 insertions, 34 deletions

Status File Name N° Changes Insertions Deletions
Modified man/man1/cmark.1 15 11 4
Modified man/man3/cmark.3 43 27 16
Modified src/cmark.h 2 1 1
Modified src/commonmark.c 16 11 5
Modified src/latex.c 10 7 3
Modified src/main.c 3 3 0
Modified src/man.c 14 9 5
diff --git a/man/man1/cmark.1 b/man/man1/cmark.1
@@ -25,13 +25,20 @@ Specify a column width to which to wrap the output. For no wrapping, use
 the value 0 (the default).  This option currently only affects the
 commonmark, latex, and man renderers.
 .TP 12n
+.B \-\-hardbreaks
+Render soft breaks (newlines inside paragraphs in the CommonMark source)
+as hard line breaks in the target format.  If this option is specified,
+hard wrapping is disabled for CommonMark output, regardless of the value
+given with \-\-width.
+.TP 12n
+.B \-\-nobreaks
+Render soft breaks as spaces.  If this option is specified,
+hard wrapping is disabled for all output formats, regardless of the value
+given with \-\-width.
+.TP 12n
 .B \-\-sourcepos
 Include source position attribute.
 .TP 12n
-.B \-\-hardbreaks
-Treat newlines as hard line breaks.  If this option is specified,
-hard wrapping is disabled, regardless of the value given with \-\-width.
-.TP 12n
 .B \-\-normalize
 Consolidate adjacent text nodes.
 .TP 12n
diff --git a/man/man3/cmark.3 b/man/man3/cmark.3
@@ -1,4 +1,4 @@
-.TH cmark 3 "March 24, 2016" "LOCAL" "Library Functions Manual"
+.TH cmark 3 "April 09, 2016" "LOCAL" "Library Functions Manual"
 .SH
 NAME
 .PP
@@ -102,8 +102,8 @@ Creating and Destroying Nodes
 
 .PP
 Creates a new node of type \f[I]type\f[]. Note that the node may have
-other required properties, which it is the caller\[cq]s responsibility
-to assign.
+other required properties, which it is the caller's responsibility to
+assign.
 
 .PP
 \fIvoid\f[] \fBcmark_node_free\f[](\fIcmark_node *node\f[])
@@ -376,8 +376,7 @@ Returns 1 if \f[I]node\f[] is a tight list, 0 otherwise.
 \fIint\f[] \fBcmark_node_set_list_tight\f[](\fIcmark_node *node\f[], \fIint tight\f[])
 
 .PP
-Sets the \[lq]tightness\[rq] of a list. Returns 1 on success, 0 on
-failure.
+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[])
@@ -424,31 +423,31 @@ on failure.
 \fIconst char *\f[] \fBcmark_node_get_on_enter\f[](\fIcmark_node *node\f[])
 
 .PP
-Returns the literal \[lq]on enter\[rq] text for a custom \f[I]node\f[],
-or an empty string if no on_enter is set.
+Returns the literal "on enter" text for a custom \f[I]node\f[], or an
+empty string if no on_enter is set.
 
 .PP
 \fIint\f[] \fBcmark_node_set_on_enter\f[](\fIcmark_node *node\f[], \fIconst char *on_enter\f[])
 
 .PP
-Sets the literal text to render \[lq]on enter\[rq] for a custom
-\f[I]node\f[]. Any children of the node will be rendered after this
-text. Returns 1 on success 0 on failure.
+Sets the literal text to render "on enter" for a custom \f[I]node\f[].
+Any children of the node will be rendered after this text. Returns 1 on
+success 0 on failure.
 
 .PP
 \fIconst char *\f[] \fBcmark_node_get_on_exit\f[](\fIcmark_node *node\f[])
 
 .PP
-Returns the literal \[lq]on exit\[rq] text for a custom \f[I]node\f[],
-or an empty string if no on_exit is set.
+Returns the literal "on exit" text for a custom \f[I]node\f[], or an
+empty string if no on_exit is set.
 
 .PP
 \fIint\f[] \fBcmark_node_set_on_exit\f[](\fIcmark_node *node\f[], \fIconst char *on_exit\f[])
 
 .PP
-Sets the literal text to render \[lq]on exit\[rq] for a custom
-\f[I]node\f[]. Any children of the node will be rendered before this
-text. Returns 1 on success 0 on failure.
+Sets the literal text to render "on exit" for a custom \f[I]node\f[].
+Any children of the node will be rendered before this text. Returns 1 on
+success 0 on failure.
 
 .PP
 \fIint\f[] \fBcmark_node_get_start_line\f[](\fIcmark_node *node\f[])
@@ -685,6 +684,18 @@ Suppress raw HTML and unsafe links (\f[C]javascript:\f[],
 \f[C]image/webp\f[] mime types). Raw HTML is replaced by a placeholder
 HTML comment. Unsafe links are replaced by empty strings.
 
+.PP
+.nf
+\fC
+.RS 0n
+#define CMARK_OPT_NOBREAKS (1 << 4)
+.RE
+\f[]
+.fi
+
+.PP
+Render \f[C]softbreak\f[] elements as spaces.
+
 .SS
 Options affecting parsing
 
@@ -723,7 +734,7 @@ with the replacement character U+FFFD.
 .fi
 
 .PP
-Convert straight quotes to curly, \[em] to em dashes, \[en] to en
+Convert straight quotes to curly, \-\-\- to em dashes, \-\- to en
 dashes.
 
 .SS
diff --git a/src/cmark.h b/src/cmark.h
@@ -519,7 +519,7 @@ char *cmark_render_latex(cmark_node *root, int options, int width);
  */
 #define CMARK_OPT_SAFE (1 << 3)
 
-/** Render `softbreak` elements as spaces (HTML only).
+/** Render `softbreak` elements as spaces.
  */
 #define CMARK_OPT_NOBREAKS (1 << 4)
 
diff --git a/src/commonmark.c b/src/commonmark.c
@@ -172,6 +172,8 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
   char listmarker[LISTMARKER_SIZE];
   char *emph_delim;
   bufsize_t marker_width;
+  bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options) &&
+		!(CMARK_OPT_HARDBREAKS & options);
 
   // Don't adjust tight list status til we've started the list.
   // Otherwise we loose the blank line between a paragraph and
@@ -327,7 +329,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
     break;
 
   case CMARK_NODE_TEXT:
-    OUT(cmark_node_get_literal(node), true, NORMAL);
+    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
     break;
 
   case CMARK_NODE_LINEBREAK:
@@ -338,10 +340,14 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
     break;
 
   case CMARK_NODE_SOFTBREAK:
-    if (renderer->width == 0 && !(CMARK_OPT_HARDBREAKS & options)) {
+    if (CMARK_OPT_HARDBREAKS & options) {
+      LIT("  ");
+      CR();
+    } else if (renderer->width == 0 && !(CMARK_OPT_HARDBREAKS & options) &&
+		    !(CMARK_OPT_NOBREAKS & options)) {
       CR();
     } else {
-      OUT(" ", true, LITERAL);
+      OUT(" ", allow_wrap, LITERAL);
     }
     break;
 
@@ -355,7 +361,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
     if (code_len == 0 || code[0] == '`') {
       LIT(" ");
     }
-    OUT(cmark_node_get_literal(node), true, LITERAL);
+    OUT(cmark_node_get_literal(node), allow_wrap, LITERAL);
     if (code_len == 0 || code[code_len - 1] == '`') {
       LIT(" ");
     }
@@ -435,7 +441,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
       OUT(cmark_node_get_url(node), false, URL);
       title = cmark_node_get_title(node);
       if (safe_strlen(title) > 0) {
-        OUT(" \"", true, LITERAL);
+        OUT(" \"", allow_wrap, LITERAL);
         OUT(title, false, TITLE);
         LIT("\"");
       }
diff --git a/src/latex.c b/src/latex.c
@@ -223,6 +223,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
   cmark_list_type list_type;
   const char *roman_numerals[] = {"",   "i",   "ii",   "iii", "iv", "v",
                                   "vi", "vii", "viii", "ix",  "x"};
+  bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
 
   // avoid warning about unused parameter:
   (void)(options);
@@ -334,7 +335,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
     break;
 
   case CMARK_NODE_TEXT:
-    OUT(cmark_node_get_literal(node), true, NORMAL);
+    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
     break;
 
   case CMARK_NODE_LINEBREAK:
@@ -343,10 +344,13 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
     break;
 
   case CMARK_NODE_SOFTBREAK:
-    if (renderer->width == 0) {
+    if (options & CMARK_OPT_HARDBREAKS) {
+      LIT("\\\\");
+      CR();
+    } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) {
       CR();
     } else {
-      OUT(" ", true, NORMAL);
+      OUT(" ", allow_wrap, NORMAL);
     }
     break;
 
diff --git a/src/main.c b/src/main.c
@@ -27,6 +27,7 @@ void print_usage() {
   printf("  --width WIDTH    Specify wrap width (default 0 = nowrap)\n");
   printf("  --sourcepos      Include source position attribute\n");
   printf("  --hardbreaks     Treat newlines as hard line breaks\n");
+  printf("  --nobreaks       Render soft line breaks as spaces\n");
   printf("  --safe           Suppress raw HTML and dangerous URLs\n");
   printf("  --smart          Use smart punctuation\n");
   printf("  --normalize      Consolidate adjacent text nodes\n");
@@ -90,6 +91,8 @@ int main(int argc, char *argv[]) {
       options |= CMARK_OPT_SOURCEPOS;
     } else if (strcmp(argv[i], "--hardbreaks") == 0) {
       options |= CMARK_OPT_HARDBREAKS;
+    } else if (strcmp(argv[i], "--nobreaks") == 0) {
+      options |= CMARK_OPT_NOBREAKS;
     } else if (strcmp(argv[i], "--smart") == 0) {
       options |= CMARK_OPT_SMART;
     } else if (strcmp(argv[i], "--safe") == 0) {
diff --git a/src/man.c b/src/man.c
@@ -75,6 +75,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
   cmark_node *tmp;
   int list_number;
   bool entering = (ev_type == CMARK_EVENT_ENTER);
+  bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
 
   // avoid unused parameter error:
   (void)(options);
@@ -173,7 +174,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
     break;
 
   case CMARK_NODE_TEXT:
-    OUT(cmark_node_get_literal(node), true, NORMAL);
+    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
     break;
 
   case CMARK_NODE_LINEBREAK:
@@ -182,16 +183,19 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
     break;
 
   case CMARK_NODE_SOFTBREAK:
-    if (renderer->width == 0) {
+    if (options & CMARK_OPT_HARDBREAKS) {
+      LIT(".PD 0\n.P\n.PD");
+      CR();
+    } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) {
       CR();
     } else {
-      OUT(" ", true, LITERAL);
+      OUT(" ", allow_wrap, LITERAL);
     }
     break;
 
   case CMARK_NODE_CODE:
     LIT("\\f[C]");
-    OUT(cmark_node_get_literal(node), true, NORMAL);
+    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
     LIT("\\f[]");
     break;
 
@@ -222,7 +226,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
   case CMARK_NODE_LINK:
     if (!entering) {
       LIT(" (");
-      OUT(cmark_node_get_url(node), true, URL);
+      OUT(cmark_node_get_url(node), allow_wrap, URL);
       LIT(")");
     }
     break;