http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/cmark_ctype.c
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/cmark_ctype.c 
b/compiler/modules/CommonMark/src/cmark_ctype.c
new file mode 100644
index 0000000..5de8199
--- /dev/null
+++ b/compiler/modules/CommonMark/src/cmark_ctype.c
@@ -0,0 +1,53 @@
+#include <stdint.h>
+
+#include "cmark_ctype.h"
+
+/** 1 = space, 2 = punct, 3 = digit, 4 = alpha, 0 = other
+ */
+static const int8_t cmark_ctype_class[256] = {
+       /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
+       /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
+       /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 2 */ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+       /* 3 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
+       /* 4 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+       /* 5 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2,
+       /* 6 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+       /* 7 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0,
+       /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       /* f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/**
+ * Returns 1 if c is a "whitespace" character as defined by the spec.
+ */
+int cmark_isspace(char c)
+{
+       return cmark_ctype_class[(int8_t)c] == 1;
+}
+
+/**
+ * Returns 1 if c is an ascii punctuation character.
+ */
+int cmark_ispunct(char c)
+{
+       return cmark_ctype_class[(int8_t)c] == 2;
+}
+
+int cmark_isalnum(char c)
+{
+       int8_t result;
+       result = cmark_ctype_class[(int8_t)c];
+       return (result == 3 || result == 4);
+}
+
+int cmark_isdigit(char c)
+{
+       return cmark_ctype_class[(int8_t)c] == 3;
+}

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/cmark_ctype.h
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/cmark_ctype.h 
b/compiler/modules/CommonMark/src/cmark_ctype.h
new file mode 100644
index 0000000..f803946
--- /dev/null
+++ b/compiler/modules/CommonMark/src/cmark_ctype.h
@@ -0,0 +1,24 @@
+#ifndef CMARK_CMARK_CTYPE_H
+#define CMARK_CMARK_CTYPE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Locale-independent versions of functions from ctype.h.
+ * We want cmark to behave the same no matter what the system locale.
+ */
+
+int cmark_isspace(char c);
+
+int cmark_ispunct(char c);
+
+int cmark_isalnum(char c);
+
+int cmark_isdigit(char c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/cmark_export.h
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/cmark_export.h 
b/compiler/modules/CommonMark/src/cmark_export.h
index fa14b4d..1102c36 100644
--- a/compiler/modules/CommonMark/src/cmark_export.h
+++ b/compiler/modules/CommonMark/src/cmark_export.h
@@ -1,7 +1,35 @@
+
 #ifndef CMARK_EXPORT_H
 #define CMARK_EXPORT_H
 
-#define CMARK_EXPORT
-#define CMARK_NO_EXPORT
+#ifdef CMARK_STATIC_DEFINE
+#  define CMARK_EXPORT
+#  define CMARK_NO_EXPORT
+#else
+#  ifndef CMARK_EXPORT
+#    ifdef libcmark_EXPORTS
+        /* We are building this library */
+#      define CMARK_EXPORT __attribute__((visibility("default")))
+#    else
+        /* We are using this library */
+#      define CMARK_EXPORT __attribute__((visibility("default")))
+#    endif
+#  endif
+
+#  ifndef CMARK_NO_EXPORT
+#    define CMARK_NO_EXPORT __attribute__((visibility("hidden")))
+#  endif
+#endif
+
+#ifndef CMARK_DEPRECATED
+#  define CMARK_DEPRECATED __attribute__ ((__deprecated__))
+#  define CMARK_DEPRECATED_EXPORT CMARK_EXPORT __attribute__ ((__deprecated__))
+#  define CMARK_DEPRECATED_NO_EXPORT CMARK_NO_EXPORT __attribute__ 
((__deprecated__))
+#endif
+
+#define DEFINE_NO_DEPRECATED 0
+#if DEFINE_NO_DEPRECATED
+# define CMARK_NO_DEPRECATED
+#endif
 
 #endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/config.h
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/config.h 
b/compiler/modules/CommonMark/src/config.h
index ce3064e..ecfa334 100644
--- a/compiler/modules/CommonMark/src/config.h
+++ b/compiler/modules/CommonMark/src/config.h
@@ -9,3 +9,7 @@ typedef char bool;
 #endif
 
 #define CMARK_ATTRIBUTE(list)
+
+#ifndef CHY_HAS_VA_COPY
+  #define va_copy(dest, src) ((dest) = (src))
+#endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/config.h.in
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/config.h.in 
b/compiler/modules/CommonMark/src/config.h.in
index 5294bc9..c1e9597 100644
--- a/compiler/modules/CommonMark/src/config.h.in
+++ b/compiler/modules/CommonMark/src/config.h.in
@@ -15,3 +15,9 @@
 #else
   #define CMARK_ATTRIBUTE(list)
 #endif
+
+#cmakedefine HAVE_VA_COPY
+
+#ifndef HAVE_VA_COPY
+  #define va_copy(dest, src) ((dest) = (src))
+#endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/houdini.h
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/houdini.h 
b/compiler/modules/CommonMark/src/houdini.h
index 9e1200e..9f00f6d 100644
--- a/compiler/modules/CommonMark/src/houdini.h
+++ b/compiler/modules/CommonMark/src/houdini.h
@@ -31,19 +31,19 @@ extern "C" {
 #define HOUDINI_ESCAPED_SIZE(x) (((x) * 12) / 10)
 #define HOUDINI_UNESCAPED_SIZE(x) (x)
 
-extern size_t houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t 
size);
-extern int houdini_escape_html(strbuf *ob, const uint8_t *src, size_t size);
-extern int houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t size, 
int secure);
-extern int houdini_unescape_html(strbuf *ob, const uint8_t *src, size_t size);
-extern void houdini_unescape_html_f(strbuf *ob, const uint8_t *src, size_t 
size);
-extern int houdini_escape_xml(strbuf *ob, const uint8_t *src, size_t size);
-extern int houdini_escape_uri(strbuf *ob, const uint8_t *src, size_t size);
-extern int houdini_escape_url(strbuf *ob, const uint8_t *src, size_t size);
-extern int houdini_escape_href(strbuf *ob, const uint8_t *src, size_t size);
-extern int houdini_unescape_uri(strbuf *ob, const uint8_t *src, size_t size);
-extern int houdini_unescape_url(strbuf *ob, const uint8_t *src, size_t size);
-extern int houdini_escape_js(strbuf *ob, const uint8_t *src, size_t size);
-extern int houdini_unescape_js(strbuf *ob, const uint8_t *src, size_t size);
+extern size_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src, 
size_t size);
+extern int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, size_t 
size, int secure);
+extern int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src, 
size_t size);
+extern int houdini_escape_xml(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern int houdini_escape_uri(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern int houdini_escape_url(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern int houdini_unescape_uri(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern int houdini_unescape_url(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern int houdini_escape_js(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
+extern int houdini_unescape_js(cmark_strbuf *ob, const uint8_t *src, size_t 
size);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/houdini_href_e.c
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/houdini_href_e.c 
b/compiler/modules/CommonMark/src/houdini_href_e.c
index 1c99432..7527780 100644
--- a/compiler/modules/CommonMark/src/houdini_href_e.c
+++ b/compiler/modules/CommonMark/src/houdini_href_e.c
@@ -49,7 +49,7 @@ static const char HREF_SAFE[] = {
 };
 
 int
-houdini_escape_href(strbuf *ob, const uint8_t *src, size_t size)
+houdini_escape_href(cmark_strbuf *ob, const uint8_t *src, size_t size)
 {
        static const uint8_t hex_chars[] = "0123456789ABCDEF";
        size_t  i = 0, org;
@@ -63,7 +63,7 @@ houdini_escape_href(strbuf *ob, const uint8_t *src, size_t 
size)
                        i++;
 
                if (likely(i > org))
-                       strbuf_put(ob, src + org, i - org);
+                       cmark_strbuf_put(ob, src + org, i - org);
 
                /* escaping */
                if (i >= size)
@@ -73,23 +73,23 @@ houdini_escape_href(strbuf *ob, const uint8_t *src, size_t 
size)
                /* amp appears all the time in URLs, but needs
                 * HTML-entity escaping to be inside an href */
                case '&':
-                       strbuf_puts(ob, "&amp;");
+                       cmark_strbuf_puts(ob, "&amp;");
                        break;
 
                /* the single quote is a valid URL character
                 * according to the standard; it needs HTML
                 * entity escaping too */
                case '\'':
-                       strbuf_puts(ob, "&#x27;");
+                       cmark_strbuf_puts(ob, "&#x27;");
                        break;
 
-               /* the space can be escaped to %20 or a plus
-                * sign. we're going with the generic escape
-                * for now. the plus thing is more commonly seen
-                * when building GET strings */
+                       /* the space can be escaped to %20 or a plus
+                        * sign. we're going with the generic escape
+                        * for now. the plus thing is more commonly seen
+                        * when building GET strings */
 #if 0
                case ' ':
-                       strbuf_putc(ob, '+');
+                       cmark_strbuf_putc(ob, '+');
                        break;
 #endif
 
@@ -97,7 +97,7 @@ houdini_escape_href(strbuf *ob, const uint8_t *src, size_t 
size)
                default:
                        hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
                        hex_str[2] = hex_chars[src[i] & 0xF];
-                       strbuf_put(ob, hex_str, 3);
+                       cmark_strbuf_put(ob, hex_str, 3);
                }
 
                i++;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/houdini_html_e.c
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/houdini_html_e.c 
b/compiler/modules/CommonMark/src/houdini_html_e.c
index db5034b..1a4c3e1 100644
--- a/compiler/modules/CommonMark/src/houdini_html_e.c
+++ b/compiler/modules/CommonMark/src/houdini_html_e.c
@@ -35,17 +35,17 @@ static const char HTML_ESCAPE_TABLE[] = {
 };
 
 static const char *HTML_ESCAPES[] = {
-        "",
-        "&quot;",
-        "&amp;",
-        "&#39;",
-        "&#47;",
-        "&lt;",
-        "&gt;"
+       "",
+       "&quot;",
+       "&amp;",
+       "&#39;",
+       "&#47;",
+       "&lt;",
+       "&gt;"
 };
 
 int
-houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t size, int secure)
+houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, size_t size, int 
secure)
 {
        size_t  i = 0, org, esc = 0;
 
@@ -55,7 +55,7 @@ houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t 
size, int secure)
                        i++;
 
                if (i > org)
-                       strbuf_put(ob, src + org, i - org);
+                       cmark_strbuf_put(ob, src + org, i - org);
 
                /* escaping */
                if (unlikely(i >= size))
@@ -63,9 +63,9 @@ houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t 
size, int secure)
 
                /* The forward slash is only escaped in secure mode */
                if ((src[i] == '/' || src[i] == '\'') && !secure) {
-                       strbuf_putc(ob, src[i]);
+                       cmark_strbuf_putc(ob, src[i]);
                } else {
-                       strbuf_puts(ob, HTML_ESCAPES[esc]);
+                       cmark_strbuf_puts(ob, HTML_ESCAPES[esc]);
                }
 
                i++;
@@ -75,7 +75,7 @@ houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t 
size, int secure)
 }
 
 int
-houdini_escape_html(strbuf *ob, const uint8_t *src, size_t size)
+houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, size_t size)
 {
        return houdini_escape_html0(ob, src, size, 1);
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/houdini_html_u.c
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/houdini_html_u.c 
b/compiler/modules/CommonMark/src/houdini_html_u.c
index b88b9d1..ecd7faa 100644
--- a/compiler/modules/CommonMark/src/houdini_html_u.c
+++ b/compiler/modules/CommonMark/src/houdini_html_u.c
@@ -8,7 +8,7 @@
 #include "html_unescape.h"
 
 size_t
-houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t size)
+houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src, size_t size)
 {
        size_t i = 0;
 
@@ -55,7 +55,8 @@ houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t 
size)
                                const struct html_ent *entity = 
find_entity((char *)src, i);
 
                                if (entity != NULL) {
-                                       strbuf_put(ob, entity->utf8, 
entity->utf8_len);
+                                       size_t len = strnlen((const char 
*)entity->utf8, 4);
+                                       cmark_strbuf_put(ob, entity->utf8, len);
                                        return i + 1;
                                }
 
@@ -68,7 +69,7 @@ houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t 
size)
 }
 
 int
-houdini_unescape_html(strbuf *ob, const uint8_t *src, size_t size)
+houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src, size_t size)
 {
        size_t  i = 0, org, ent;
 
@@ -82,10 +83,10 @@ houdini_unescape_html(strbuf *ob, const uint8_t *src, 
size_t size)
                                if (i >= size)
                                        return 0;
 
-                               strbuf_grow(ob, HOUDINI_UNESCAPED_SIZE(size));
+                               cmark_strbuf_grow(ob, 
HOUDINI_UNESCAPED_SIZE(size));
                        }
 
-                       strbuf_put(ob, src + org, i - org);
+                       cmark_strbuf_put(ob, src + org, i - org);
                }
 
                /* escaping */
@@ -99,14 +100,14 @@ houdini_unescape_html(strbuf *ob, const uint8_t *src, 
size_t size)
 
                /* not really an entity */
                if (ent == 0)
-                       strbuf_putc(ob, '&');
+                       cmark_strbuf_putc(ob, '&');
        }
 
        return 1;
 }
 
-void houdini_unescape_html_f(strbuf *ob, const uint8_t *src, size_t size)
+void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src, size_t size)
 {
        if (!houdini_unescape_html(ob, src, size))
-               strbuf_put(ob, src, size);
+               cmark_strbuf_put(ob, src, size);
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5672da15/compiler/modules/CommonMark/src/html.c
----------------------------------------------------------------------
diff --git a/compiler/modules/CommonMark/src/html.c 
b/compiler/modules/CommonMark/src/html.c
index 60229cc..abc3e83 100644
--- a/compiler/modules/CommonMark/src/html.c
+++ b/compiler/modules/CommonMark/src/html.c
@@ -11,10 +11,7 @@
 
 // Functions to convert cmark_nodes to HTML strings.
 
-static bool
-finish_node(strbuf *html, cmark_node *node, bool tight);
-
-static void escape_html(strbuf *dest, const unsigned char *source, int length)
+static void escape_html(cmark_strbuf *dest, const unsigned char *source, int 
length)
 {
        if (length < 0)
                length = strlen((char *)source);
@@ -22,7 +19,7 @@ static void escape_html(strbuf *dest, const unsigned char 
*source, int length)
        houdini_escape_html0(dest, source, (size_t)length, 0);
 }
 
-static void escape_href(strbuf *dest, const unsigned char *source, int length)
+static void escape_href(cmark_strbuf *dest, const unsigned char *source, int 
length)
 {
        if (length < 0)
                length = strlen((char *)source);
@@ -30,328 +27,298 @@ static void escape_href(strbuf *dest, const unsigned char 
*source, int length)
        houdini_escape_href(dest, source, (size_t)length);
 }
 
-static inline void cr(strbuf *html)
+static inline void cr(cmark_strbuf *html)
 {
        if (html->size && html->ptr[html->size - 1] != '\n')
-               strbuf_putc(html, '\n');
+               cmark_strbuf_putc(html, '\n');
 }
 
-// Convert the inline children of a node to a plain string.
-static void inlines_to_plain_html(strbuf *html, cmark_node* node)
-{
-       cmark_node* cur = node->first_child;
-
-       if (cur == NULL) {
-               return;
-       }
-
-       while (true) {
-               switch(cur->type) {
-               case NODE_TEXT:
-               case NODE_INLINE_CODE:
-               case NODE_INLINE_HTML:
-                       escape_html(html, cur->as.literal.data, 
cur->as.literal.len);
-                       break;
-
-               case NODE_LINEBREAK:
-               case NODE_SOFTBREAK:
-                       strbuf_putc(html, ' ');
-                       break;
+struct render_state {
+       cmark_strbuf* html;
+       cmark_node *plain;
+};
 
-               default:
-                       break;
-               }
-
-               if (cur->first_child) {
-                       cur = cur->first_child;
-                       continue;
-               }
-
-       next_sibling:
-               if (cur->next) {
-                       cur = cur->next;
-                       continue;
-               }
-               cur = cur->parent;
-               if (cur == node) {
-                       break;
-               }
-               goto next_sibling;
+static void
+S_render_sourcepos(cmark_node *node, cmark_strbuf *html, long options)
+{
+       if (CMARK_OPT_SOURCEPOS & options) {
+               cmark_strbuf_printf(html, " data-sourcepos=\"%d:%d-%d:%d\"",
+                                   cmark_node_get_start_line(node),
+                                   cmark_node_get_start_column(node),
+                                   cmark_node_get_end_line(node),
+                                   cmark_node_get_end_column(node));
        }
 }
 
-
-// Convert a cmark_node to HTML.
-static void node_to_html(strbuf *html, cmark_node *node)
+static int
+S_render_node(cmark_node *node, cmark_event_type ev_type,
+              struct render_state *state, long options)
 {
-       cmark_node *cur;
-       char start_header[] = "<h0>";
-       bool tight = false;
-       bool visit_children;
-       strbuf *info;
-
-       if (node == NULL) {
-               return;
-       }
+       cmark_node *parent;
+       cmark_node *grandparent;
+       cmark_strbuf *html = state->html;
+       char start_header[] = "<h0";
+       char end_header[] = "</h0";
+       bool tight;
 
-       cur = node;
-       while (true) {
-               // Only NODE_IMAGE wants to skip its children.
-               visit_children = true;
+       bool entering = (ev_type == CMARK_EVENT_ENTER);
 
-               switch(cur->type) {
-               case NODE_DOCUMENT:
-                       break;
+       if (state->plain == node) { // back at original node
+               state->plain = NULL;
+       }
 
-               case NODE_PARAGRAPH:
-                       if (!tight) {
-                               cr(html);
-                               strbuf_puts(html, "<p>");
-                       }
+       if (state->plain != NULL) {
+               switch(node->type) {
+               case CMARK_NODE_TEXT:
+               case CMARK_NODE_CODE:
+               case CMARK_NODE_INLINE_HTML:
+                       escape_html(html, node->as.literal.data,
+                                   node->as.literal.len);
                        break;
 
-               case NODE_BLOCK_QUOTE:
-                       cr(html);
-                       strbuf_puts(html, "<blockquote>\n");
-                       // BLOCK_QUOTE doesn't use any of the 'as' structs,
-                       // so the 'list' member can be used to store the
-                       // current value of 'tight'.
-                       cur->as.list.tight = tight;
-                       tight = false;
+               case CMARK_NODE_LINEBREAK:
+               case CMARK_NODE_SOFTBREAK:
+                       cmark_strbuf_putc(html, ' ');
                        break;
 
-               case NODE_LIST_ITEM:
-                       cr(html);
-                       strbuf_puts(html, "<li>");
+               default:
                        break;
+               }
+               return 1;
+       }
 
-               case NODE_LIST: {
-                       cmark_list *list = &cur->as.list;
-                       bool tmp;
+       switch (node->type) {
+       case CMARK_NODE_DOCUMENT:
+               break;
 
-                       // make sure a list starts at the beginning of the line:
+       case CMARK_NODE_BLOCK_QUOTE:
+               if (entering) {
                        cr(html);
-
-                       if (list->list_type == CMARK_BULLET_LIST) {
-                               strbuf_puts(html, "<ul>\n");
-                       }
-                       else if (list->start == 1) {
-                               strbuf_puts(html, "<ol>\n");
-                       }
-                       else {
-                               strbuf_printf(html, "<ol start=\"%d\">\n",
-                                             list->start);
-                       }
-
-                       // Store the current value of 'tight' by swapping.
-                       tmp = list->tight;
-                       list->tight = tight;
-                       tight = tmp;
-                       break;
+                       cmark_strbuf_puts(html, "<blockquote");
+                       S_render_sourcepos(node, html, options);
+                       cmark_strbuf_puts(html, ">\n");
+               } else {
+                       cr(html);
+                       cmark_strbuf_puts(html, "</blockquote>\n");
                }
+               break;
 
-               case NODE_HEADER:
-                       cr(html);
-                       start_header[2] = '0' + cur->as.header.level;
-                       strbuf_puts(html, start_header);
-                       break;
+       case CMARK_NODE_LIST: {
+               cmark_list_type list_type = node->as.list.list_type;
+               int start = node->as.list.start;
 
-               case NODE_CODE_BLOCK:
-                       info = &cur->as.code.info;
+               if (entering) {
                        cr(html);
-
-                       if (&cur->as.code.fence_length == 0
-                           || strbuf_len(info) == 0) {
-                               strbuf_puts(html, "<pre><code>");
+                       if (list_type == CMARK_BULLET_LIST) {
+                               cmark_strbuf_puts(html, "<ul");
+                               S_render_sourcepos(node, html, options);
+                               cmark_strbuf_puts(html, ">\n");
+                       } else if (start == 1) {
+                               cmark_strbuf_puts(html, "<ol");
+                               S_render_sourcepos(node, html, options);
+                               cmark_strbuf_puts(html, ">\n");
+                       } else {
+                               cmark_strbuf_printf(html,
+                                                   "<ol start=\"%d\"",
+                                                   start);
+                               S_render_sourcepos(node, html, options);
+                               cmark_strbuf_puts(html, ">\n");
                        }
-                       else {
-                               int first_tag = strbuf_strchr(info, ' ', 0);
-                               if (first_tag < 0)
-                                       first_tag = strbuf_len(info);
-
-                               strbuf_puts(html,
-                                           "<pre><code class=\"language-");
-                               escape_html(html, info->ptr, first_tag);
-                               strbuf_puts(html, "\">");
-                       }
-
-                       escape_html(html, cur->string_content.ptr, 
cur->string_content.size);
-                       break;
+               } else {
+                       cmark_strbuf_puts(html,
+                                         list_type == CMARK_BULLET_LIST ?
+                                         "</ul>\n" : "</ol>\n");
+               }
+               break;
+       }
 
-               case NODE_HTML:
+       case CMARK_NODE_ITEM:
+               if (entering) {
                        cr(html);
-                       strbuf_put(html, cur->string_content.ptr, 
cur->string_content.size);
-                       break;
+                       cmark_strbuf_puts(html, "<li");
+                       S_render_sourcepos(node, html, options);
+                       cmark_strbuf_putc(html, '>');
+               } else {
+                       cmark_strbuf_puts(html, "</li>\n");
+               }
+               break;
 
-               case NODE_HRULE:
+       case CMARK_NODE_HEADER:
+               if (entering) {
                        cr(html);
-                       strbuf_puts(html, "<hr />\n");
-                       break;
-
-               case NODE_REFERENCE_DEF:
-                       break;
-
-               case NODE_TEXT:
-                       escape_html(html, cur->as.literal.data, 
cur->as.literal.len);
-                       break;
-
-               case NODE_LINEBREAK:
-                       strbuf_puts(html, "<br />\n");
-                       break;
-
-               case NODE_SOFTBREAK:
-                       strbuf_putc(html, '\n');
-                       break;
-
-               case NODE_INLINE_CODE:
-                       strbuf_puts(html, "<code>");
-                       escape_html(html, cur->as.literal.data, 
cur->as.literal.len);
-                       break;
-
-               case NODE_INLINE_HTML:
-                       strbuf_put(html,
-                                  cur->as.literal.data,
-                                  cur->as.literal.len);
-                       break;
-
-               case NODE_LINK:
-                       strbuf_puts(html, "<a href=\"");
-                       if (cur->as.link.url)
-                               escape_href(html, cur->as.link.url, -1);
-
-                       if (cur->as.link.title) {
-                               strbuf_puts(html, "\" title=\"");
-                               escape_html(html, cur->as.link.title, -1);
-                       }
-
-                       strbuf_puts(html, "\">");
-                       break;
-
-               case NODE_IMAGE:
-                       strbuf_puts(html, "<img src=\"");
-                       if (cur->as.link.url)
-                               escape_href(html, cur->as.link.url, -1);
-
-                       strbuf_puts(html, "\" alt=\"");
-                       inlines_to_plain_html(html, cur);
+                       start_header[2] = '0' + node->as.header.level;
+                       cmark_strbuf_puts(html, start_header);
+                       S_render_sourcepos(node, html, options);
+                       cmark_strbuf_putc(html, '>');
+               } else {
+                       end_header[3] = '0' + node->as.header.level;
+                       cmark_strbuf_puts(html, end_header);
+                       cmark_strbuf_puts(html, ">\n");
+               }
+               break;
 
-                       if (cur->as.link.title) {
-                               strbuf_puts(html, "\" title=\"");
-                               escape_html(html, cur->as.link.title, -1);
+       case CMARK_NODE_CODE_BLOCK:
+               cr(html);
+
+               if (!node->as.code.fenced || node->as.code.info.len == 0) {
+                       cmark_strbuf_puts(html, "<pre");
+                       S_render_sourcepos(node, html, options);
+                       cmark_strbuf_puts(html, "><code>");
+               } else {
+                       int first_tag = 0;
+                       while (first_tag < node->as.code.info.len &&
+                              node->as.code.info.data[first_tag] != ' ') {
+                               first_tag += 1;
                        }
 
-                       strbuf_puts(html, "\" />");
-                       visit_children = false;
-                       break;
-
-               case NODE_STRONG:
-                       strbuf_puts(html, "<strong>");
-                       break;
-
-               case NODE_EMPH:
-                       strbuf_puts(html, "<em>");
-                       break;
-
-               default:
-                       assert(false);
+                       cmark_strbuf_puts(html, "<pre");
+                       S_render_sourcepos(node, html, options);
+                       cmark_strbuf_puts(html, "><code class=\"language-");
+                       escape_html(html, node->as.code.info.data, first_tag);
+                       cmark_strbuf_puts(html, "\">");
                }
 
-               if (visit_children && cur->first_child) {
-                       cur = cur->first_child;
-                       continue;
-               }
+               escape_html(html, node->as.code.literal.data,
+                           node->as.code.literal.len);
+               cmark_strbuf_puts(html, "</code></pre>\n");
+               break;
 
-       next_sibling:
-               tight = finish_node(html, cur, tight);
-               if (cur == node) {
-                       break;
-               }
-               if (cur->next) {
-                       cur = cur->next;
-                       continue;
-               }
-               cur = cur->parent;
-               goto next_sibling;
-       }
-}
+       case CMARK_NODE_HTML:
+               cr(html);
+               cmark_strbuf_put(html, node->as.literal.data, 
node->as.literal.len);
+               break;
 
-// Returns the restored value of 'tight'.
-static bool
-finish_node(strbuf *html, cmark_node *node, bool tight)
-{
-       char end_header[] = "</h0>\n";
+       case CMARK_NODE_HRULE:
+               cr(html);
+               cmark_strbuf_puts(html, "<hr");
+               S_render_sourcepos(node, html, options);
+               cmark_strbuf_puts(html, " />\n");
+               break;
 
-       switch (node->type) {
-       case NODE_PARAGRAPH:
+       case CMARK_NODE_PARAGRAPH:
+               parent = cmark_node_parent(node);
+               grandparent = cmark_node_parent(parent);
+               if (grandparent != NULL &&
+                   grandparent->type == CMARK_NODE_LIST) {
+                       tight = grandparent->as.list.tight;
+               } else {
+                       tight = false;
+               }
                if (!tight) {
-                       strbuf_puts(html, "</p>\n");
+                       if (entering) {
+                               cr(html);
+                               cmark_strbuf_puts(html, "<p");
+                               S_render_sourcepos(node, html, options);
+                               cmark_strbuf_putc(html, '>');
+                       } else {
+                               cmark_strbuf_puts(html, "</p>\n");
+                       }
                }
                break;
 
-       case NODE_BLOCK_QUOTE: {
-               cmark_list *list = &node->as.list;
-               strbuf_puts(html, "</blockquote>\n");
-               // Restore old 'tight' value.
-               tight = list->tight;
-               list->tight = false;
+       case CMARK_NODE_TEXT:
+               escape_html(html, node->as.literal.data,
+                           node->as.literal.len);
                break;
-       }
 
-       case NODE_LIST_ITEM:
-               strbuf_puts(html, "</li>\n");
+       case CMARK_NODE_LINEBREAK:
+               cmark_strbuf_puts(html, "<br />\n");
                break;
 
-       case NODE_LIST: {
-               cmark_list *list = &node->as.list;
-               bool tmp;
-               strbuf_puts(html,
-                           list->list_type == CMARK_BULLET_LIST ?
-                           "</ul>\n" : "</ol>\n");
-               // Restore old 'tight' value.
-               tmp = tight;
-               tight = list->tight;
-               list->tight = tmp;
+       case CMARK_NODE_SOFTBREAK:
+               if (options & CMARK_OPT_HARDBREAKS) {
+                       cmark_strbuf_puts(html, "<br />\n");
+               } else {
+                       cmark_strbuf_putc(html, '\n');
+               }
                break;
-       }
 
-       case NODE_HEADER:
-               end_header[3] = '0' + node->as.header.level;
-               strbuf_puts(html, end_header);
+       case CMARK_NODE_CODE:
+               cmark_strbuf_puts(html, "<code>");
+               escape_html(html, node->as.literal.data, node->as.literal.len);
+               cmark_strbuf_puts(html, "</code>");
                break;
 
-       case NODE_CODE_BLOCK:
-               strbuf_puts(html, "</code></pre>\n");
+       case CMARK_NODE_INLINE_HTML:
+               cmark_strbuf_put(html, node->as.literal.data, 
node->as.literal.len);
                break;
 
-       case NODE_INLINE_CODE:
-               strbuf_puts(html, "</code>");
+       case CMARK_NODE_STRONG:
+               if (entering) {
+                       cmark_strbuf_puts(html, "<strong>");
+               } else {
+                       cmark_strbuf_puts(html, "</strong>");
+               }
                break;
 
-       case NODE_LINK:
-               strbuf_puts(html, "</a>");
+       case CMARK_NODE_EMPH:
+               if (entering) {
+                       cmark_strbuf_puts(html, "<em>");
+               } else {
+                       cmark_strbuf_puts(html, "</em>");
+               }
                break;
 
-       case NODE_STRONG:
-               strbuf_puts(html, "</strong>");
+       case CMARK_NODE_LINK:
+               if (entering) {
+                       cmark_strbuf_puts(html, "<a href=\"");
+                       if (node->as.link.url)
+                               escape_href(html, node->as.link.url, -1);
+
+                       if (node->as.link.title) {
+                               cmark_strbuf_puts(html, "\" title=\"");
+                               escape_html(html, node->as.link.title, -1);
+                       }
+
+                       cmark_strbuf_puts(html, "\">");
+               } else {
+                       cmark_strbuf_puts(html, "</a>");
+               }
                break;
 
-       case NODE_EMPH:
-               strbuf_puts(html, "</em>");
+       case CMARK_NODE_IMAGE:
+               if (entering) {
+                       cmark_strbuf_puts(html, "<img src=\"");
+                       if (node->as.link.url)
+                               escape_href(html, node->as.link.url, -1);
+
+                       cmark_strbuf_puts(html, "\" alt=\"");
+                       state->plain = node;
+               } else {
+                       if (node->as.link.title) {
+                               cmark_strbuf_puts(html, "\" title=\"");
+                               escape_html(html, node->as.link.title, -1);
+                       }
+
+                       cmark_strbuf_puts(html, "\" />");
+               }
                break;
 
        default:
+               assert(false);
                break;
        }
 
-       return tight;
+       // cmark_strbuf_putc(html, 'x');
+       return 1;
 }
 
-char *cmark_render_html(cmark_node *root)
+char *cmark_render_html(cmark_node *root, long options)
 {
        char *result;
-       strbuf html = GH_BUF_INIT;
-       node_to_html(&html, root);
-       result = (char *)strbuf_detach(&html);
-       strbuf_free(&html);
+       cmark_strbuf html = GH_BUF_INIT;
+       cmark_event_type ev_type;
+       cmark_node *cur;
+       struct render_state state = { &html, NULL };
+       cmark_iter *iter = cmark_iter_new(root);
+
+       while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
+               cur = cmark_iter_get_node(iter);
+               S_render_node(cur, ev_type, &state, options);
+       }
+       result = (char *)cmark_strbuf_detach(&html);
+
+       cmark_iter_free(iter);
+       cmark_strbuf_free(&html);
        return result;
 }

Reply via email to