Ignore code blocks of other host languages
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/7973bf5b Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/7973bf5b Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/7973bf5b Branch: refs/heads/master Commit: 7973bf5b99e0128520ae32a2c5680bf37912652f Parents: d11a489 Author: Nick Wellnhofer <[email protected]> Authored: Sun Jul 26 03:04:25 2015 +0200 Committer: Nick Wellnhofer <[email protected]> Committed: Thu Aug 6 18:19:19 2015 +0200 ---------------------------------------------------------------------- compiler/src/CFCCHtml.c | 60 ++++++++++++++++++++++++++++++++------ compiler/src/CFCCMan.c | 60 +++++++++++++++++++++++++++++--------- compiler/src/CFCDocuComment.c | 15 ++++++++++ compiler/src/CFCDocuComment.h | 9 ++++++ compiler/src/CFCPerlPod.c | 42 +++++++++++++++++++------- 5 files changed, 152 insertions(+), 34 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7973bf5b/compiler/src/CFCCHtml.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCCHtml.c b/compiler/src/CFCCHtml.c index 3c953fe..aa240b0 100644 --- a/compiler/src/CFCCHtml.c +++ b/compiler/src/CFCCHtml.c @@ -159,10 +159,13 @@ static char* S_md_to_html(const char *md, CFCClass *klass, int dir_level); static void -S_convert_uris(cmark_node *node, CFCClass *klass, int dir_level); +S_transform_doc(cmark_node *node, CFCClass *klass, int dir_level); + +static int +S_transform_code_block(cmark_node *node, int found_matching_code_block); static void -S_convert_uri(cmark_node *link, CFCClass *klass, int dir_level); +S_transform_link(cmark_node *link, CFCClass *klass, int dir_level); static char* S_type_to_html(CFCClass *klass, CFCType *type); @@ -939,7 +942,7 @@ S_md_to_html(const char *md, CFCClass *klass, int dir_level) { | CMARK_OPT_VALIDATE_UTF8 | CMARK_OPT_SAFE; cmark_node *doc = cmark_parse_document(md, strlen(md), options); - S_convert_uris(doc, klass, dir_level); + S_transform_doc(doc, klass, dir_level); char *html = cmark_render_html(doc, CMARK_OPT_DEFAULT); cmark_node_free(doc); @@ -947,25 +950,64 @@ S_md_to_html(const char *md, CFCClass *klass, int dir_level) { } static void -S_convert_uris(cmark_node *node, CFCClass *klass, int dir_level) { +S_transform_doc(cmark_node *node, CFCClass *klass, int dir_level) { + int found_matching_code_block = false; cmark_iter *iter = cmark_iter_new(node); cmark_event_type ev_type; while (CMARK_EVENT_DONE != (ev_type = cmark_iter_next(iter))) { cmark_node *cur = cmark_iter_get_node(iter); + cmark_node_type type = cmark_node_get_type(cur); + + switch (type) { + case CMARK_NODE_CODE_BLOCK: + found_matching_code_block + = S_transform_code_block(cur, found_matching_code_block); + break; + + case CMARK_NODE_LINK: + if (ev_type == CMARK_EVENT_EXIT) { + S_transform_link(cur, klass, dir_level); + } + break; - if (ev_type == CMARK_EVENT_EXIT - && cmark_node_get_type(cur) == NODE_LINK - ) { - S_convert_uri(cur, klass, dir_level); + default: + break; } } cmark_iter_free(iter); } +static int +S_transform_code_block(cmark_node *code_block, int found_matching_code_block) { + int is_host = CFCMarkdown_code_block_is_host(code_block, "c"); + + if (is_host) { + found_matching_code_block = true; + } + + if (CFCMarkdown_code_block_is_last(code_block)) { + if (!found_matching_code_block) { + cmark_node *warning + = cmark_node_new(CMARK_NODE_CODE_BLOCK); + cmark_node_set_literal(warning, + "Code example for C is missing"); + cmark_node_insert_after(code_block, warning); + } + else { + // Reset. + found_matching_code_block = false; + } + } + + if (!is_host) { cmark_node_free(code_block); } + + return found_matching_code_block; +} + static void -S_convert_uri(cmark_node *link, CFCClass *klass, int dir_level) { +S_transform_link(cmark_node *link, CFCClass *klass, int dir_level) { const char *uri_string = cmark_node_get_url(link); if (!uri_string || !CFCUri_is_clownfish_uri(uri_string)) { return; http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7973bf5b/compiler/src/CFCCMan.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCCMan.c b/compiler/src/CFCCMan.c index 79248c8..6089ca3 100644 --- a/compiler/src/CFCCMan.c +++ b/compiler/src/CFCCMan.c @@ -427,6 +427,7 @@ S_nodes_to_man(CFCClass *klass, cmark_node *node, int needs_indent) { int level = needs_indent ? 1 : 0; int has_indent = needs_indent; int has_vspace = true; + int found_matching_code_block = false; cmark_iter *iter = cmark_iter_new(node); cmark_event_type ev_type; @@ -497,23 +498,54 @@ S_nodes_to_man(CFCClass *klass, cmark_node *node, int needs_indent) { break; case CMARK_NODE_CODE_BLOCK: { - if (level > 0) { - result = CFCUtil_cat(result, ".RS\n", NULL); - } + int is_host = CFCMarkdown_code_block_is_host(node, "c"); - const char *content = cmark_node_get_literal(node); - char *escaped = S_man_escape(content); - result = CFCUtil_cat(result, ".IP\n.nf\n.fam C\n", escaped, - ".fam\n.fi\n", NULL); - FREEMEM(escaped); + if (is_host) { + found_matching_code_block = true; - if (level > 0) { - result = CFCUtil_cat(result, ".RE\n", NULL); - has_indent = false; + if (level > 0) { + result = CFCUtil_cat(result, ".RS\n", NULL); + } + + const char *content = cmark_node_get_literal(node); + char *escaped = S_man_escape(content); + result = CFCUtil_cat(result, ".IP\n.nf\n.fam C\n", escaped, + ".fam\n.fi\n", NULL); + FREEMEM(escaped); + + if (level > 0) { + result = CFCUtil_cat(result, ".RE\n", NULL); + has_indent = false; + } + else { + has_indent = true; + has_vspace = false; + } } - else { - has_indent = true; - has_vspace = false; + + if (CFCMarkdown_code_block_is_last(node)) { + if (!found_matching_code_block) { + if (level > 0) { + result = CFCUtil_cat(result, ".RS\n", NULL); + } + result = CFCUtil_cat(result, + ".IP\n.nf\n.fam C\n" + "Code example for Perl is missing\n", + ".fam\n.fi\n", + NULL); + if (level > 0) { + result = CFCUtil_cat(result, ".RE\n", NULL); + has_indent = false; + } + else { + has_indent = true; + has_vspace = false; + } + } + else { + // Reset. + found_matching_code_block = false; + } } break; http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7973bf5b/compiler/src/CFCDocuComment.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCDocuComment.c b/compiler/src/CFCDocuComment.c index d88335f..ce59275 100644 --- a/compiler/src/CFCDocuComment.c +++ b/compiler/src/CFCDocuComment.c @@ -16,6 +16,7 @@ #include <ctype.h> #include <string.h> +#include <cmark.h> #define CFC_NEED_BASE_STRUCT_DEF #include "CFCBase.h" @@ -253,3 +254,17 @@ CFCDocuComment_get_retval(CFCDocuComment *self) { return self->retval; } +int +CFCMarkdown_code_block_is_host(cmark_node *code_block, const char *lang) { + const char *fence_info = cmark_node_get_fence_info(code_block); + return !fence_info + || fence_info[0] == '\0' + || strcmp(fence_info, lang) == 0; +} + +int +CFCMarkdown_code_block_is_last(cmark_node *code_block) { + cmark_node *next = cmark_node_next(code_block); + return !next || cmark_node_get_type(next) != CMARK_NODE_CODE_BLOCK; +} + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7973bf5b/compiler/src/CFCDocuComment.h ---------------------------------------------------------------------- diff --git a/compiler/src/CFCDocuComment.h b/compiler/src/CFCDocuComment.h index 910f191..8b44c83 100644 --- a/compiler/src/CFCDocuComment.h +++ b/compiler/src/CFCDocuComment.h @@ -26,6 +26,8 @@ extern "C" { typedef struct CFCDocuComment CFCDocuComment; +struct cmark_node; + /** Parse comment text. */ CFCDocuComment* @@ -53,6 +55,13 @@ CFCDocuComment_get_param_docs(CFCDocuComment *self); const char* CFCDocuComment_get_retval(CFCDocuComment *self); +int +CFCMarkdown_code_block_is_host(struct cmark_node *code_block, + const char *lang); + +int +CFCMarkdown_code_block_is_last(struct cmark_node *code_block); + #ifdef __cplusplus } #endif http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7973bf5b/compiler/src/CFCPerlPod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCPerlPod.c b/compiler/src/CFCPerlPod.c index 8fc2eae..fa221e4 100644 --- a/compiler/src/CFCPerlPod.c +++ b/compiler/src/CFCPerlPod.c @@ -340,6 +340,7 @@ S_nodes_to_pod(cmark_node *node, CFCClass *klass, int header_level) { return result; } + int found_matching_code_block = false; cmark_iter *iter = cmark_iter_new(node); cmark_event_type ev_type; @@ -388,18 +389,37 @@ S_nodes_to_pod(cmark_node *node, CFCClass *klass, int header_level) { break; case CMARK_NODE_CODE_BLOCK: { - const char *content = cmark_node_get_literal(node); - char *copy = CFCUtil_strdup(content); - // Chomp trailing newline. - size_t len = strlen(copy); - if (len > 0 && copy[len-1] == '\n') { - copy[len-1] = '\0'; + int is_host = CFCMarkdown_code_block_is_host(node, "perl"); + + if (is_host) { + found_matching_code_block = true; + + const char *content = cmark_node_get_literal(node); + char *copy = CFCUtil_strdup(content); + // Chomp trailing newline. + size_t len = strlen(copy); + if (len > 0 && copy[len-1] == '\n') { + copy[len-1] = '\0'; + } + char *indented + = CFCUtil_global_replace(copy, "\n", "\n "); + result + = CFCUtil_cat(result, " ", indented, "\n\n", NULL); + FREEMEM(indented); + FREEMEM(copy); + } + + if (CFCMarkdown_code_block_is_last(node)) { + if (!found_matching_code_block) { + result = CFCUtil_cat(result, + " Code example for Perl is missing\n\n"); + } + else { + // Reset. + found_matching_code_block = false; + } } - char *indented - = CFCUtil_global_replace(copy, "\n", "\n "); - result = CFCUtil_cat(result, " ", indented, "\n\n", NULL); - FREEMEM(indented); - FREEMEM(copy); + break; }
