summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorXavier Mendez <jmendeth@gmail.com>2014-08-18 12:03:18 +0200
committerXavier Mendez <jmendeth@gmail.com>2014-08-18 12:03:18 +0200
commitd3c7ec801bed551fdcf56d25ea4c7e210c274689 (patch)
treedaa7b0faddc9d7a482e1ef6453cdebe09e43defe /src
parent6590101008066f69ad36f6ea5cd47e4da16baaff (diff)
downloadrust-hoedown-d3c7ec801bed551fdcf56d25ea4c7e210c274689.tar.gz
document: Implement MATH extension
Diffstat (limited to 'src')
-rw-r--r--src/document.c65
-rw-r--r--src/document.h9
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);