diff options
author | Xavier Mendez <jmendeth@gmail.com> | 2014-08-18 12:03:18 +0200 |
---|---|---|
committer | Xavier Mendez <jmendeth@gmail.com> | 2014-08-18 12:03:18 +0200 |
commit | d3c7ec801bed551fdcf56d25ea4c7e210c274689 (patch) | |
tree | daa7b0faddc9d7a482e1ef6453cdebe09e43defe /src | |
parent | 6590101008066f69ad36f6ea5cd47e4da16baaff (diff) | |
download | rust-hoedown-d3c7ec801bed551fdcf56d25ea4c7e210c274689.tar.gz |
document: Implement MATH extension
Diffstat (limited to 'src')
-rw-r--r-- | src/document.c | 65 | ||||
-rw-r--r-- | src/document.h | 9 |
2 files changed, 69 insertions, 5 deletions
diff --git a/src/document.c b/src/document.c index 8ae8eb9..8f35c98 100644 --- a/src/document.c +++ b/src/document.c @@ -78,6 +78,7 @@ static size_t char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uin 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); enum markdown_char_t { MD_CHAR_NONE = 0, @@ -92,7 +93,8 @@ enum markdown_char_t { MD_CHAR_AUTOLINK_EMAIL, MD_CHAR_AUTOLINK_WWW, MD_CHAR_SUPERSCRIPT, - MD_CHAR_QUOTE + MD_CHAR_QUOTE, + MD_CHAR_MATH }; static char_trigger markdown_char_ptrs[] = { @@ -108,7 +110,8 @@ static char_trigger markdown_char_ptrs[] = { &char_autolink_email, &char_autolink_www, &char_superscript, - &char_quote + &char_quote, + &char_math }; /* render • structure containing state for a parser instance */ @@ -685,6 +688,37 @@ parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz return 0; } +/* 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) +{ + size_t i = delimsz; + if (!doc->md.math) return 0; + + /* find ending delimiter */ + while (1) { + while (i < size && data[i] != (uint8_t)end[0]) i++; + if (i >= size) return 0; + + if (!is_escaped(data, i) && !(i + delimsz > size) + && memcmp(data + i, end, delimsz) == 0) + break; + i++; + } + + /* enforce spacing around the span */ + if (offset && !_isspace(data[-1])) return 0; + if (i + delimsz < size && !_isspace(data[i + delimsz])) return 0; + + /* prepare buffers */ + hoedown_buffer text = { data + delimsz, i - delimsz, 0, 0, NULL, NULL, NULL }; + + /* call callback */ + if (doc->md.math(ob, &text, displaymode, doc->md.opaque)) + return i + delimsz; + return 0; +} + /* 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) @@ -832,10 +866,18 @@ char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs static size_t char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offset, size_t size) { - static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~=\""; + static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~=\"$"; hoedown_buffer work = { 0, 0, 0, 0, NULL, NULL, NULL }; + size_t w; if (size > 1) { + 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] == '['); + if (w) return w; + } + if (strchr(escape_chars, data[1]) == NULL) return 0; @@ -1289,6 +1331,20 @@ char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_ 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) +{ + /* double dollar */ + if (size > 1 && data[1] == '$') + return parse_math(ob, doc, data, offset, size, "$$", 2, doc->ext_flags & HOEDOWN_EXT_MATH_DOLLAR); + + /* single dollar allowed only at with flag */ + if (doc->ext_flags & HOEDOWN_EXT_MATH_DOLLAR) + return parse_math(ob, doc, data, offset, size, "$", 1, 0); + + return 0; +} + /********************************* * BLOCK-LEVEL PARSING FUNCTIONS * *********************************/ @@ -2735,6 +2791,9 @@ hoedown_document_new( if (extensions & HOEDOWN_EXT_QUOTE) doc->active_char['"'] = MD_CHAR_QUOTE; + if (extensions & HOEDOWN_EXT_MATH) + doc->active_char['$'] = MD_CHAR_MATH; + /* Extension data */ doc->ext_flags = extensions; doc->max_nesting = max_nesting; diff --git a/src/document.h b/src/document.h index 8fec835..23e850c 100644 --- a/src/document.h +++ b/src/document.h @@ -27,11 +27,13 @@ enum hoedown_extensions { HOEDOWN_EXT_HIGHLIGHT = (1 << 6), HOEDOWN_EXT_QUOTE = (1 << 7), HOEDOWN_EXT_SUPERSCRIPT = (1 << 8), + HOEDOWN_EXT_MATH = (1 << 13), /* other flags */ HOEDOWN_EXT_LAX_SPACING = (1 << 9), HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 10), HOEDOWN_EXT_SPACE_HEADERS = (1 << 11), + HOEDOWN_EXT_MATH_DOLLAR = (1 << 14), /* negative flags */ HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 12) @@ -48,12 +50,14 @@ enum hoedown_extensions { HOEDOWN_EXT_UNDERLINE |\ HOEDOWN_EXT_HIGHLIGHT |\ HOEDOWN_EXT_QUOTE |\ - HOEDOWN_EXT_SUPERSCRIPT ) + HOEDOWN_EXT_SUPERSCRIPT |\ + HOEDOWN_EXT_MATH ) #define HOEDOWN_EXT_FLAGS (\ HOEDOWN_EXT_LAX_SPACING |\ HOEDOWN_EXT_NO_INTRA_EMPHASIS |\ - HOEDOWN_EXT_SPACE_HEADERS ) + HOEDOWN_EXT_SPACE_HEADERS |\ + HOEDOWN_EXT_MATH_DOLLAR ) #define HOEDOWN_EXT_NEGATIVE (\ HOEDOWN_EXT_DISABLE_INDENTED_CODE ) @@ -119,6 +123,7 @@ struct hoedown_renderer { int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque); int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, void *opaque); + int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, void *opaque); /* low level callbacks - NULL copies input directly into the output */ void (*entity)(hoedown_buffer *ob, const hoedown_buffer *entity, void *opaque); |