diff options
author | Alex Crichton <alex@alexcrichton.com> | 2017-01-19 16:24:48 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-19 16:24:48 -0800 |
commit | da282f1bb7277b4d30fa1599ee29ad8eb4dd2a92 (patch) | |
tree | 34b6fa5bd72b934e753a3f46d1eaa872f817e377 | |
parent | a3736a0a1907cbc8bf619708738815a5fd789c80 (diff) | |
parent | 78e7b6f69d3fa0cb6ae6e7fb9278c3fd167ec0d1 (diff) | |
download | rust-hoedown-rust-2015-09-21-do-not-delete.tar.gz |
Merge pull request #8 from GuillaumeGomez/line_informationrust-2015-09-21-do-not-delete
Line information
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | src/document.c | 433 | ||||
-rw-r--r-- | src/document.h | 66 | ||||
-rw-r--r-- | src/html.c | 71 | ||||
-rw-r--r-- | src/html_smartypants.c | 2 | ||||
-rw-r--r-- | src/version.h | 4 | ||||
-rw-r--r-- | test/Tests/CommentsInMiddleOfLine.html | 6 | ||||
-rw-r--r-- | test/Tests/CommentsInMiddleOfLine.text | 8 | ||||
-rw-r--r-- | test/Tests/Images.html | 9 | ||||
-rw-r--r-- | test/Tests/Images.text | 11 | ||||
-rw-r--r-- | test/Tests/list.html | 6 | ||||
-rw-r--r-- | test/Tests/list.text | 7 | ||||
-rw-r--r-- | test/config.json | 9 | ||||
-rw-r--r-- | test/line.c | 227 | ||||
-rw-r--r-- | test/line_tests/basic.md | 12 | ||||
-rw-r--r-- | test/line_tests/basic.out | 7 | ||||
-rw-r--r-- | test/line_tests/test.md | 61 | ||||
-rw-r--r-- | test/line_tests/test.out | 41 | ||||
-rwxr-xr-x | test/runner.py | 27 |
20 files changed, 773 insertions, 245 deletions
@@ -8,3 +8,4 @@ hoedown.lib smartypants libhoedown.so* libhoedown.a +test/tester @@ -9,6 +9,11 @@ ifneq ($(OS),Windows_NT) HOEDOWN_CFLAGS += -fPIC endif +SONAME = -soname +ifeq ($(shell uname -s),Darwin) + SONAME = -install_name +endif + HOEDOWN_SRC=\ src/autolink.o \ src/buffer.o \ @@ -30,7 +35,7 @@ libhoedown.so: libhoedown.so.3 ln -f -s $^ $@ libhoedown.so.3: $(HOEDOWN_SRC) - $(CC) -Wl,-soname,$(@F) -shared $^ $(LDFLAGS) -o $@ + $(CC) -Wl,$(SONAME),$(@F) -shared $^ $(LDFLAGS) -o $@ libhoedown.a: $(HOEDOWN_SRC) $(AR) rcs libhoedown.a $^ @@ -50,7 +55,8 @@ src/html_blocks.c: html_block_names.gperf # Testing -test: hoedown +test: hoedown libhoedown.a + $(CC) test/line.c libhoedown.a -o test/tester python test/runner.py test-pl: hoedown diff --git a/src/document.c b/src/document.c index 8cd7315..58b5172 100644 --- a/src/document.c +++ b/src/document.c @@ -64,21 +64,22 @@ struct footnote_list { /* data is the pointer of the beginning of the span */ /* offset is the number of valid chars before data */ typedef size_t -(*char_trigger)(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); - -static size_t char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); -static size_t char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size); +(*char_trigger)(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); + +static size_t char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_image(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); +static size_t char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line); enum markdown_char_t { MD_CHAR_NONE = 0, @@ -86,6 +87,7 @@ enum markdown_char_t { MD_CHAR_CODESPAN, MD_CHAR_LINEBREAK, MD_CHAR_LINK, + MD_CHAR_IMAGE, MD_CHAR_LANGLE, MD_CHAR_ESCAPE, MD_CHAR_ENTITY, @@ -103,6 +105,7 @@ static char_trigger markdown_char_ptrs[] = { &char_codespan, &char_linebreak, &char_link, + &char_image, &char_langle_tag, &char_escape, &char_entity, @@ -402,9 +405,23 @@ tag_length(uint8_t *data, size_t size, hoedown_autolink_type *autolink) /* a valid tag can't be shorter than 3 chars */ if (size < 3) return 0; - /* begins with a '<' optionally followed by '/', followed by letter or number */ if (data[0] != '<') return 0; - i = (data[1] == '/') ? 2 : 1; + + /* HTML comment, laxist form */ + if (size > 5 && data[1] == '!' && data[2] == '-' && data[3] == '-') { + i = 5; + + while (i < size && !(data[i - 2] == '-' && data[i - 1] == '-' && data[i] == '>')) + i++; + + i++; + + if (i <= size) + return i; + } + + /* begins with a '<' optionally followed by '/', followed by letter or number */ + i = (data[1] == '/') ? 2 : 1; if (!isalnum(data[i])) return 0; @@ -457,7 +474,7 @@ tag_length(uint8_t *data, size_t size, hoedown_autolink_type *autolink) /* parse_inline • parses inline markdown elements */ static void -parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size) +parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, size_t line) { size_t i = 0, end = 0, consumed = 0; hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL }; @@ -475,7 +492,7 @@ parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t si if (doc->md.normal_text) { work.data = data + i; work.size = end - i; - doc->md.normal_text(ob, &work, &doc->data); + doc->md.normal_text(ob, &work, &doc->data, line); } else hoedown_buffer_put(ob, data + i, end - i); @@ -483,7 +500,7 @@ parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t si if (end >= size) break; i = end; - end = markdown_char_ptrs[ (int)active_char[data[end]] ](ob, doc, data + i, i - consumed, size - i); + end = markdown_char_ptrs[ (int)active_char[data[end]] ](ob, doc, data + i, i - consumed, size - i, line); if (!end) /* no action from the callback */ end = i + 1; else { @@ -602,7 +619,7 @@ find_emph_char(uint8_t *data, size_t size, uint8_t c) /* parse_emph1 • parsing single emphase */ /* closed by a symbol not preceded by spacing and not followed by symbol */ static size_t -parse_emph1(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c) +parse_emph1(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c, size_t line) { size_t i = 0, len; hoedown_buffer *work = 0; @@ -625,12 +642,12 @@ parse_emph1(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz } work = newbuf(doc, BUFFER_SPAN); - parse_inline(work, doc, data, i); + parse_inline(work, doc, data, i, line); if (doc->ext_flags & HOEDOWN_EXT_UNDERLINE && c == '_') - r = doc->md.underline(ob, work, &doc->data); + r = doc->md.underline(ob, work, &doc->data, line); else - r = doc->md.emphasis(ob, work, &doc->data); + r = doc->md.emphasis(ob, work, &doc->data, line); popbuf(doc, BUFFER_SPAN); return r ? i + 1 : 0; @@ -642,7 +659,7 @@ parse_emph1(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz /* parse_emph2 • parsing single emphase */ static size_t -parse_emph2(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c) +parse_emph2(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c, size_t line) { size_t i = 0, len; hoedown_buffer *work = 0; @@ -655,14 +672,14 @@ parse_emph2(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !_isspace(data[i - 1])) { work = newbuf(doc, BUFFER_SPAN); - parse_inline(work, doc, data, i); + parse_inline(work, doc, data, i, line); if (c == '~') - r = doc->md.strikethrough(ob, work, &doc->data); + r = doc->md.strikethrough(ob, work, &doc->data, line); else if (c == '=') - r = doc->md.highlight(ob, work, &doc->data); + r = doc->md.highlight(ob, work, &doc->data, line); else - r = doc->md.double_emphasis(ob, work, &doc->data); + r = doc->md.double_emphasis(ob, work, &doc->data, line); popbuf(doc, BUFFER_SPAN); return r ? i + 2 : 0; @@ -675,7 +692,7 @@ parse_emph2(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz /* parse_emph3 • parsing single emphase */ /* finds the first closing tag, and delegates to the other emph */ static size_t -parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c) +parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, uint8_t c, size_t line) { size_t i = 0, len; int r; @@ -693,20 +710,20 @@ parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz /* triple symbol found */ hoedown_buffer *work = newbuf(doc, BUFFER_SPAN); - parse_inline(work, doc, data, i); - r = doc->md.triple_emphasis(ob, work, &doc->data); + parse_inline(work, doc, data, i, line); + r = doc->md.triple_emphasis(ob, work, &doc->data, line); popbuf(doc, BUFFER_SPAN); return r ? i + 3 : 0; } else if (i + 1 < size && data[i + 1] == c) { /* double symbol found, handing over to emph1 */ - len = parse_emph1(ob, doc, data - 2, size + 2, c); + len = parse_emph1(ob, doc, data - 2, size + 2, c, line); if (!len) return 0; else return len - 2; } else { /* single symbol found, handing over to emph2 */ - len = parse_emph2(ob, doc, data - 1, size + 1, c); + len = parse_emph2(ob, doc, data - 1, size + 1, c, line); if (!len) return 0; else return len - 1; } @@ -716,7 +733,7 @@ parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz /* parse_math • parses a math span until the given ending delimiter */ static size_t -parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, const char *end, size_t delimsz, int displaymode) +parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, const char *end, size_t delimsz, int displaymode, size_t line) { hoedown_buffer text = { NULL, 0, 0, 0, NULL, NULL, NULL }; size_t i = delimsz; @@ -750,7 +767,7 @@ parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs displaymode = is_empty_all(data - offset, offset) && is_empty_all(data + i, size - i); /* call callback */ - if (doc->md.math(ob, &text, displaymode, &doc->data)) + if (doc->md.math(ob, &text, displaymode, &doc->data, line)) return i; return 0; @@ -758,7 +775,7 @@ parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs /* char_emphasis • single and double emphasis parsing */ static size_t -char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { uint8_t c = data[0]; size_t ret; @@ -771,21 +788,21 @@ char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t o if (size > 2 && data[1] != c) { /* spacing cannot follow an opening emphasis; * strikethrough and highlight only takes two characters '~~' */ - if (c == '~' || c == '=' || _isspace(data[1]) || (ret = parse_emph1(ob, doc, data + 1, size - 1, c)) == 0) + if (c == '~' || c == '=' || _isspace(data[1]) || (ret = parse_emph1(ob, doc, data + 1, size - 1, c, line)) == 0) return 0; return ret + 1; } if (size > 3 && data[1] == c && data[2] != c) { - if (_isspace(data[2]) || (ret = parse_emph2(ob, doc, data + 2, size - 2, c)) == 0) + if (_isspace(data[2]) || (ret = parse_emph2(ob, doc, data + 2, size - 2, c, line)) == 0) return 0; return ret + 2; } if (size > 4 && data[1] == c && data[2] == c && data[3] != c) { - if (c == '~' || c == '=' || _isspace(data[3]) || (ret = parse_emph3(ob, doc, data + 3, size - 3, c)) == 0) + if (c == '~' || c == '=' || _isspace(data[3]) || (ret = parse_emph3(ob, doc, data + 3, size - 3, c, line)) == 0) return 0; return ret + 3; @@ -797,7 +814,7 @@ char_emphasis(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t o /* char_linebreak • '\n' preceded by two spaces (assuming linebreak != 0) */ static size_t -char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { if (offset < 2 || data[-1] != ' ' || data[-2] != ' ') return 0; @@ -806,13 +823,13 @@ char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t while (ob->size && ob->data[ob->size - 1] == ' ') ob->size--; - return doc->md.linebreak(ob, &doc->data) ? 1 : 0; + return doc->md.linebreak(ob, &doc->data, line) ? 1 : 0; } /* char_codespan • '`' parsing a code span (assuming codespan != 0) */ static size_t -char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL }; size_t end, nb = 0, i, f_begin, f_end; @@ -845,10 +862,10 @@ char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t o work.data = data + f_begin; work.size = f_end - f_begin; - if (!doc->md.codespan(ob, &work, &doc->data)) + if (!doc->md.codespan(ob, &work, &doc->data, line)) end = 0; } else { - if (!doc->md.codespan(ob, 0, &doc->data)) + if (!doc->md.codespan(ob, 0, &doc->data, line)) end = 0; } @@ -857,7 +874,7 @@ char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t o /* char_quote • '"' parsing a quote */ static size_t -char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { size_t end, nq = 0, i, f_begin, f_end; @@ -888,13 +905,13 @@ char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs /* real quote */ if (f_begin < f_end) { hoedown_buffer *work = newbuf(doc, BUFFER_SPAN); - parse_inline(work, doc, data + f_begin, f_end - f_begin); + parse_inline(work, doc, data + f_begin, f_end - f_begin, line); - if (!doc->md.quote(ob, work, &doc->data)) + if (!doc->md.quote(ob, work, &doc->data, line)) end = 0; popbuf(doc, BUFFER_SPAN); } else { - if (!doc->md.quote(ob, 0, &doc->data)) + if (!doc->md.quote(ob, 0, &doc->data, line)) end = 0; } @@ -904,7 +921,7 @@ char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs /* char_escape • '\\' backslash escape */ static size_t -char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~=\"$"; hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL }; @@ -914,7 +931,7 @@ char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off if (data[1] == '\\' && (doc->ext_flags & HOEDOWN_EXT_MATH) && size > 2 && (data[2] == '(' || data[2] == '[')) { const char *end = (data[2] == '[') ? "\\\\]" : "\\\\)"; - w = parse_math(ob, doc, data, offset, size, end, 3, data[2] == '['); + w = parse_math(ob, doc, data, offset, size, end, 3, data[2] == '[', line); if (w) return w; } @@ -924,11 +941,16 @@ char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off if (doc->md.normal_text) { work.data = data + 1; work.size = 1; - doc->md.normal_text(ob, &work, &doc->data); + doc->md.normal_text(ob, &work, &doc->data, line); } else hoedown_buffer_putc(ob, data[1]); } else if (size == 1) { - hoedown_buffer_putc(ob, data[0]); + if (doc->md.normal_text) { + work.data = data; + work.size = 1; + doc->md.normal_text(ob, &work, &doc->data, line); + } + else hoedown_buffer_putc(ob, data[0]); } return 2; @@ -937,7 +959,7 @@ char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off /* char_entity • '&' escaped when it doesn't belong to an entity */ /* valid entities are assumed to be anything matching &#?[A-Za-z0-9]+; */ static size_t -char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { size_t end = 1; hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL }; @@ -956,7 +978,7 @@ char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off if (doc->md.entity) { work.data = data; work.size = end; - doc->md.entity(ob, &work, &doc->data); + doc->md.entity(ob, &work, &doc->data, line); } else hoedown_buffer_put(ob, data, end); @@ -965,7 +987,7 @@ char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off /* char_langle_tag • '<' when tags or autolinks are allowed */ static size_t -char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL }; hoedown_autolink_type altype = HOEDOWN_AUTOLINK_NONE; @@ -981,11 +1003,11 @@ char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t work.data = data + 1; work.size = end - 2; unscape_text(u_link, &work); - ret = doc->md.autolink(ob, u_link, altype, &doc->data); + ret = doc->md.autolink(ob, u_link, altype, &doc->data, line); popbuf(doc, BUFFER_SPAN); } else if (doc->md.raw_html) - ret = doc->md.raw_html(ob, &work, &doc->data); + ret = doc->md.raw_html(ob, &work, &doc->data, line); } if (!ret) return 0; @@ -993,7 +1015,7 @@ char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t } static size_t -char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { hoedown_buffer *link, *link_url, *link_text; size_t link_len, rewind; @@ -1015,11 +1037,11 @@ char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size if (doc->md.normal_text) { link_text = newbuf(doc, BUFFER_SPAN); - doc->md.normal_text(link_text, link, &doc->data); - doc->md.link(ob, link_text, link_url, NULL, &doc->data); + doc->md.normal_text(link_text, link, &doc->data, line); + doc->md.link(ob, link_text, link_url, NULL, &doc->data, line); popbuf(doc, BUFFER_SPAN); } else { - doc->md.link(ob, link, link_url, NULL, &doc->data); + doc->md.link(ob, link, link_url, NULL, &doc->data, line); } popbuf(doc, BUFFER_SPAN); } @@ -1029,7 +1051,7 @@ char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size } static size_t -char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { hoedown_buffer *link; size_t link_len, rewind; @@ -1045,7 +1067,7 @@ char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, si else ob->size = 0; - doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_EMAIL, &doc->data); + doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_EMAIL, &doc->data, line); } popbuf(doc, BUFFER_SPAN); @@ -1053,7 +1075,7 @@ char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, si } static size_t -char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { hoedown_buffer *link; size_t link_len, rewind; @@ -1069,16 +1091,27 @@ char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size else ob->size = 0; - doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_NORMAL, &doc->data); + doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_NORMAL, &doc->data, line); } popbuf(doc, BUFFER_SPAN); return link_len; } +static size_t +char_image(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { + size_t ret; + + if (size < 2 || data[1] != '[') return 0; + + ret = char_link(ob, doc, data + 1, offset + 1, size - 1, line); + if (!ret) return 0; + return ret + 1; +} + /* char_link • '[': parsing a link, a footnote or an image */ static size_t -char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { int is_img = (offset && data[-1] == '!' && !is_escaped(data - offset, offset - 1)); int is_footnote = (doc->ext_flags & HOEDOWN_EXT_FOOTNOTES && data[1] == '^'); @@ -1124,7 +1157,7 @@ char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offse /* render */ if (doc->md.footnote_ref) - ret = doc->md.footnote_ref(ob, fr->num, &doc->data); + ret = doc->md.footnote_ref(ob, fr->num, &doc->data, line); } goto cleanup; @@ -1199,8 +1232,10 @@ char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offse link_e--; /* remove optional angle brackets around the link */ - if (data[link_b] == '<') link_b++; - if (data[link_e - 1] == '>') link_e--; + if (data[link_b] == '<' && data[link_e - 1] == '>') { + link_b++; + link_e--; + } /* building escaped link and title */ if (link_e > link_b) { @@ -1274,7 +1309,7 @@ char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offse /* disable autolinking when parsing inline the * content of a link */ doc->in_link_body = 1; - parse_inline(content, doc, data + 1, txt_e - 1); + parse_inline(content, doc, data + 1, txt_e - 1, line); doc->in_link_body = 0; } } @@ -1286,12 +1321,9 @@ char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offse /* calling the relevant rendering function */ if (is_img) { - if (ob->size && ob->data[ob->size - 1] == '!') - ob->size -= 1; - - ret = doc->md.image(ob, u_link, title, content, &doc->data); + ret = doc->md.image(ob, u_link, title, content, &doc->data, line); } else { - ret = doc->md.link(ob, content, u_link, title, &doc->data); + ret = doc->md.link(ob, content, u_link, title, &doc->data, line); } /* cleanup */ @@ -1301,7 +1333,7 @@ cleanup: } static size_t -char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { size_t sup_start, sup_len; hoedown_buffer *sup; @@ -1329,23 +1361,23 @@ char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_ return (sup_start == 2) ? 3 : 0; sup = newbuf(doc, BUFFER_SPAN); - parse_inline(sup, doc, data + sup_start, sup_len - sup_start); - doc->md.superscript(ob, sup, &doc->data); + parse_inline(sup, doc, data + sup_start, sup_len - sup_start, line); + doc->md.superscript(ob, sup, &doc->data, line); popbuf(doc, BUFFER_SPAN); return (sup_start == 2) ? sup_len + 1 : sup_len; } static size_t -char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) +char_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size, size_t line) { /* double dollar */ if (size > 1 && data[1] == '$') - return parse_math(ob, doc, data, offset, size, "$$", 2, 1); + return parse_math(ob, doc, data, offset, size, "$$", 2, 1, line); /* single dollar allowed only with MATH_EXPLICIT flag */ if (doc->ext_flags & HOEDOWN_EXT_MATH_EXPLICIT) - return parse_math(ob, doc, data, offset, size, "$", 1, 0); + return parse_math(ob, doc, data, offset, size, "$", 1, 0, line); return 0; } @@ -1594,22 +1626,26 @@ prefix_uli(uint8_t *data, size_t size) /* parse_block • parsing of one block, returning next uint8_t to parse */ static void parse_block(hoedown_buffer *ob, hoedown_document *doc, - uint8_t *data, size_t size); + uint8_t *data, size_t size, size_t *line); /* parse_blockquote • handles parsing of a blockquote fragment */ static size_t -parse_blockquote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size) +parse_blockquote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, size_t *line) { size_t beg, end = 0, pre, work_size = 0; uint8_t *work_data = 0; hoedown_buffer *out = 0; + size_t lines_to_add = *line; + size_t start_line = *line; out = newbuf(doc, BUFFER_BLOCK); beg = 0; while (beg < size) { for (end = beg + 1; end < size && data[end - 1] != '\n'; end++); + lines_to_add += data[end - 1] == '\n'; + pre = prefix_quote(data + beg, end - beg); if (pre) @@ -1632,19 +1668,20 @@ parse_blockquote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_ beg = end; } - parse_block(out, doc, work_data, work_size); + *line = lines_to_add; + parse_block(out, doc, work_data, work_size, &lines_to_add); if (doc->md.blockquote) - doc->md.blockquote(ob, out, &doc->data); + doc->md.blockquote(ob, out, &doc->data, start_line); popbuf(doc, BUFFER_BLOCK); return end; } static size_t -parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int do_render); +parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int do_render, size_t *line); /* parse_blockquote • handles parsing of a regular paragraph */ static size_t -parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size) +parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, size_t *line) { hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL }; size_t i = 0, end = 0; @@ -1677,9 +1714,9 @@ parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t if (!level) { hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK); - parse_inline(tmp, doc, work.data, work.size); + parse_inline(tmp, doc, work.data, work.size, *line); if (doc->md.paragraph) - doc->md.paragraph(ob, tmp, &doc->data); + doc->md.paragraph(ob, tmp, &doc->data, *line); popbuf(doc, BUFFER_BLOCK); } else { hoedown_buffer *header_work; @@ -1698,10 +1735,10 @@ parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t if (work.size > 0) { hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK); - parse_inline(tmp, doc, work.data, work.size); + parse_inline(tmp, doc, work.data, work.size, *line); if (doc->md.paragraph) - doc->md.paragraph(ob, tmp, &doc->data); + doc->md.paragraph(ob, tmp, &doc->data, *line); popbuf(doc, BUFFER_BLOCK); work.data += beg; @@ -1711,20 +1748,22 @@ parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t } header_work = newbuf(doc, BUFFER_SPAN); - parse_inline(header_work, doc, work.data, work.size); + parse_inline(header_work, doc, work.data, work.size, *line); if (doc->md.header) - doc->md.header(ob, header_work, (int)level, &doc->data); + doc->md.header(ob, header_work, (int)level, &doc->data, *line); popbuf(doc, BUFFER_SPAN); } + for (i = 0; i < end; ++i) + *line += data[i] == '\n'; return end; } /* parse_fencedcode • handles parsing of a block-level code fragment */ static size_t -parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size) +parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, size_t *line) { hoedown_buffer text = { 0, 0, 0, 0, NULL, NULL, NULL }; hoedown_buffer lang = { 0, 0, 0, 0, NULL, NULL, NULL }; @@ -1732,10 +1771,12 @@ parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_ size_t w, w2; size_t width, width2; uint8_t chr, chr2; + size_t lines_to_add = 0; /* parse codefence line */ while (i < size && data[i] != '\n') i++; + lines_to_add += data[i] == '\n'; w = parse_codefence(data, i, &lang, &width, &chr); if (!w) @@ -1747,6 +1788,7 @@ parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_ while ((line_start = i) < size) { while (i < size && data[i] != '\n') i++; + lines_to_add += data[i] == '\n'; w2 = is_codefence(data + line_start, i - line_start, &width2, &chr2); if (w == w2 && width == width2 && chr == chr2 && @@ -1760,15 +1802,16 @@ parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_ text.size = line_start - text_start; if (doc->md.blockcode) - doc->md.blockcode(ob, text.size ? &text : NULL, lang.size ? &lang : NULL, &doc->data); + doc->md.blockcode(ob, text.size ? &text : NULL, lang.size ? &lang : NULL, &doc->data, *line); + *line += lines_to_add; return i; } static size_t -parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size) +parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, size_t *line) { - size_t beg, end, pre; + size_t beg, end, pre, lines_to_add = *line; hoedown_buffer *work = 0; work = newbuf(doc, BUFFER_BLOCK); @@ -1783,6 +1826,7 @@ parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t else if (!is_empty(data + beg, end - beg)) /* non-empty non-prefixed line breaks the pre */ break; + lines_to_add += data[end - 1] == '\n'; if (beg < end) { /* verbatim copy to the working buffer, @@ -1800,8 +1844,9 @@ parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t hoedown_buffer_putc(work, '\n'); if (doc->md.blockcode) - doc->md.blockcode(ob, work, NULL, &doc->data); + doc->md.blockcode(ob, work, NULL, &doc->data, *line); + *line = lines_to_add; popbuf(doc, BUFFER_BLOCK); return beg; } @@ -1809,11 +1854,12 @@ parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* parse_listitem • parsing of a single list item */ /* assuming initial prefix is already removed */ static size_t -parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags *flags) +parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags *flags, size_t *line) { hoedown_buffer *work = 0, *inter = 0; size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; int in_empty = 0, has_inside_empty = 0, in_fence = 0; + size_t lines_to_add = *line; /* keeping track of the first indentation prefix */ while (orgpre < 3 && orgpre < size && data[orgpre] == ' ') @@ -1847,6 +1893,7 @@ parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t while (end < size && data[end - 1] != '\n') end++; + lines_to_add += data[end - 1] == '\n'; /* process an empty line */ if (is_empty(data + beg, end - beg)) { @@ -1917,27 +1964,30 @@ parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t *flags |= HOEDOWN_LI_BLOCK; if (*flags & HOEDOWN_LI_BLOCK) { + size_t tmp_line = *line; /* intermediate render of block li */ if (sublist && sublist < work->size) { - parse_block(inter, doc, work->data, sublist); - parse_block(inter, doc, work->data + sublist, work->size - sublist); + parse_block(inter, doc, work->data, sublist, &tmp_line); + parse_block(inter, doc, work->data + sublist, work->size - sublist, &tmp_line); } else - parse_block(inter, doc, work->data, work->size); + parse_block(inter, doc, work->data, work->size, &tmp_line); } else { /* intermediate render of inline li */ if (sublist && sublist < work->size) { - parse_inline(inter, doc, work->data, sublist); - parse_block(inter, doc, work->data + sublist, work->size - sublist); + size_t tmp_line = *line; + parse_inline(inter, doc, work->data, sublist, *line); + parse_block(inter, doc, work->data + sublist, work->size - sublist, &tmp_line); } else - parse_inline(inter, doc, work->data, work->size); + parse_inline(inter, doc, work->data, work->size, *line); } /* render of li itself */ if (doc->md.listitem) - doc->md.listitem(ob, inter, *flags, &doc->data); + doc->md.listitem(ob, inter, *flags, &doc->data, *line); + *line = lines_to_add; popbuf(doc, BUFFER_SPAN); popbuf(doc, BUFFER_SPAN); return beg; @@ -1946,30 +1996,31 @@ parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* parse_list • parsing ordered or unordered list block */ static size_t -parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags flags) +parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, hoedown_list_flags flags, size_t *line) { hoedown_buffer *work = 0; size_t i = 0, j; + size_t new_lines = *line; work = newbuf(doc, BUFFER_BLOCK); while (i < size) { - j = parse_listitem(work, doc, data + i, size - i, &flags); + j = parse_listitem(work, doc, data + i, size - i, &flags, &new_lines); i += j; - if (!j || (flags & HOEDOWN_LI_END)) break; } if (doc->md.list) - doc->md.list(ob, work, flags, &doc->data); + doc->md.list(ob, work, flags, &doc->data, *line); + *line = new_lines; popbuf(doc, BUFFER_BLOCK); return i; } /* parse_atxheader • parsing of atx-style headers */ static size_t -parse_atxheader(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size) +parse_atxheader(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, size_t *line) { size_t level = 0; size_t i, end, skip; @@ -1991,10 +2042,10 @@ parse_atxheader(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t if (end > i) { hoedown_buffer *work = newbuf(doc, BUFFER_SPAN); - parse_inline(work, doc, data + i, end - i); + parse_inline(work, doc, data + i, end - i, *line); if (doc->md.header) - doc->md.header(ob, work, (int)level, &doc->data); + doc->md.header(ob, work, (int)level, &doc->data, *line); popbuf(doc, BUFFER_SPAN); } @@ -2004,25 +2055,28 @@ parse_atxheader(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* parse_footnote_def • parse a single footnote definition */ static void -parse_footnote_def(hoedown_buffer *ob, hoedown_document *doc, unsigned int num, uint8_t *data, size_t size) +parse_footnote_def(hoedown_buffer *ob, hoedown_document *doc, unsigned int num, uint8_t *data, size_t size, size_t *line) { hoedown_buffer *work = 0; + size_t save_line = *line; work = newbuf(doc, BUFFER_SPAN); - parse_block(work, doc, data, size); + parse_block(work, doc, data, size, &save_line); if (doc->md.footnote_def) - doc->md.footnote_def(ob, work, num, &doc->data); + doc->md.footnote_def(ob, work, num, &doc->data, *line); + *line = save_line; popbuf(doc, BUFFER_SPAN); } /* parse_footnote_list • render the contents of the footnotes */ static void -parse_footnote_list(hoedown_buffer *ob, hoedown_document *doc, struct footnote_list *footnotes) +parse_footnote_list(hoedown_buffer *ob, hoedown_document *doc, struct footnote_list *footnotes, size_t *line) { hoedown_buffer *work = 0; struct footnote_item *item; struct footnote_ref *ref; + size_t save_line = *line; if (footnotes->count == 0) return; @@ -2032,12 +2086,13 @@ parse_footnote_list(hoedown_buffer *ob, hoedown_document *doc, struct footnote_l item = footnotes->head; while (item) { ref = item->ref; - parse_footnote_def(work, doc, ref->num, ref->contents->data, ref->contents->size); + parse_footnote_def(work, doc, ref->num, ref->contents->data, ref->contents->size, &save_line); item = item->next; } if (doc->md.footnotes) - doc->md.footnotes(ob, work, &doc->data); + doc->md.footnotes(ob, work, &doc->data, *line); + *line = save_line; popbuf(doc, BUFFER_BLOCK); } @@ -2077,13 +2132,18 @@ htmlblock_find_end( size_t tag_len, hoedown_document *doc, uint8_t *data, - size_t size) + size_t size, + size_t *line) { size_t i = 0, w; + size_t original_line = *line; while (1) { - while (i < size && data[i] != '<') i++; - if (i >= size) return 0; + while (i < size && data[i] != '<') *line += data[i++] == '\n'; + if (i >= size) { + *line = original_line; + return 0; + } w = htmlblock_is_end(tag, tag_len, doc, data + i, size - i); if (w) return i + w; @@ -2100,18 +2160,19 @@ htmlblock_find_end_strict( size_t tag_len, hoedown_document *doc, uint8_t *data, - size_t size) + size_t size, + size_t *line) { size_t i = 0, mark; while (1) { mark = i; while (i < size && data[i] != '\n') i++; - if (i < size) i++; + if (i < size) { i++; *line += 1; } if (i == mark) return 0; if (data[mark] == ' ' && mark > 0) continue; - mark += htmlblock_find_end(tag, tag_len, doc, data + mark, i - mark); + mark += htmlblock_find_end(tag, tag_len, doc, data + mark, i - mark, line); if (mark == i && (is_empty(data + i, size - i) || i >= size)) break; } @@ -2120,11 +2181,12 @@ htmlblock_find_end_strict( /* parse_htmlblock • parsing of inline HTML block */ static size_t -parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int do_render) +parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, int do_render, size_t *line) { hoedown_buffer work = { NULL, 0, 0, 0, NULL, NULL, NULL }; size_t i, j = 0, tag_len, tag_end; const char *curtag = NULL; + size_t tmp_line = *line; work.data = data; @@ -2134,7 +2196,7 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t i = 1; while (i < size && data[i] != '>' && data[i] != ' ') - i++; + tmp_line += data[i++] == '\n'; if (i < size) curtag = hoedown_find_block_tag((char *)data + 1, (int)i - 1); @@ -2157,7 +2219,7 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t if (j) { work.size = i + j; if (do_render && doc->md.blockhtml) - doc->md.blockhtml(ob, &work, &doc->data); + doc->md.blockhtml(ob, &work, &doc->data, *line); return work.size; } } @@ -2166,7 +2228,7 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t if (size > 4 && (data[1] == 'h' || data[1] == 'H') && (data[2] == 'r' || data[2] == 'R')) { i = 3; while (i < size && data[i] != '>') - i++; + tmp_line += data[i++] == '\n'; if (i + 1 < size) { i++; @@ -2174,7 +2236,7 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t if (j) { work.size = i + j; if (do_render && doc->md.blockhtml) - doc->md.blockhtml(ob, &work, &doc->data); + doc->md.blockhtml(ob, &work, &doc->data, *line); return work.size; } } @@ -2186,12 +2248,13 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* looking for a matching closing tag in strict mode */ tag_len = strlen(curtag); - tag_end = htmlblock_find_end_strict(curtag, tag_len, doc, data, size); + tag_end = htmlblock_find_end_strict(curtag, tag_len, doc, data, size, &tmp_line); /* if not found, trying a second pass looking for indented match */ /* but not if tag is "ins" or "del" (following original Markdown.pl) */ - if (!tag_end && strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0) - tag_end = htmlblock_find_end(curtag, tag_len, doc, data, size); + if (!tag_end && strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0) { + tag_end = htmlblock_find_end(curtag, tag_len, doc, data, size, &tmp_line); + } if (!tag_end) return 0; @@ -2199,7 +2262,8 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t /* the end of the block has been found */ work.size = tag_end; if (do_render && doc->md.blockhtml) - doc->md.blockhtml(ob, &work, &doc->data); + doc->md.blockhtml(ob, &work, &doc->data, *line); + *line = tmp_line; return tag_end; } @@ -2210,6 +2274,7 @@ parse_table_row( hoedown_document *doc, uint8_t *data, size_t size, + size_t line, size_t columns, hoedown_table_flags *col_data, hoedown_table_flags header_flag) @@ -2252,8 +2317,8 @@ parse_table_row( while (cell_end > cell_start && _isspace(data[cell_end])) cell_end--; - parse_inline(cell_work, doc, data + cell_start, 1 + cell_end - cell_start); - doc->md.table_cell(row_work, cell_work, col_data[col] | header_flag, &doc->data); + parse_inline(cell_work, doc, data + cell_start, 1 + cell_end - cell_start, line); + doc->md.table_cell(row_work, cell_work, col_data[col] | header_flag, &doc->data, line); popbuf(doc, BUFFER_SPAN); i++; @@ -2261,10 +2326,10 @@ parse_table_row( for (; col < columns; ++col) { hoedown_buffer empty_cell = { 0, 0, 0, 0, NULL, NULL, NULL }; - doc->md.table_cell(row_work, &empty_cell, col_data[col] | header_flag, &doc->data); + doc->md.table_cell(row_work, &empty_cell, col_data[col] | header_flag, &doc->data, line); } - doc->md.table_row(ob, row_work, &doc->data); + doc->md.table_row(ob, row_work, &doc->data, line); popbuf(doc, BUFFER_SPAN); } @@ -2275,6 +2340,7 @@ parse_table_header( hoedown_document *doc, uint8_t *data, size_t size, + size_t *line, size_t *columns, hoedown_table_flags **column_data) { @@ -2353,6 +2419,7 @@ parse_table_header( parse_table_row( ob, doc, data, header_end, + *line, *columns, *column_data, HOEDOWN_TABLE_HEADER @@ -2366,7 +2433,8 @@ parse_table( hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, - size_t size) + size_t size, + size_t *line) { size_t i; @@ -2376,12 +2444,14 @@ parse_table( size_t columns; hoedown_table_flags *col_data = NULL; + size_t lines_to_add = 0; work = newbuf(doc, BUFFER_BLOCK); header_work = newbuf(doc, BUFFER_SPAN); body_work = newbuf(doc, BUFFER_BLOCK); - i = parse_table_header(header_work, doc, data, size, &columns, &col_data); + + i = parse_table_header(header_work, doc, data, size, line, &columns, &col_data); if (i > 0) { while (i < size) { @@ -2404,23 +2474,27 @@ parse_table( doc, data + row_start, i - row_start, + *line + lines_to_add, columns, col_data, 0 ); i++; + lines_to_add += 1; } - if (doc->md.table_header) - doc->md.table_header(work, header_work, &doc->data); + if (doc->md.table_header) + doc->md.table_header(work, header_work, &doc->data, *line); - if (doc->md.table_body) - doc->md.table_body(work, body_work, &doc->data); + if (doc->md.table_body) + doc->md.table_body(work, body_work, &doc->data, *line); if (doc->md.table) - doc->md.table(ob, work, &doc->data); + doc->md.table(ob, work, &doc->data, *line); } + *line += lines_to_add; + free(col_data); popbuf(doc, BUFFER_SPAN); popbuf(doc, BUFFER_BLOCK); @@ -2430,7 +2504,7 @@ parse_table( /* parse_block • parsing of one block, returning next uint8_t to parse */ static void -parse_block(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size) +parse_block(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size, size_t *line) { size_t beg, end, i; uint8_t *txt_data; @@ -2444,48 +2518,60 @@ parse_block(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz txt_data = data + beg; end = size - beg; - if (is_atxheader(doc, txt_data, end)) - beg += parse_atxheader(ob, doc, txt_data, end); + if (is_atxheader(doc, txt_data, end)) { + beg += parse_atxheader(ob, doc, txt_data, end, line); + } else if (data[beg] == '<' && doc->md.blockhtml && - (i = parse_htmlblock(ob, doc, txt_data, end, 1)) != 0) + (i = parse_htmlblock(ob, doc, txt_data, end, 1, line)) != 0) { beg += i; + } - else if ((i = is_empty(txt_data, end)) != 0) - beg += i; + else if ((i = is_empty(txt_data, end)) != 0) { + while (i-- > 0) { + *line += data[beg++] == '\n'; + } + } else if (is_hrule(txt_data, end)) { if (doc->md.hrule) - doc->md.hrule(ob, &doc->data); + doc->md.hrule(ob, &doc->data, beg); while (beg < size && data[beg] != '\n') beg++; - + *line += 1; beg++; } else if ((doc->ext_flags & HOEDOWN_EXT_FENCED_CODE) != 0 && - (i = parse_fencedcode(ob, doc, txt_data, end)) != 0) + (i = parse_fencedcode(ob, doc, txt_data, end, line)) != 0) { beg += i; + } else if ((doc->ext_flags & HOEDOWN_EXT_TABLES) != 0 && - (i = parse_table(ob, doc, txt_data, end)) != 0) + (i = parse_table(ob, doc, txt_data, end, line)) != 0) { beg += i; + } - else if (prefix_quote(txt_data, end)) - beg += parse_blockquote(ob, doc, txt_data, end); + else if (prefix_quote(txt_data, end)) { + beg += parse_blockquote(ob, doc, txt_data, end, line); + } - else if (!(doc->ext_flags & HOEDOWN_EXT_DISABLE_INDENTED_CODE) && prefix_code(txt_data, end)) - beg += parse_blockcode(ob, doc, txt_data, end); + else if (!(doc->ext_flags & HOEDOWN_EXT_DISABLE_INDENTED_CODE) && prefix_code(txt_data, end)) { + beg += parse_blockcode(ob, doc, txt_data, end, line); + } - else if (prefix_uli(txt_data, end)) - beg += parse_list(ob, doc, txt_data, end, 0); + else if (prefix_uli(txt_data, end)) { + beg += parse_list(ob, doc, txt_data, end, 0, line); + } - else if (prefix_oli(txt_data, end)) - beg += parse_list(ob, doc, txt_data, end, HOEDOWN_LIST_ORDERED); + else if (prefix_oli(txt_data, end)) { + beg += parse_list(ob, doc, txt_data, end, HOEDOWN_LIST_ORDERED, line); + } - else - beg += parse_paragraph(ob, doc, txt_data, end); + else { + beg += parse_paragraph(ob, doc, txt_data, end, line); + } } } @@ -2791,8 +2877,10 @@ hoedown_document_new( if (doc->md.linebreak) doc->active_char['\n'] = MD_CHAR_LINEBREAK; - if (doc->md.image || doc->md.link || doc->md.footnotes || doc->md.footnote_ref) + if (doc->md.image || doc->md.link || doc->md.footnotes || doc->md.footnote_ref) { doc->active_char['['] = MD_CHAR_LINK; + doc->active_char['!'] = MD_CHAR_IMAGE; + } doc->active_char['<'] = MD_CHAR_LANGLE; doc->active_char['\\'] = MD_CHAR_ESCAPE; @@ -2828,6 +2916,7 @@ hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t hoedown_buffer *text; size_t beg, end; + size_t line = 1; int footnotes_enabled; @@ -2891,12 +2980,14 @@ hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r') hoedown_buffer_putc(text, '\n'); - parse_block(ob, doc, text->data, text->size); + parse_block(ob, doc, text->data, text->size, &line); } /* footnotes */ - if (footnotes_enabled) - parse_footnote_list(ob, doc, &doc->footnotes_used); + if (footnotes_enabled) { + line = 1; + parse_footnote_list(ob, doc, &doc->footnotes_used, &line); + } if (doc->md.doc_footer) doc->md.doc_footer(ob, 0, &doc->data); @@ -2948,7 +3039,7 @@ hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const if (doc->md.doc_header) doc->md.doc_header(ob, 1, &doc->data); - parse_inline(ob, doc, text->data, text->size); + parse_inline(ob, doc, text->data, text->size, 1); if (doc->md.doc_footer) doc->md.doc_footer(ob, 1, &doc->data); diff --git a/src/document.h b/src/document.h index a8178fe..5110b18 100644 --- a/src/document.h +++ b/src/document.h @@ -99,43 +99,43 @@ struct hoedown_renderer { void *opaque; /* block level callbacks - NULL skips the block */ - void (*blockcode)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data); - void (*blockquote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - void (*header)(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data); - void (*hrule)(hoedown_buffer *ob, const hoedown_renderer_data *data); - void (*list)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data); - void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data); - void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - void (*table)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - void (*table_header)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - void (*table_body)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data); - void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data); - void (*blockhtml)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); + void (*blockcode)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data, size_t line); + void (*blockquote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + void (*header)(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data, size_t line); + void (*hrule)(hoedown_buffer *ob, const hoedown_renderer_data *data, size_t line); + void (*list)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data, size_t line); + void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data, size_t line); + void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + void (*table)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + void (*table_header)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + void (*table_body)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data, size_t line); + void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data, size_t line); + void (*blockhtml)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line); /* span level callbacks - NULL or return 0 prints the span verbatim */ - int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data); - int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); - int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - int (*underline)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - int (*highlight)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - int (*quote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - int (*image)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data); - int (*linebreak)(hoedown_buffer *ob, const hoedown_renderer_data *data); - int (*link)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data); - int (*triple_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data); - int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data); - int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data); - int (*raw_html)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); + int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data, size_t line); + int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line); + int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + int (*underline)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + int (*highlight)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + int (*quote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + int (*image)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data, size_t line); + int (*linebreak)(hoedown_buffer *ob, const hoedown_renderer_data *data, size_t line); + int (*link)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data, size_t line); + int (*triple_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line); + int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data, size_t line); + int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data, size_t line); + int (*raw_html)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line); /* low level callbacks - NULL copies input directly into the output */ - void (*entity)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); - void (*normal_text)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data); + void (*entity)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line); + void (*normal_text)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line); /* miscellaneous callbacks */ void (*doc_header)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data); @@ -56,7 +56,7 @@ static void escape_href(hoedown_buffer *ob, const uint8_t *source, size_t length * GENERIC RENDERER * ********************/ static int -rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data) +rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; @@ -93,7 +93,7 @@ rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_t } static void -rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data) +rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data, size_t line) { if (ob->size) hoedown_buffer_putc(ob, '\n'); @@ -112,7 +112,7 @@ rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buf } static void -rndr_blockquote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_blockquote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (ob->size) hoedown_buffer_putc(ob, '\n'); HOEDOWN_BUFPUTSL(ob, "<blockquote>\n"); @@ -121,7 +121,7 @@ rndr_blockquote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown } static int -rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data) +rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line) { HOEDOWN_BUFPUTSL(ob, "<code>"); if (text) escape_html(ob, text->data, text->size); @@ -130,7 +130,7 @@ rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_rend } static int -rndr_strikethrough(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_strikethrough(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (!content || !content->size) return 0; @@ -142,7 +142,7 @@ rndr_strikethrough(hoedown_buffer *ob, const hoedown_buffer *content, const hoed } static int -rndr_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (!content || !content->size) return 0; @@ -155,7 +155,7 @@ rndr_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const ho } static int -rndr_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (!content || !content->size) return 0; HOEDOWN_BUFPUTSL(ob, "<em>"); @@ -165,7 +165,7 @@ rndr_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_r } static int -rndr_underline(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_underline(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (!content || !content->size) return 0; @@ -178,7 +178,7 @@ rndr_underline(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_ } static int -rndr_highlight(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_highlight(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (!content || !content->size) return 0; @@ -191,7 +191,7 @@ rndr_highlight(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_ } static int -rndr_quote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_quote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (!content || !content->size) return 0; @@ -204,7 +204,7 @@ rndr_quote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_rend } static int -rndr_linebreak(hoedown_buffer *ob, const hoedown_renderer_data *data) +rndr_linebreak(hoedown_buffer *ob, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; hoedown_buffer_puts(ob, USE_XHTML(state) ? "<br/>\n" : "<br>\n"); @@ -212,7 +212,7 @@ rndr_linebreak(hoedown_buffer *ob, const hoedown_renderer_data *data) } static void -rndr_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data) +rndr_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; @@ -229,7 +229,7 @@ rndr_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const } static int -rndr_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data) +rndr_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; @@ -257,7 +257,7 @@ rndr_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffe } static void -rndr_list(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data) +rndr_list(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data, size_t line) { if (ob->size) hoedown_buffer_putc(ob, '\n'); hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "<ol>\n" : "<ul>\n"), 5); @@ -266,7 +266,7 @@ rndr_list(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags } static void -rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data) +rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data, size_t line) { HOEDOWN_BUFPUTSL(ob, "<li>"); if (content) { @@ -280,7 +280,7 @@ rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_fl } static void -rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; size_t i = 0; @@ -302,6 +302,7 @@ rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_ org = i; while (i < content->size && content->data[i] != '\n') i++; + line += i < content->size; if (i > org) hoedown_buffer_put(ob, content->data + org, i - org); @@ -313,7 +314,7 @@ rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_ if (i >= content->size - 1) break; - rndr_linebreak(ob, data); + rndr_linebreak(ob, data, line); i++; } } else { @@ -323,7 +324,7 @@ rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_ } static void -rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data) +rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line) { size_t org, sz; @@ -350,7 +351,7 @@ rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_ren } static int -rndr_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (!content || !content->size) return 0; HOEDOWN_BUFPUTSL(ob, "<strong><em>"); @@ -360,7 +361,7 @@ rndr_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const ho } static void -rndr_hrule(hoedown_buffer *ob, const hoedown_renderer_data *data) +rndr_hrule(hoedown_buffer *ob, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; if (ob->size) hoedown_buffer_putc(ob, '\n'); @@ -368,7 +369,7 @@ rndr_hrule(hoedown_buffer *ob, const hoedown_renderer_data *data) } static int -rndr_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data) +rndr_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; if (!link || !link->size) return 0; @@ -389,7 +390,7 @@ rndr_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer } static int -rndr_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data) +rndr_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; @@ -408,7 +409,7 @@ rndr_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_rend } static void -rndr_table(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_table(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (ob->size) hoedown_buffer_putc(ob, '\n'); HOEDOWN_BUFPUTSL(ob, "<table>\n"); @@ -417,7 +418,7 @@ rndr_table(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_rend } static void -rndr_table_header(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_table_header(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (ob->size) hoedown_buffer_putc(ob, '\n'); HOEDOWN_BUFPUTSL(ob, "<thead>\n"); @@ -426,7 +427,7 @@ rndr_table_header(hoedown_buffer *ob, const hoedown_buffer *content, const hoedo } static void -rndr_table_body(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_table_body(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (ob->size) hoedown_buffer_putc(ob, '\n'); HOEDOWN_BUFPUTSL(ob, "<tbody>\n"); @@ -435,7 +436,7 @@ rndr_table_body(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown } static void -rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { HOEDOWN_BUFPUTSL(ob, "<tr>\n"); if (content) hoedown_buffer_put(ob, content->data, content->size); @@ -443,7 +444,7 @@ rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_r } static void -rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data) +rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data, size_t line) { if (flags & HOEDOWN_TABLE_HEADER) { HOEDOWN_BUFPUTSL(ob, "<th"); @@ -479,7 +480,7 @@ rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_ } static int -rndr_superscript(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_superscript(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (!content || !content->size) return 0; HOEDOWN_BUFPUTSL(ob, "<sup>"); @@ -489,14 +490,14 @@ rndr_superscript(hoedown_buffer *ob, const hoedown_buffer *content, const hoedow } static void -rndr_normal_text(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_normal_text(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { if (content) escape_html(ob, content->data, content->size); } static void -rndr_footnotes(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data) +rndr_footnotes(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; @@ -511,7 +512,7 @@ rndr_footnotes(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_ } static void -rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data) +rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data, size_t line) { size_t i = 0; int pfound = 0; @@ -541,14 +542,14 @@ rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *content, unsigned in } static int -rndr_footnote_ref(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data) +rndr_footnote_ref(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data, size_t line) { hoedown_buffer_printf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\" rel=\"footnote\">%d</a></sup>", num, num, num); return 1; } static int -rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data) +rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data, size_t line) { hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\[" : "\\("), 2); escape_html(ob, text->data, text->size); @@ -557,7 +558,7 @@ rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const } static void -toc_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data) +toc_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data, size_t line) { hoedown_html_renderer_state *state = data->opaque; @@ -592,7 +593,7 @@ toc_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const h } static int -toc_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data) +toc_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data, size_t line) { if (content && content->size) hoedown_buffer_put(ob, content->data, content->size); return 1; diff --git a/src/html_smartypants.c b/src/html_smartypants.c index b0904da..e3dfa28 100644 --- a/src/html_smartypants.c +++ b/src/html_smartypants.c @@ -314,7 +314,7 @@ smartypants_cb__ltag(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t size_t tag, i = 0; /* This is a comment. Copy everything verbatim until --> or EOF is seen. */ - if (i + 4 < size && memcmp(text, "<!--", 4) == 0) { + if (i + 4 < size && memcmp(text + i, "<!--", 4) == 0) { i += 4; while (i + 3 < size && memcmp(text + i, "-->", 3) != 0) i++; diff --git a/src/version.h b/src/version.h index d3247b6..62fb366 100644 --- a/src/version.h +++ b/src/version.h @@ -12,10 +12,10 @@ extern "C" { * CONSTANTS * *************/ -#define HOEDOWN_VERSION "3.0.5" +#define HOEDOWN_VERSION "3.0.7" #define HOEDOWN_VERSION_MAJOR 3 #define HOEDOWN_VERSION_MINOR 0 -#define HOEDOWN_VERSION_REVISION 5 +#define HOEDOWN_VERSION_REVISION 7 /************* diff --git a/test/Tests/CommentsInMiddleOfLine.html b/test/Tests/CommentsInMiddleOfLine.html new file mode 100644 index 0000000..2b93166 --- /dev/null +++ b/test/Tests/CommentsInMiddleOfLine.html @@ -0,0 +1,6 @@ +<p>It would be super-keen to be able to use <a href= +"https://github.com/google/moe">MOE</a> directives in Markdown.</p> +<!-- HTML comments work at the start of a block --> +<p>But I'd <!-- MOE:begin_strip -->really, really +<!-- MOE:end_strip --> +like to be able to use them in the middle of a line.</p> diff --git a/test/Tests/CommentsInMiddleOfLine.text b/test/Tests/CommentsInMiddleOfLine.text new file mode 100644 index 0000000..22e08be --- /dev/null +++ b/test/Tests/CommentsInMiddleOfLine.text @@ -0,0 +1,8 @@ +It would be super-keen to be able to use [MOE](https://github.com/google/moe) +directives in Markdown. + +<!-- HTML comments work at the start of a block --> + +But I'd <!-- MOE:begin_strip -->really, really <!-- MOE:end_strip --> +like to be able to use them in the middle of a line. + diff --git a/test/Tests/Images.html b/test/Tests/Images.html new file mode 100644 index 0000000..2e6367c --- /dev/null +++ b/test/Tests/Images.html @@ -0,0 +1,9 @@ +<p>This is an <img src="/url" alt="image">.</p> + +<p>This is a tricky !<img src="/url" alt="image">.</p> + +<p>This is another tricky case: !<a href="/url">not image</a>.</p> + +<p>This is a reference <img src="/url2" alt="image">.</p> + +<p>Terminating !</p> diff --git a/test/Tests/Images.text b/test/Tests/Images.text new file mode 100644 index 0000000..24c0d32 --- /dev/null +++ b/test/Tests/Images.text @@ -0,0 +1,11 @@ +This is an . + +This is a tricky !. + +This is another tricky case: \. + +This is a reference ![image][ref]. + +[ref]: /url2 + +Terminating ! diff --git a/test/Tests/list.html b/test/Tests/list.html new file mode 100644 index 0000000..21b4f80 --- /dev/null +++ b/test/Tests/list.html @@ -0,0 +1,6 @@ +fuck +<ul> + <li>First,test</li> + <li>Second,huhu</li> +</ul> +<p>Coolisn't it?</p> diff --git a/test/Tests/list.text b/test/Tests/list.text new file mode 100644 index 0000000..d3f6d04 --- /dev/null +++ b/test/Tests/list.text @@ -0,0 +1,7 @@ +* First, + test + * Second, + huhu + +Cool +isn't it? diff --git a/test/config.json b/test/config.json index 365c7bc..5697951 100644 --- a/test/config.json +++ b/test/config.json @@ -98,6 +98,10 @@ "flags": ["--html-toc", "-t", "3"] }, { + "input": "Tests/CommentsInMiddleOfLine.text", + "output": "Tests/CommentsInMiddleOfLine.html" + }, + { "input": "Tests/Math.text", "output": "Tests/Math.html", "flags": ["--math"] @@ -111,6 +115,11 @@ "input": "Tests/Table.text", "output": "Tests/Table.html", "flags": ["--tables"] + }, + { + "input": "Tests/Images.text", + "output": "Tests/Images.html", + "flags": [] } ] } diff --git a/test/line.c b/test/line.c new file mode 100644 index 0000000..23cb691 --- /dev/null +++ b/test/line.c @@ -0,0 +1,227 @@ +#include <stdio.h> +#include <unistd.h> +#include "../src/html.h" + +typedef struct { + char *content; + size_t length; +} RawBuffer; + +void do_printing(const char *name, size_t line) { + printf("%s => line:%zu\n", name, line); +} + +void blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, + const hoedown_renderer_data *data, size_t line) { + do_printing("blockcode", line); +} + +void blockquote(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("blockquote", line); +} + +void header(hoedown_buffer *ob, const hoedown_buffer *text, int level, + const hoedown_renderer_data *data, size_t line) { + do_printing("header", line); +} + +void list(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, + const hoedown_renderer_data *data, size_t line) { + do_printing("list", line); +} + +void listitem(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, + const hoedown_renderer_data *data, size_t line) { + do_printing("listitem", line); +} + +void paragraph(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("paragraph", line); +} + +void table(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("table", line); +} + +void table_header(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("table_header", line); +} + +void table_body(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("table_body", line); +} + +void table_row(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("table_row", line); +} + +void table_cell(hoedown_buffer *ob, const hoedown_buffer *text, + hoedown_table_flags flags, const hoedown_renderer_data *data, size_t line) { + do_printing("table_cell", line); +} + +void footnotes(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data, size_t line) { + do_printing("footnotes", line); +} + +void footnote_def(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int num, + const hoedown_renderer_data *data, size_t line) { + do_printing("footnote_def", line); +} + +void blockhtml(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("blockhtml", line); +} + +int codespan(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("codespan", line); + return 0; +} + +int double_emphasis(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("double_emphasis", line); + return 0; +} + +int emphasis(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("emphasis", line); + return 0; +} + +int underline(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("underline", line); + return 0; +} + +int highlight(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("highlight", line); + return 0; +} + +int quote(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("quote", line); + return 0; +} + +int image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, + const hoedown_buffer *alt, const hoedown_renderer_data *data, size_t line) { + do_printing("image", line); + return 0; +} + +int _link(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *link, + const hoedown_buffer *title, const hoedown_renderer_data *data, size_t line) { + do_printing("link", line); + return 0; +} + +int triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("triple_emphasis", line); + return 0; +} + +int strikethrough(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("strikethrough", line); + return 0; +} + +int superscript(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("superscript", line); + return 0; +} + +int math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, + const hoedown_renderer_data *data, size_t line) { + do_printing("math", line); + return 0; +} + +int raw_html(hoedown_buffer *ob, const hoedown_buffer *text, + const hoedown_renderer_data *data, size_t line) { + do_printing("raw_html", line); + return 0; +} + +int get_file_content(RawBuffer *buffer, char *file_name) { + FILE *fp = fopen(file_name, "r"); + + if (!fp) { + fprintf(stderr, "Cannot read file: '%s'\n", file_name); + return 2; + } + fseek(fp, 0, SEEK_END); + buffer->length = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (!(buffer->content = malloc(buffer->length))) { + fprintf(stderr, "%s\n", "Malloc failed..."); + fclose(fp); + return 3; + } + fread(buffer->content, 1, buffer->length, fp); + fclose(fp); + return 0; +} + +int main(int ac, char **av) { + if (ac != 2) { + fprintf(stderr, "%s\n", "A file name is expected."); + return 1; + } + RawBuffer buffer = {0, 0}; + int ret = get_file_content(&buffer, av[1]); + if (ret) { + return ret; + } + hoedown_renderer *renderer = hoedown_html_renderer_new(0, 0); + renderer->blockcode = blockcode; + renderer->blockquote = blockquote; + renderer->header = header; + renderer->list = list; + renderer->listitem = listitem; + renderer->paragraph = paragraph; + renderer->table = table; + renderer->table_header = table_header; + renderer->table_cell = table_cell; + renderer->table_row = table_row; + renderer->table_body = table_body; + renderer->footnotes = footnotes; + renderer->footnote_def = footnote_def; + renderer->blockhtml = blockhtml; + renderer->codespan = codespan; + renderer->double_emphasis = double_emphasis; + renderer->emphasis = emphasis; + renderer->underline = underline; + renderer->highlight = highlight; + renderer->quote = quote; + renderer->image = image; + renderer->link = _link; + renderer->triple_emphasis = triple_emphasis; + renderer->strikethrough = strikethrough; + renderer->superscript = superscript; + renderer->math = math; + renderer->raw_html = raw_html; + hoedown_document *document = hoedown_document_new(renderer, 0, 16); + hoedown_buffer *html = hoedown_buffer_new(16); + hoedown_document_render(document, html, (const uint8_t*)buffer.content, buffer.length); + free(buffer.content); + hoedown_buffer_free(html); + hoedown_document_free(document); + hoedown_html_renderer_free(renderer); + return 0; +} diff --git a/test/line_tests/basic.md b/test/line_tests/basic.md new file mode 100644 index 0000000..d61b236 --- /dev/null +++ b/test/line_tests/basic.md @@ -0,0 +1,12 @@ +# Basic file + +This is a basic main function example: + +```C +int main() { + printf("test!\n"); + return 0; +} +``` + +Basics and stuff. For more information, read the funny manual! diff --git a/test/line_tests/basic.out b/test/line_tests/basic.out new file mode 100644 index 0000000..033fb04 --- /dev/null +++ b/test/line_tests/basic.out @@ -0,0 +1,7 @@ +header => line:1 +paragraph => line:3 +codespan => line:5 +codespan => line:5 +codespan => line:5 +paragraph => line:5 +paragraph => line:12 diff --git a/test/line_tests/test.md b/test/line_tests/test.md new file mode 100644 index 0000000..37b5672 --- /dev/null +++ b/test/line_tests/test.md @@ -0,0 +1,61 @@ +# Test + +``` +Some text in a block code +``` + +Now let's try a list: + + * Oh! + * What a nice list! + + pony! + +### Sub-title + +What to put in here? + +### Another! + +uuuh?! + +> This a blockquote! +> +> with an empty line + +## New title! + +test? + +<table> + <tr> + <td>Foo</td> + </tr> + <tr> + <td>Bar</td> + </tr> +</table> + +http://test.com + +42 > 5 + + 1. a + 2. b + 3. c + 4. d + + blockcode + +Let's test [urls!](http://test.com)! And go for [test2], right? + +[test2]: http://test.com + +__hoho__ and *hoho*. + +And instead a `function()`! + + last test + or another + +yeay!
\ No newline at end of file diff --git a/test/line_tests/test.out b/test/line_tests/test.out new file mode 100644 index 0000000..34e79d6 --- /dev/null +++ b/test/line_tests/test.out @@ -0,0 +1,41 @@ +header => line:1 +codespan => line:3 +codespan => line:3 +codespan => line:3 +paragraph => line:3 +paragraph => line:7 +listitem => line:9 +paragraph => line:10 +paragraph => line:12 +listitem => line:10 +list => line:9 +header => line:14 +paragraph => line:16 +header => line:18 +paragraph => line:20 +paragraph => line:26 +paragraph => line:28 +blockquote => line:22 +header => line:26 +paragraph => line:28 +blockhtml => line:30 +paragraph => line:39 +paragraph => line:41 +listitem => line:43 +listitem => line:44 +listitem => line:45 +paragraph => line:46 +paragraph => line:48 +listitem => line:46 +list => line:43 +link => line:50 +link => line:50 +paragraph => line:50 +double_emphasis => line:54 +emphasis => line:54 +emphasis => line:54 +paragraph => line:54 +codespan => line:56 +paragraph => line:56 +blockcode => line:58 +paragraph => line:61 diff --git a/test/runner.py b/test/runner.py index 7cbb27d..726e8ab 100755 --- a/test/runner.py +++ b/test/runner.py @@ -100,7 +100,32 @@ class MarkdownTestsMeta(type): class MarkdownTests(with_metaclass(MarkdownTestsMeta, unittest.TestCase)): - pass + def test_lines(self): + from os import listdir + from os.path import isfile, join, splitext + + LINE_TESTS = "./test/line_tests" + files = [join(LINE_TESTS, f) for f in listdir(LINE_TESTS) + if isfile(join(LINE_TESTS, f))] + indexes = {} + for f in files: + filename, file_extension = splitext(f) + if file_extension == ".md": + indexes[f] = filename + '.out' + for index in indexes: + content = '' + try: + with open(indexes[index], 'r') as fdd: + content = fdd.read() + except Exception: + raise TestFailed(index, + 'Missing file: "{}"'.format(indexes[index]), + '') + child = subprocess.Popen(["./test/tester", index], + stdout=subprocess.PIPE) + stdout = child.communicate()[0] + if stdout != content: + raise TestFailed(index, content, stdout) if __name__ == '__main__': |