Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to 0.29.0.gfm.11 #236

Merged
merged 6 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,3 @@ ext/commonmarker/cmark-gfm_export.h: ext/commonmarker/cmark-upstream/build/src/c

ext/commonmarker/cmark-gfm_version.h: ext/commonmarker/cmark-upstream/build/src/cmark-gfm_version.h
cp $< $@

ext/commonmarker/cmark-gfm-extensions_export.h: ext/commonmarker/cmark-upstream/build/extensions/cmark-gfm-extensions_export.h
cp $< $@
12 changes: 11 additions & 1 deletion ext/commonmarker/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 @@ -1224,6 +1233,7 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
(*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 ext/commonmarker/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
4 changes: 2 additions & 2 deletions ext/commonmarker/cmark-gfm_version.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef CMARK_GFM_VERSION_H
#define CMARK_GFM_VERSION_H

#define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 6)
#define CMARK_GFM_VERSION_STRING "0.29.0.gfm.6"
#define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 11)
#define CMARK_GFM_VERSION_STRING "0.29.0.gfm.11"

#endif
51 changes: 18 additions & 33 deletions ext/commonmarker/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 @@ -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 ext/commonmarker/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 ext/commonmarker/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 ext/commonmarker/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
57 changes: 46 additions & 11 deletions ext/commonmarker/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 All @@ -29,7 +39,7 @@ void cmark_register_node_flag(cmark_node_internal_flags *flags) {
nextflag <<= 1;
}

void cmark_init_standard_node_flags() {}
void cmark_init_standard_node_flags(void) {}

bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
if (child_type == CMARK_NODE_DOCUMENT) {
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 @@ -554,6 +564,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
17 changes: 16 additions & 1 deletion ext/commonmarker/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 Down Expand Up @@ -119,7 +127,7 @@ void cmark_register_node_flag(cmark_node_internal_flags *flags);
* library. It is now a no-op.
*/
CMARK_GFM_EXPORT
void cmark_init_standard_node_flags();
void cmark_init_standard_node_flags(void);

static CMARK_INLINE cmark_mem *cmark_node_mem(cmark_node *node) {
return node->content.mem;
Expand All @@ -144,6 +152,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