summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-01-19 16:24:48 -0800
committerGitHub <noreply@github.com>2017-01-19 16:24:48 -0800
commitda282f1bb7277b4d30fa1599ee29ad8eb4dd2a92 (patch)
tree34b6fa5bd72b934e753a3f46d1eaa872f817e377
parenta3736a0a1907cbc8bf619708738815a5fd789c80 (diff)
parent78e7b6f69d3fa0cb6ae6e7fb9278c3fd167ec0d1 (diff)
downloadrust-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--.gitignore1
-rw-r--r--Makefile10
-rw-r--r--src/document.c433
-rw-r--r--src/document.h66
-rw-r--r--src/html.c71
-rw-r--r--src/html_smartypants.c2
-rw-r--r--src/version.h4
-rw-r--r--test/Tests/CommentsInMiddleOfLine.html6
-rw-r--r--test/Tests/CommentsInMiddleOfLine.text8
-rw-r--r--test/Tests/Images.html9
-rw-r--r--test/Tests/Images.text11
-rw-r--r--test/Tests/list.html6
-rw-r--r--test/Tests/list.text7
-rw-r--r--test/config.json9
-rw-r--r--test/line.c227
-rw-r--r--test/line_tests/basic.md12
-rw-r--r--test/line_tests/basic.out7
-rw-r--r--test/line_tests/test.md61
-rw-r--r--test/line_tests/test.out41
-rwxr-xr-xtest/runner.py27
20 files changed, 773 insertions, 245 deletions
diff --git a/.gitignore b/.gitignore
index b8a9371..41a680e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ hoedown.lib
smartypants
libhoedown.so*
libhoedown.a
+test/tester
diff --git a/Makefile b/Makefile
index 75c3e26..2b16b88 100644
--- a/Makefile
+++ b/Makefile
@@ -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);
diff --git a/src/html.c b/src/html.c
index b5101c1..fd96c77 100644
--- a/src/html.c
+++ b/src/html.c
@@ -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 ![image](/url).
+
+This is a tricky !![image](/url).
+
+This is another tricky case: \![not image](/url).
+
+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__':