static cmark_node *fixup_nodes(cmark_inline_parser *inline_parser, cmark_node *parent, int size) { int node_text_len; cmark_node *prev = NULL; cmark_node *tmp; int name_size = size; cmark_strbuf *name; for (prev = cmark_node_last_child(parent); prev; prev = cmark_node_previous(prev)) { if (cmark_node_get_type(prev) == CMARK_NODE_TEXT) { const char *text = cmark_node_get_literal(prev); node_text_len = strlen(text); size -= node_text_len; if (size <= 0) { if (size < 0) { char *split_text = my_strndup(text, size * -1); cmark_node *split = cmark_node_new(CMARK_NODE_TEXT); cmark_node_set_literal(split, split_text); free(split_text); split_text = my_strndup(text + (size * - 1), node_text_len - size); cmark_node_set_literal(prev, split_text); free(split_text); cmark_node_insert_before(prev, split); } break; } } else { return NULL; } } name = cmark_strbuf_new(name_size + 1); tmp = prev; while (tmp) { cmark_node *next = cmark_node_next(tmp); cmark_strbuf_puts(name, cmark_node_get_literal(tmp)); if (tmp != prev) cmark_node_free(tmp); tmp = next; } cmark_node_set_type(prev, CMARK_NODE_LINK); cmark_node_set_url(prev, cmark_strbuf_get(name)); cmark_strbuf_free(name); return prev; }
static cmark_node *fixup_nodes(cmark_syntax_extension *self, cmark_parser *parser, cmark_inline_parser *inline_parser, cmark_node *parent, int start_offset, int size) { int node_text_len; cmark_node *prev = NULL; cmark_node *tmp; int name_size = size; cmark_strbuf *name; NamedLink *named_link; for (prev = cmark_node_last_child(parent); prev; prev = cmark_node_previous(prev)) { if (cmark_node_get_type(prev) == CMARK_NODE_TEXT) { const char *text = cmark_node_get_literal(prev); node_text_len = strlen(text); size -= node_text_len; if (size <= 0) { if (size < 0) { char *split_text = my_strndup(text, size * -1); cmark_node *split = cmark_node_new(CMARK_NODE_TEXT); cmark_node_set_literal(split, split_text); free(split_text); split_text = my_strndup(text + (size * - 1), node_text_len - size); cmark_node_set_literal(prev, split_text); free(split_text); cmark_node_insert_before(prev, split); } break; } } else { return NULL; } } name = cmark_strbuf_new(name_size + 1); tmp = prev; while (tmp) { cmark_node *next = cmark_node_next(tmp); cmark_strbuf_puts(name, cmark_node_get_literal(tmp)); if (tmp != prev) cmark_node_free(tmp); tmp = next; } named_link = PRIV(self)->link_resolve_func(cmark_strbuf_get(name)); if (!named_link || !named_link->ref) { int actual_line, actual_col; translate_sourcepos(get_first_parent_block(parent), start_offset, &actual_line, &actual_col); cmark_strbuf *message = cmark_strbuf_new(0); cmark_strbuf_puts(message, "Trying to link to non-existing symbol ‘"); cmark_strbuf_puts(message, cmark_strbuf_get(name)); cmark_strbuf_puts(message, "’"); diagnose("gtk-doc-bad-link", cmark_strbuf_get(message), actual_line - 1, actual_col - 1); cmark_strbuf_free(message); cmark_node_set_literal(prev, cmark_strbuf_get(name)); cmark_strbuf_free(name); return prev; } free_named_link(named_link); cmark_node_set_type(prev, CMARK_NODE_LINK); cmark_node_set_url(prev, cmark_strbuf_get(name)); cmark_strbuf_free(name); return prev; }
static void create_tree(test_batch_runner *runner) { char *html; cmark_node *doc = cmark_node_new(CMARK_NODE_DOCUMENT); cmark_node *p = cmark_node_new(CMARK_NODE_PARAGRAPH); OK(runner, !cmark_node_insert_before(doc, p), "insert before root fails"); OK(runner, !cmark_node_insert_after(doc, p), "insert after root fails"); OK(runner, cmark_node_append_child(doc, p), "append1"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "append1 consistent"); OK(runner, cmark_node_parent(p) == doc, "node_parent"); cmark_node *emph = cmark_node_new(CMARK_NODE_EMPH); OK(runner, cmark_node_prepend_child(p, emph), "prepend1"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "prepend1 consistent"); cmark_node *str1 = cmark_node_new(CMARK_NODE_TEXT); cmark_node_set_literal(str1, "Hello, "); OK(runner, cmark_node_prepend_child(p, str1), "prepend2"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "prepend2 consistent"); cmark_node *str3 = cmark_node_new(CMARK_NODE_TEXT); cmark_node_set_literal(str3, "!"); OK(runner, cmark_node_append_child(p, str3), "append2"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "append2 consistent"); cmark_node *str2 = cmark_node_new(CMARK_NODE_TEXT); cmark_node_set_literal(str2, "world"); OK(runner, cmark_node_append_child(emph, str2), "append3"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "append3 consistent"); html = cmark_render_html(doc, CMARK_OPT_DEFAULT); STR_EQ(runner, html, "<p>Hello, <em>world</em>!</p>\n", "render_html"); free(html); OK(runner, cmark_node_insert_before(str1, str3), "ins before1"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "ins before1 consistent"); // 31e OK(runner, cmark_node_first_child(p) == str3, "ins before1 works"); OK(runner, cmark_node_insert_before(str1, emph), "ins before2"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "ins before2 consistent"); // 3e1 OK(runner, cmark_node_last_child(p) == str1, "ins before2 works"); OK(runner, cmark_node_insert_after(str1, str3), "ins after1"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "ins after1 consistent"); // e13 OK(runner, cmark_node_next(str1) == str3, "ins after1 works"); OK(runner, cmark_node_insert_after(str1, emph), "ins after2"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "ins after2 consistent"); // 1e3 OK(runner, cmark_node_previous(emph) == str1, "ins after2 works"); cmark_node_unlink(emph); html = cmark_render_html(doc, CMARK_OPT_DEFAULT); STR_EQ(runner, html, "<p>Hello, !</p>\n", "render_html after shuffling"); free(html); cmark_node_free(doc); // TODO: Test that the contents of an unlinked inline are valid // after the parent block was destroyed. This doesn't work so far. cmark_node_free(emph); }