From 9c3a7023014f961197bc27ff8360ce9e1b1d6c29 Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Sat, 9 Apr 2016 11:44:58 -0700 Subject: 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. --- man/man1/cmark.1 | 15 +++++++++++---- man/man3/cmark.3 | 43 +++++++++++++++++++++++++++---------------- src/cmark.h | 2 +- src/commonmark.c | 16 +++++++++++----- src/latex.c | 10 +++++++--- src/main.c | 3 +++ src/man.c | 14 +++++++++----- 7 files changed, 69 insertions(+), 34 deletions(-) diff --git a/man/man1/cmark.1 b/man/man1/cmark.1 index 9ea8d4c..cfde3d7 100644 --- 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 index 283b9cc..cf0874a 100644 --- 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 index c98e18e..40aa465 100644 --- 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 index f5a352d..ed6eff3 100644 --- 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 index cd2f6f3..904a1b9 100644 --- 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 index fa18e03..5716e18 100644 --- 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 index 3d8bc20..1c76f68 100644 --- 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; -- cgit v1.2.3