cmark

My personal build of CMark ✏️

Commit
6122d5cc3c5e5e8f94f203daddfd38a36be7aed4
Parent
becfb75e9f2f85cfff18aec49fd96e252f737eb2
Author
John MacFarlane <jgm@berkeley.edu>
Date

commonmark renderer: improve escaping.

URL-escape special characters when escape mode is URL, and not otherwise.

Entity-escape control characters (< 0x20) in non-literal escape modes.

Diffstat

1 file changed, 9 insertions, 4 deletions

Status File Name N° Changes Insertions Deletions
Modified src/commonmark.c 13 9 4
diff --git a/src/commonmark.c b/src/commonmark.c
@@ -32,7 +32,8 @@ static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape,
   needs_escaping =
       c < 0x80 && escape != LITERAL &&
       ((escape == NORMAL &&
-        (c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
+        (c < 0x20 ||
+	 c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
          c == '>' || c == '\\' || c == '`' || c == '!' ||
          (c == '&' && cmark_isalpha(nextc)) || (c == '!' && nextc == '[') ||
          (renderer->begin_content && (c == '-' || c == '+' || c == '=') &&
@@ -48,14 +49,18 @@ static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape,
         (c == '`' || c == '<' || c == '>' || c == '"' || c == '\\')));
 
   if (needs_escaping) {
-    if (cmark_isspace(c)) {
+    if (escape == URL && cmark_isspace(c)) {
       // use percent encoding for spaces
-      snprintf(encoded, ENCODED_SIZE, "%%%2x", c);
+      snprintf(encoded, ENCODED_SIZE, "%%%2X", c);
       cmark_strbuf_puts(renderer->buffer, encoded);
       renderer->column += 3;
-    } else {
+    } else if (cmark_ispunct(c)) {
       cmark_render_ascii(renderer, "\\");
       cmark_render_code_point(renderer, c);
+    } else { // render as entity
+      snprintf(encoded, ENCODED_SIZE, "&#%d;", c);
+      cmark_strbuf_puts(renderer->buffer, encoded);
+      renderer->column += strlen(encoded);
     }
   } else {
     cmark_render_code_point(renderer, c);