Skip to content

Commit

Permalink
updated cmark-gfm from 0.29.0.gfm.9 to .13; bumped up version to 1.9.2 (
Browse files Browse the repository at this point in the history
  • Loading branch information
trbailey326 committed Jan 30, 2024
1 parent 89c6ddc commit 969e27e
Show file tree
Hide file tree
Showing 15 changed files with 251 additions and 151 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: commonmark
Type: Package
Title: High Performance CommonMark and Github Markdown Rendering in R
Version: 1.9.1
Version: 1.9.2
Authors@R: c(
person("Jeroen", "Ooms", ,"[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-4035-0289")),
Expand Down
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
1.9.2
- Update libcmark-gfm to 0.29.0.gfm.13

1.9.0
- Add parameter 'footnotes' to enable footnote parsing
- Update libcmark-gfm to 0.29.0.gfm.9
Expand Down
18 changes: 15 additions & 3 deletions src/cmark/blocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
#define CODE_INDENT 4
#define TAB_STOP 4

/**
* Very deeply nested lists can cause quadratic performance issues.
* This constant is used in open_new_blocks() to limit the nesting
* depth. It is unlikely that a non-contrived markdown document will
* be nested this deeply.
*/
#define MAX_LIST_DEPTH 100

#ifndef MIN
#define MIN(x, y) ((x < y) ? x : y)
#endif
Expand Down Expand Up @@ -1119,10 +1127,11 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
bool has_content;
int save_offset;
int save_column;
size_t depth = 0;

while (cont_type != CMARK_NODE_CODE_BLOCK &&
cont_type != CMARK_NODE_HTML_BLOCK) {

depth++;
S_find_first_nonspace(parser, input);
indented = parser->indent >= CODE_INDENT;

Expand Down Expand Up @@ -1208,22 +1217,25 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
parser->first_nonspace + 1);
S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
} else if (!indented &&
parser->options & CMARK_OPT_FOOTNOTES &&
(parser->options & CMARK_OPT_FOOTNOTES) &&
depth < MAX_LIST_DEPTH &&
(matched = scan_footnote_definition(input, parser->first_nonspace))) {
cmark_chunk c = cmark_chunk_dup(input, parser->first_nonspace + 2, matched - 2);
cmark_chunk_to_cstr(parser->mem, &c);

while (c.data[c.len - 1] != ']')
--c.len;
--c.len;

cmark_chunk_to_cstr(parser->mem, &c);

S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false);
*container = add_child(parser, *container, CMARK_NODE_FOOTNOTE_DEFINITION, parser->first_nonspace + matched + 1);
(*container)->as.literal = c;

(*container)->internal_offset = matched;
} else if ((!indented || cont_type == CMARK_NODE_LIST) &&
parser->indent < 4 &&
depth < MAX_LIST_DEPTH &&
(matched = parse_list_marker(
parser->mem, input, parser->first_nonspace,
(*container)->type == CMARK_NODE_PARAGRAPH, &data))) {
Expand Down
11 changes: 11 additions & 0 deletions src/cmark/cmark-gfm.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,17 @@ CMARK_GFM_EXPORT int cmark_node_get_list_tight(cmark_node *node);
*/
CMARK_GFM_EXPORT int cmark_node_set_list_tight(cmark_node *node, int tight);

/**
* Returns item index of 'node'. This is only used when rendering output
* formats such as commonmark, which need to output the index. It is not
* required for formats such as html or latex.
*/
CMARK_GFM_EXPORT int cmark_node_get_item_index(cmark_node *node);

/** Sets item index of 'node'. Returns 1 on success, 0 on failure.
*/
CMARK_GFM_EXPORT int cmark_node_set_item_index(cmark_node *node, int idx);

/** Returns the info string from a fenced code block.
*/
CMARK_GFM_EXPORT const char *cmark_node_get_fence_info(cmark_node *node);
Expand Down
53 changes: 19 additions & 34 deletions src/cmark/commonmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,23 +153,8 @@ static bool is_autolink(cmark_node *node) {
link_text->as.literal.len) == 0);
}

// if node is a block node, returns node.
// otherwise returns first block-level node that is an ancestor of node.
// if there is no block-level ancestor, returns NULL.
static cmark_node *get_containing_block(cmark_node *node) {
while (node) {
if (CMARK_NODE_BLOCK_P(node)) {
return node;
} else {
node = node->parent;
}
}
return NULL;
}

static int S_render_node(cmark_renderer *renderer, cmark_node *node,
cmark_event_type ev_type, int options) {
cmark_node *tmp;
int list_number;
cmark_delim_type list_delim;
int numticks;
Expand All @@ -180,7 +165,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
char fencechar[2] = {'\0', '\0'};
size_t info_len, code_len;
char listmarker[LISTMARKER_SIZE];
char *emph_delim;
const char *emph_delim;
bool first_in_list_item;
bufsize_t marker_width;
bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options) &&
Expand All @@ -189,14 +174,17 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
// Don't adjust tight list status til we've started the list.
// Otherwise we loose the blank line between a paragraph and
// a following list.
if (!(node->type == CMARK_NODE_ITEM && node->prev == NULL && entering)) {
tmp = get_containing_block(node);
renderer->in_tight_list_item =
tmp && // tmp might be NULL if there is no containing block
((tmp->type == CMARK_NODE_ITEM &&
cmark_node_get_list_tight(tmp->parent)) ||
(tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM &&
cmark_node_get_list_tight(tmp->parent->parent)));
if (entering) {
if (node->parent && node->parent->type == CMARK_NODE_ITEM) {
renderer->in_tight_list_item = node->parent->parent->as.list.tight;
}
} else {
if (node->type == CMARK_NODE_LIST) {
renderer->in_tight_list_item =
node->parent &&
node->parent->type == CMARK_NODE_ITEM &&
node->parent->parent->as.list.tight;
}
}

if (node->extension && node->extension->commonmark_render_func) {
Expand Down Expand Up @@ -234,13 +222,8 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
marker_width = 4;
} else {
list_number = cmark_node_get_list_start(node->parent);
list_number = cmark_node_get_item_index(node);
list_delim = cmark_node_get_list_delim(node->parent);
tmp = node;
while (tmp->prev) {
tmp = tmp->prev;
list_number += 1;
}
// we ensure a width of at least 4 so
// we get nice transition from single digits
// to double
Expand Down Expand Up @@ -405,10 +388,12 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
break;

case CMARK_NODE_STRONG:
if (entering) {
LIT("**");
} else {
LIT("**");
if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
if (entering) {
LIT("**");
} else {
LIT("**");
}
}
break;

Expand Down
10 changes: 6 additions & 4 deletions src/cmark/html.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,12 @@ static int S_render_node(cmark_html_renderer *renderer, cmark_node *node,
break;

case CMARK_NODE_STRONG:
if (entering) {
cmark_strbuf_puts(html, "<strong>");
} else {
cmark_strbuf_puts(html, "</strong>");
if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
if (entering) {
cmark_strbuf_puts(html, "<strong>");
} else {
cmark_strbuf_puts(html, "</strong>");
}
}
break;

Expand Down
10 changes: 6 additions & 4 deletions src/cmark/latex.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,12 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
break;

case CMARK_NODE_STRONG:
if (entering) {
LIT("\\textbf{");
} else {
LIT("}");
if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
if (entering) {
LIT("\\textbf{");
} else {
LIT("}");
}
}
break;

Expand Down
18 changes: 7 additions & 11 deletions src/cmark/man.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ static void S_outc(cmark_renderer *renderer, cmark_node *node,

static int S_render_node(cmark_renderer *renderer, cmark_node *node,
cmark_event_type ev_type, int options) {
cmark_node *tmp;
int list_number;
bool entering = (ev_type == CMARK_EVENT_ENTER);
bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
Expand Down Expand Up @@ -123,12 +122,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
LIT("\\[bu] 2");
} else {
list_number = cmark_node_get_list_start(node->parent);
tmp = node;
while (tmp->prev) {
tmp = tmp->prev;
list_number += 1;
}
list_number = cmark_node_get_item_index(node);
char list_number_s[LIST_NUMBER_SIZE];
snprintf(list_number_s, LIST_NUMBER_SIZE, "\"%d.\" 4", list_number);
LIT(list_number_s);
Expand Down Expand Up @@ -225,10 +219,12 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
break;

case CMARK_NODE_STRONG:
if (entering) {
LIT("\\f[B]");
} else {
LIT("\\f[]");
if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
if (entering) {
LIT("\\f[B]");
} else {
LIT("\\f[]");
}
}
break;

Expand Down
56 changes: 46 additions & 10 deletions src/cmark/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@
#include "node.h"
#include "syntax_extension.h"

/**
* Expensive safety checks are off by default, but can be enabled
* by calling cmark_enable_safety_checks().
*/
static bool enable_safety_checks = false;

void cmark_enable_safety_checks(bool enable) {
enable_safety_checks = enable;
}

static void S_node_unlink(cmark_node *node);

#define NODE_MEM(node) cmark_node_mem(node)
Expand Down Expand Up @@ -70,23 +80,23 @@ bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
}

static bool S_can_contain(cmark_node *node, cmark_node *child) {
cmark_node *cur;

if (node == NULL || child == NULL) {
return false;
}
if (NODE_MEM(node) != NODE_MEM(child)) {
return 0;
}

// Verify that child is not an ancestor of node or equal to node.
cur = node;
do {
if (cur == child) {
return false;
}
cur = cur->parent;
} while (cur != NULL);
if (enable_safety_checks) {
// Verify that child is not an ancestor of node or equal to node.
cmark_node *cur = node;
do {
if (cur == child) {
return false;
}
cur = cur->parent;
} while (cur != NULL);
}

return cmark_node_can_contain_type(node, (cmark_node_type) child->type);
}
Expand Down Expand Up @@ -367,6 +377,7 @@ const char *cmark_node_get_literal(cmark_node *node) {
case CMARK_NODE_HTML_INLINE:
case CMARK_NODE_CODE:
case CMARK_NODE_FOOTNOTE_REFERENCE:
case CMARK_NODE_FOOTNOTE_DEFINITION:
return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal);

case CMARK_NODE_CODE_BLOCK:
Expand Down Expand Up @@ -554,6 +565,31 @@ int cmark_node_set_list_tight(cmark_node *node, int tight) {
}
}

int cmark_node_get_item_index(cmark_node *node) {
if (node == NULL) {
return 0;
}

if (node->type == CMARK_NODE_ITEM) {
return node->as.list.start;
} else {
return 0;
}
}

int cmark_node_set_item_index(cmark_node *node, int idx) {
if (node == NULL || idx < 0) {
return 0;
}

if (node->type == CMARK_NODE_ITEM) {
node->as.list.start = idx;
return 1;
} else {
return 0;
}
}

const char *cmark_node_get_fence_info(cmark_node *node) {
if (node == NULL) {
return NULL;
Expand Down
16 changes: 16 additions & 0 deletions src/cmark/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ struct cmark_node {

cmark_syntax_extension *extension;

/**
* Used during cmark_render() to cache the most recent non-NULL
* extension, if you go up the parent chain like this:
*
* node->parent->...parent->extension
*/
cmark_syntax_extension *ancestor_extension;

union {
int ref_ix;
int def_count;
Expand All @@ -97,6 +105,7 @@ struct cmark_node {
cmark_link link;
cmark_custom custom;
int html_block_type;
int cell_index; // For keeping track of TABLE_CELL table alignments
void *opaque;
} as;
};
Expand Down Expand Up @@ -144,6 +153,13 @@ static CMARK_INLINE bool CMARK_NODE_INLINE_P(cmark_node *node) {

CMARK_GFM_EXPORT bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type);

/**
* Enable (or disable) extra safety checks. These extra checks cause
* extra performance overhead (in some cases quadratic), so they are only
* intended to be used during testing.
*/
CMARK_GFM_EXPORT void cmark_enable_safety_checks(bool enable);

#ifdef __cplusplus
}
#endif
Expand Down
Loading

0 comments on commit 969e27e

Please sign in to comment.