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

Fix sourcepos, add missing extension tests and add sourcepos tests #223

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
937fb16
Add `cmark_strbuf_remove` that removes a subrange of characters.
chriszielinski Apr 26, 2019
0fea1dd
Fix source positions for inlines inside inconsistently indented blocks.
chriszielinski Apr 26, 2019
e523c73
Add three additional source position tests.
chriszielinski Apr 26, 2019
6df4f1f
Fix outdated expected test result.
chriszielinski Apr 26, 2019
891db70
Fix autolink source position.
chriszielinski May 1, 2019
9160d60
Fix expected autolink test fixture, and add an additional autolink so…
chriszielinski May 1, 2019
469031e
Fix source position of setext headings.
chriszielinski May 3, 2019
51cd4f5
Add setext heading test case.
chriszielinski May 3, 2019
4ef6064
Fix source position for ATX-style headings.
chriszielinski May 3, 2019
035c392
Add ATX-style heading source position test case.
chriszielinski May 3, 2019
92444d7
Fix HTMl block source position.
chriszielinski May 6, 2019
2157196
Add HTML block source position test case.
chriszielinski May 6, 2019
79bf93b
Fix thematic break source position.
chriszielinski May 6, 2019
53041c3
Add thematic break source position test case.
chriszielinski May 6, 2019
be7f9c0
Fix ending source position for lists and list items.
chriszielinski May 8, 2019
d2721bf
Add list/list item source position test case.
chriszielinski May 8, 2019
94dba88
Remove commented out code.
chriszielinski May 8, 2019
99621a3
Correct list source position.
chriszielinski May 8, 2019
2570911
Fix source position for HTML blocks without a matching end condition.
chriszielinski May 15, 2019
062d461
Add test case for source position of a HTML block without a matching …
chriszielinski May 15, 2019
a4222f5
Fix line length.
chriszielinski May 15, 2019
538ff21
Fix soourcepos for strikethrough.
martincizek Apr 9, 2020
ce43592
Add test for broken multiline strikethrough. Restore adapted extensio…
martincizek Apr 10, 2020
de09b9c
Add test catching sourcepos bugs related to tables with a paragraph r…
martincizek Apr 10, 2020
27ff048
Fix sourcepos bugs related to table headers with a rejected paragraph.
martincizek Apr 10, 2020
a2792cf
Add sourcepos to softbreak and linebreak nodes if SOURCEPOS requested…
martincizek Apr 11, 2020
80548df
Fix shifted paragraph table offset introduced in ddf21bb.
martincizek May 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add sourcepos to softbreak and linebreak nodes if SOURCEPOS requested…
… on parser.
martincizek committed May 4, 2021
commit a2792cfeff8376fa38319eaaab4046e35b4058bc
77 changes: 44 additions & 33 deletions api_test/main.c
Original file line number Diff line number Diff line change
@@ -1272,13 +1272,14 @@ static void source_pos(test_batch_runner *runner) {
}
{
static const char markdown[] =
"* List 1, item A.\n"
"\n"
" <script>\n"
"- List 2, item A.\n";

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT);
char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS);
"* List 1, item A.\n"
"\n"
" <script>\n"
"- List 2, item A.\n";
int options = CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS;

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, options);
char *xml = cmark_render_xml(doc, options);
STR_EQ(runner, xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n"
"<document sourcepos=\"1:1-4:17\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
@@ -1306,22 +1307,30 @@ static void source_pos(test_batch_runner *runner) {
}

static void source_pos_inlines(test_batch_runner *runner) {
int options = CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS;
{
static const char markdown[] =
"*first*\n"
"second\n";
"second \n"
"third\\\n"
"fourth\n";

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT);
char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS);
cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, options);
char *xml = cmark_render_xml(doc, options);
STR_EQ(runner, xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n"
"<document sourcepos=\"1:1-2:6\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
" <paragraph sourcepos=\"1:1-2:6\">\n"
"<document sourcepos=\"1:1-4:6\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
" <paragraph sourcepos=\"1:1-4:6\">\n"
" <emph sourcepos=\"1:1-1:7\">\n"
" <text sourcepos=\"1:2-1:6\" xml:space=\"preserve\">first</text>\n"
" </emph>\n"
" <softbreak />\n"
" <text sourcepos=\"2:1-2:6\" xml:space=\"preserve\">second</text>\n"
" <softbreak sourcepos=\"1:8-2:0\" />\n"
// two-space hard break considered a part of text - correct?
" <text sourcepos=\"2:1-2:8\" xml:space=\"preserve\">second</text>\n"
" <linebreak sourcepos=\"2:7-3:0\" />\n"
" <text sourcepos=\"3:1-3:5\" xml:space=\"preserve\">third</text>\n"
" <linebreak sourcepos=\"3:6-4:0\" />\n"
" <text sourcepos=\"4:1-4:6\" xml:space=\"preserve\">fourth</text>\n"
" </paragraph>\n"
"</document>\n",
"sourcepos are as expected");
@@ -1333,15 +1342,15 @@ static void source_pos_inlines(test_batch_runner *runner) {
"*first\n"
"second*\n";

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT);
char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS);
cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, options);
char *xml = cmark_render_xml(doc, options);
STR_EQ(runner, xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n"
"<document sourcepos=\"1:1-2:7\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
" <paragraph sourcepos=\"1:1-2:7\">\n"
" <emph sourcepos=\"1:1-2:7\">\n"
" <text sourcepos=\"1:2-1:6\" xml:space=\"preserve\">first</text>\n"
" <softbreak />\n"
" <softbreak sourcepos=\"1:7-2:0\" />\n"
" <text sourcepos=\"2:1-2:6\" xml:space=\"preserve\">second</text>\n"
" </emph>\n"
" </paragraph>\n"
@@ -1356,18 +1365,18 @@ static void source_pos_inlines(test_batch_runner *runner) {
"line\n"
" breaks](https://commonmark.org).";

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT);
char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS);
cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, options);
char *xml = cmark_render_xml(doc, options);
STR_EQ(runner, xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n"
"<document sourcepos=\"1:1-3:33\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
" <paragraph sourcepos=\"1:1-3:33\">\n"
" <text sourcepos=\"1:1-1:24\" xml:space=\"preserve\">This link will have two </text>\n"
" <link sourcepos=\"1:25-3:32\" destination=\"https://commonmark.org\" title=\"\">\n"
" <text sourcepos=\"1:26-1:30\" xml:space=\"preserve\">soft</text>\n"
" <softbreak />\n"
" <softbreak sourcepos=\"1:31-2:0\" />\n"
" <text sourcepos=\"2:1-2:4\" xml:space=\"preserve\">line</text>\n"
" <softbreak />\n"
" <softbreak sourcepos=\"2:5-3:0\" />\n"
" <text sourcepos=\"3:2-3:7\" xml:space=\"preserve\">breaks</text>\n"
" </link>\n"
" <text sourcepos=\"3:33-3:33\" xml:space=\"preserve\">.</text>\n"
@@ -1382,8 +1391,8 @@ static void source_pos_inlines(test_batch_runner *runner) {
" 1. <http://www.google.com>\n"
" <http://www.google.com>\n";

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT);
char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS);
cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, options);
char *xml = cmark_render_xml(doc, options);
STR_EQ(runner, xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n"
"<document sourcepos=\"1:1-2:27\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
@@ -1393,7 +1402,7 @@ static void source_pos_inlines(test_batch_runner *runner) {
" <link sourcepos=\"1:5-1:27\" destination=\"http://www.google.com\" title=\"\">\n"
" <text sourcepos=\"1:6-1:26\" xml:space=\"preserve\">http://www.google.com</text>\n"
" </link>\n"
" <softbreak />\n"
" <softbreak sourcepos=\"1:28-2:0\" />\n"
" <link sourcepos=\"2:5-2:27\" destination=\"http://www.google.com\" title=\"\">\n"
" <text sourcepos=\"2:6-2:26\" xml:space=\"preserve\">http://www.google.com</text>\n"
" </link>\n"
@@ -1411,8 +1420,8 @@ static void source_pos_inlines(test_batch_runner *runner) {
"===============\n"
"A paragraph.\n";

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT);
char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS);
cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, options);
char *xml = cmark_render_xml(doc, options);
STR_EQ(runner, xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n"
"<document sourcepos=\"1:1-3:12\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
@@ -1433,8 +1442,8 @@ static void source_pos_inlines(test_batch_runner *runner) {
"\n"
"> # Header 1 #\n";

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT);
char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS);
cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, options);
char *xml = cmark_render_xml(doc, options);
STR_EQ(runner, xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n"
"<document sourcepos=\"1:1-3:14\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
@@ -1454,13 +1463,15 @@ static void source_pos_inlines(test_batch_runner *runner) {
}

static void ref_source_pos(test_batch_runner *runner) {
int options = CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS;

static const char markdown[] =
"Let's try [reference] links.\n"
"\n"
"[reference]: https://github.com (GitHub)\n";

cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT);
char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS);
cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, options);
char *xml = cmark_render_xml(doc, options);
STR_EQ(runner, xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n"
"<document sourcepos=\"1:1-3:40\" xmlns=\"http://commonmark.org/xml/1.0\">\n"
@@ -1483,6 +1494,7 @@ static void ext_source_pos(test_batch_runner *runner) {
"table",
"autolink",
};
int options = CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS;

static const char markdown[] =
"Hi ~~friend~~ and ~~other\n"
@@ -1494,7 +1506,6 @@ static void ext_source_pos(test_batch_runner *runner) {
" | - | - | --: |\n"
" | 1 | 2 | ~3~ |\n";

int options = CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS;
cmark_parser *parser = cmark_parser_new(options);

for (int i = 0; i < (int)(sizeof(extensions) / sizeof(*extensions)); ++i) {
@@ -1517,7 +1528,7 @@ static void ext_source_pos(test_batch_runner *runner) {
" <text sourcepos=\"1:14-1:18\" xml:space=\"preserve\"> and </text>\n"
" <strikethrough sourcepos=\"1:19-2:8\">\n"
" <text sourcepos=\"1:21-1:25\" xml:space=\"preserve\">other</text>\n"
" <softbreak />\n"
" <softbreak sourcepos=\"1:26-2:0\" />\n"
" <text sourcepos=\"2:1-2:6\" xml:space=\"preserve\">friend</text>\n"
" </strikethrough>\n"
" <text sourcepos=\"2:9-2:9\" xml:space=\"preserve\">.</text>\n"
@@ -1574,14 +1585,14 @@ static void ext_source_pos_corners(test_batch_runner *runner) {
"table",
"autolink",
};
int options = CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS;

// a paragraph inserted by the table extension
static const char markdown[] =
"| paragraph |\n" // +6
"| header |\n" //+3
"| --- |\n";

int options = CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS;
cmark_parser *parser = cmark_parser_new(options);

for (int i = 0; i < (int)(sizeof(extensions) / sizeof(*extensions)); ++i) {
31 changes: 21 additions & 10 deletions src/inlines.c
Original file line number Diff line number Diff line change
@@ -830,11 +830,17 @@ static cmark_node *handle_backslash(cmark_parser *parser, subject *subj) {
advance(subj);
return make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_dup(&subj->input, subj->pos - 1, 1));
} else if (!is_eof(subj) && skip_line_end(subj)) {
cmark_node *res = make_linebreak(subj->mem);

if (parser->options & CMARK_OPT_SOURCEPOS) {
res->start_line = subj->line;
res->start_column = subj->pos - 1 + subj->column_offset + subj->block_offset;
res->end_line = subj->line + 1;
}
// Adjust the subject source position state.
++subj->line;
subj->column_offset = -subj->pos;

return make_linebreak(subj->mem);
return res;
} else {
return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("\\"));
}
@@ -1241,25 +1247,30 @@ static cmark_node *handle_close_bracket(cmark_parser *parser, subject *subj) {

// Parse a hard or soft linebreak, returning an inline.
// Assumes the subject has a cr or newline at the current position.
static cmark_node *handle_newline(subject *subj) {
static cmark_node *handle_newline(subject *subj, int options) {
bufsize_t nlpos = subj->pos;
cmark_node *res;
// skip over cr, crlf, or lf:
if (peek_at(subj, subj->pos) == '\r') {
advance(subj);
}
if (peek_at(subj, subj->pos) == '\n') {
advance(subj);
}
res = nlpos > 1 && peek_at(subj, nlpos - 1) == ' ' && peek_at(subj, nlpos - 2) == ' '
? make_linebreak(subj->mem)
: make_softbreak(subj->mem);
if (options & CMARK_OPT_SOURCEPOS) {
res->start_line = subj->line;
res->start_column = nlpos + subj->column_offset + subj->block_offset;
res->start_column += res->type == CMARK_NODE_LINEBREAK ? -1 : 1;
res->end_line = subj->line + 1;
}
++subj->line;
subj->column_offset = -subj->pos;
// skip spaces at beginning of line
skip_spaces(subj);
if (nlpos > 1 && peek_at(subj, nlpos - 1) == ' ' &&
peek_at(subj, nlpos - 2) == ' ') {
return make_linebreak(subj->mem);
} else {
return make_softbreak(subj->mem);
}
return res;
}

// "\r\n\\`&_*[]<!"
@@ -1360,7 +1371,7 @@ static int parse_inline(cmark_parser *parser, subject *subj, cmark_node *parent,
switch (c) {
case '\r':
case '\n':
new_inl = handle_newline(subj);
new_inl = handle_newline(subj, options);
break;
case '`':
new_inl = handle_backticks(subj, options);