Fix quadratic behavior involving get_containing_block
Fix quadratic behavior in the Commonmark renderer when determining the tight list status in deeply nested inlines. Instead of searching for the containing block, update the tight list status when - entering a child of a list item - exiting a list Fixes #431.
This commit is contained in:
parent
99b48963a2
commit
2dca096d8e
@ -150,21 +150,6 @@ static bool is_autolink(cmark_node *node) {
|
||||
strcmp((const char *)url, (char *)link_text->data) == 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 (node->type >= CMARK_NODE_FIRST_BLOCK &&
|
||||
node->type <= CMARK_NODE_LAST_BLOCK) {
|
||||
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;
|
||||
@ -186,16 +171,19 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
||||
!(CMARK_OPT_HARDBREAKS & options);
|
||||
|
||||
// Don't adjust tight list status til we've started the list.
|
||||
// Otherwise we loose the blank line between a paragraph and
|
||||
// Otherwise we lose 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;
|
||||
}
|
||||
}
|
||||
|
||||
switch (node->type) {
|
||||
|
@ -111,6 +111,9 @@ pathological = {
|
||||
}
|
||||
|
||||
pathological_cmark = {
|
||||
"nested inlines":
|
||||
("*" * 40000 + "a" + "*" * 40000,
|
||||
re.compile("^\*+a\*+$")),
|
||||
}
|
||||
|
||||
whitespace_re = re.compile('/s+/')
|
||||
|
Loading…
Reference in New Issue
Block a user