Skip to content

Commit

Permalink
Update common mark code from upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
melroy89 committed Dec 14, 2023
1 parent 8a07a63 commit b0b6a3f
Show file tree
Hide file tree
Showing 22 changed files with 14,400 additions and 10,566 deletions.
17 changes: 9 additions & 8 deletions lib/commonmarker/src/arena.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,16 @@ static void *arena_calloc(size_t nmem, size_t size) {
const size_t align = sizeof(size_t) - 1;
sz = (sz + align) & ~align;

struct arena_chunk *chunk;
if (sz > A->sz) {
A->prev = alloc_arena_chunk(sz, A->prev);
return (uint8_t *) A->prev->ptr + sizeof(size_t);
A->prev = chunk = alloc_arena_chunk(sz, A->prev);
} else if (sz > A->sz - A->used) {
A = chunk = alloc_arena_chunk(A->sz + A->sz / 2, A);
} else {
chunk = A;
}
if (sz > A->sz - A->used) {
A = alloc_arena_chunk(A->sz + A->sz / 2, A);
}
void *ptr = (uint8_t *) A->ptr + A->used;
A->used += sz;
void *ptr = (uint8_t *) chunk->ptr + chunk->used;
chunk->used += sz;
*((size_t *) ptr) = sz - sizeof(size_t);
return (uint8_t *) ptr + sizeof(size_t);
}
Expand All @@ -98,6 +99,6 @@ static void arena_free(void *ptr) {

cmark_mem CMARK_ARENA_MEM_ALLOCATOR = {arena_calloc, arena_realloc, arena_free};

cmark_mem *cmark_get_arena_mem_allocator() {
cmark_mem *cmark_get_arena_mem_allocator(void) {
return &CMARK_ARENA_MEM_ALLOCATOR;
}
32 changes: 29 additions & 3 deletions lib/commonmarker/src/blocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <limits.h>

#include "cmark_ctype.h"
#include "syntax_extension.h"
Expand All @@ -26,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 @@ -639,6 +648,14 @@ static cmark_node *finalize_document(cmark_parser *parser) {
}

finalize(parser, parser->root);

// Limit total size of extra content created from reference links to
// document size to avoid superlinear growth. Always allow 100KB.
if (parser->total_size > 100000)
parser->refmap->max_ref_size = parser->total_size;
else
parser->refmap->max_ref_size = 100000;

process_inlines(parser, parser->refmap, parser->options);
if (parser->options & CMARK_OPT_FOOTNOTES)
process_footnotes(parser);
Expand Down Expand Up @@ -698,6 +715,11 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
const unsigned char *end = buffer + len;
static const uint8_t repl[] = {239, 191, 189};

if (len > UINT_MAX - parser->total_size)
parser->total_size = UINT_MAX;
else
parser->total_size += len;

if (parser->last_buffer_ended_with_cr && *buffer == '\n') {
// skip NL if last buffer ended with CR ; see #117
buffer++;
Expand Down Expand Up @@ -1105,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 @@ -1194,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
1 change: 1 addition & 0 deletions lib/commonmarker/src/cmark-gfm-extension_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ typedef struct delimiter {
struct delimiter *previous;
struct delimiter *next;
cmark_node *inl_text;
bufsize_t position;
bufsize_t length;
unsigned char delim_char;
int can_open;
Expand Down
20 changes: 18 additions & 2 deletions lib/commonmarker/src/cmark-gfm.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ typedef struct cmark_mem {
* realloc and free.
*/
CMARK_GFM_EXPORT
cmark_mem *cmark_get_default_mem_allocator();
cmark_mem *cmark_get_default_mem_allocator(void);

/** An arena allocator; uses system calloc to allocate large
* slabs of memory. Memory in these slabs is not reused at all.
*/
CMARK_GFM_EXPORT
cmark_mem *cmark_get_arena_mem_allocator();
cmark_mem *cmark_get_arena_mem_allocator(void);

/** Resets the arena allocator, quickly returning all used memory
* to the operating system.
Expand Down Expand Up @@ -225,6 +225,11 @@ CMARK_GFM_EXPORT cmark_node *cmark_node_first_child(cmark_node *node);
*/
CMARK_GFM_EXPORT cmark_node *cmark_node_last_child(cmark_node *node);

/** Returns the footnote reference of 'node', or NULL if 'node' doesn't have a
* footnote reference.
*/
CMARK_GFM_EXPORT cmark_node *cmark_node_parent_footnote_def(cmark_node *node);

/**
* ## Iterator
*
Expand Down Expand Up @@ -408,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
6 changes: 3 additions & 3 deletions lib/commonmarker/src/cmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
cmark_node_type CMARK_NODE_LAST_BLOCK = CMARK_NODE_FOOTNOTE_DEFINITION;
cmark_node_type CMARK_NODE_LAST_INLINE = CMARK_NODE_FOOTNOTE_REFERENCE;

int cmark_version() { return CMARK_GFM_VERSION; }
int cmark_version(void) { return CMARK_GFM_VERSION; }

const char *cmark_version_string() { return CMARK_GFM_VERSION_STRING; }
const char *cmark_version_string(void) { return CMARK_GFM_VERSION_STRING; }

static void *xcalloc(size_t nmem, size_t size) {
void *ptr = calloc(nmem, size);
Expand All @@ -38,7 +38,7 @@ static void xfree(void *ptr) {

cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR = {xcalloc, xrealloc, xfree};

cmark_mem *cmark_get_default_mem_allocator() {
cmark_mem *cmark_get_default_mem_allocator(void) {
return &CMARK_DEFAULT_MEM_ALLOCATOR;
}

Expand Down
56 changes: 20 additions & 36 deletions lib/commonmarker/src/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 @@ -225,8 +213,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
// this ensures that a following indented code block or list will be
// inteprereted correctly.
CR();
// MBGJ: Do not output html in parser
//LIT("<!-- end list -->");
LIT("<!-- end list -->");
BLANKLINE();
}
break;
Expand All @@ -235,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 @@ -406,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
28 changes: 22 additions & 6 deletions lib/commonmarker/src/html.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,16 @@ static bool S_put_footnote_backref(cmark_html_renderer *renderer, cmark_strbuf *
if (renderer->written_footnote_ix >= renderer->footnote_ix)
return false;
renderer->written_footnote_ix = renderer->footnote_ix;
char m[32];
snprintf(m, sizeof(m), "%d", renderer->written_footnote_ix);

cmark_strbuf_puts(html, "<a href=\"#fnref-");
houdini_escape_href(html, node->as.literal.data, node->as.literal.len);
cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref aria-label=\"Back to content\">↩</a>");
cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"");
cmark_strbuf_puts(html, m);
cmark_strbuf_puts(html, "\" aria-label=\"Back to reference ");
cmark_strbuf_puts(html, m);
cmark_strbuf_puts(html, "\">↩</a>");

if (node->footnote.def_count > 1)
{
Expand All @@ -78,7 +84,15 @@ static bool S_put_footnote_backref(cmark_html_renderer *renderer, cmark_strbuf *
houdini_escape_href(html, node->as.literal.data, node->as.literal.len);
cmark_strbuf_puts(html, "-");
cmark_strbuf_puts(html, n);
cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref aria-label=\"Back to content\">↩<sup class=\"footnote-ref\">");
cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"");
cmark_strbuf_puts(html, m);
cmark_strbuf_puts(html, "-");
cmark_strbuf_puts(html, n);
cmark_strbuf_puts(html, "\" aria-label=\"Back to reference ");
cmark_strbuf_puts(html, m);
cmark_strbuf_puts(html, "-");
cmark_strbuf_puts(html, n);
cmark_strbuf_puts(html, "\">↩<sup class=\"footnote-ref\">");
cmark_strbuf_puts(html, n);
cmark_strbuf_puts(html, "</sup></a>");
}
Expand Down Expand Up @@ -350,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
Loading

0 comments on commit b0b6a3f

Please sign in to comment.