packages feed

sundown 0.2.3 → 0.3

raw patch · 19 files changed

+675/−604 lines, 19 files

Files

cbits/autolink.c view
@@ -22,7 +22,7 @@ #include <ctype.h>  int-sd_autolink_issafe(const char *link, size_t link_len)+sd_autolink_issafe(const uint8_t *link, size_t link_len) { 	static const size_t valid_uris_count = 4; 	static const char *valid_uris[] = {@@ -35,7 +35,7 @@ 		size_t len = strlen(valid_uris[i]);  		if (link_len > len &&-			strncasecmp(link, valid_uris[i], len) == 0 &&+			strncasecmp((char *)link, valid_uris[i], len) == 0 && 			isalnum(link[len])) 			return 1; 	}@@ -44,9 +44,9 @@ }  static size_t-autolink_delim(char *data, size_t link_end, size_t offset, size_t size)+autolink_delim(uint8_t *data, size_t link_end, size_t offset, size_t size) {-	char cclose, copen = 0;+	uint8_t cclose, copen = 0; 	size_t i;  	for (i = 0; i < link_end; ++i)@@ -128,7 +128,7 @@ }  static size_t-check_domain(char *data, size_t size)+check_domain(uint8_t *data, size_t size) { 	size_t i, np = 0; @@ -147,7 +147,7 @@ }  size_t-sd_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)+sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size) { 	size_t link_end; @@ -177,13 +177,13 @@ }  size_t-sd_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)+sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size) { 	size_t link_end, rewind; 	int nb = 0, np = 0;  	for (rewind = 0; rewind < offset; ++rewind) {-		char c = data[-rewind - 1];+		uint8_t c = data[-rewind - 1];  		if (isalnum(c)) 			continue;@@ -198,7 +198,7 @@ 		return 0;  	for (link_end = 0; link_end < size; ++link_end) {-		char c = data[link_end];+		uint8_t c = data[link_end];  		if (isalnum(c)) 			continue;@@ -226,7 +226,7 @@ }  size_t-sd_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)+sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size) { 	size_t link_end, rewind = 0, domain_len; 
cbits/autolink.h view
@@ -20,16 +20,16 @@ #include "buffer.h"  extern int-sd_autolink_issafe(const char *link, size_t link_len);+sd_autolink_issafe(const uint8_t *link, size_t link_len);  extern size_t-sd_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);+sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);  extern size_t-sd_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);+sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);  extern size_t-sd_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);+sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);  #endif 
cbits/buffer.c view
@@ -30,59 +30,7 @@ #	define _buf_vsnprintf vsnprintf #endif -/* bufcmp: buffer comparison */ int-bufcmp(const struct buf *a, const struct buf *b)-{-	size_t i = 0;-	size_t cmplen;--	if (a == b)-		return 0;--	if (!a)-		return -1;--	if (!b)-		return 1;--	cmplen = (a->size < b->size) ? a->size : b->size;--	while (i < cmplen && a->data[i] == b->data[i])-		++i;--	if (i < a->size) {-		if (i < b->size) return a->data[i] - b->data[i];-		return 1;-	} else {-		if (i < b->size) return -1;-		return 0;-	}-}--/* bufcmps: comparison of a string to a buffer */-int-bufcmps(const struct buf *a, const char *b)-{-	const size_t len = strlen(b);-	size_t cmplen = len;-	int r;--	if (!a || !a->size)-		return b ? 0 : -1;--	if (len < a->size)-		cmplen = a->size;--	r = strncmp(a->data, b, cmplen);--	if (r) return r;-	else if (a->size == len) return 0;-	else if (a->size < len) return -1;-	else return 1;-}--int bufprefix(const struct buf *buf, const char *prefix) { 	size_t i;@@ -98,42 +46,6 @@ 	return 0; } --/* bufdup: buffer duplication */-struct buf *-bufdup(const struct buf *src, size_t dupunit)-{-	size_t blocks;-	struct buf *ret;-	if (src == 0)-		return 0;--	ret = malloc(sizeof (struct buf));-	if (ret == 0)-		return 0;--	ret->unit = dupunit;-	ret->size = src->size;-	ret->ref = 1;-	if (!src->size) {-		ret->asize = 0;-		ret->data = 0;-		return ret;-	}--	blocks = (src->size + dupunit - 1) / dupunit;-	ret->asize = blocks * dupunit;-	ret->data = malloc(ret->asize);--	if (ret->data == 0) {-		free(ret);-		return 0;-	}--	memcpy(ret->data, src->data, src->size);-	return ret;-}- /* bufgrow: increasing the allocated size to the given value */ int bufgrow(struct buf *buf, size_t neosz)@@ -170,7 +82,6 @@ 	if (ret) { 		ret->data = 0; 		ret->size = ret->asize = 0;-		ret->ref = 1; 		ret->unit = unit; 	} 	return ret;@@ -184,11 +95,11 @@ 		return NULL;  	if (buf->size < buf->asize && buf->data[buf->size] == 0)-		return buf->data;+		return (char *)buf->data;  	if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1) == 0) { 		buf->data[buf->size] = 0;-		return buf->data;+		return (char *)buf->data; 	}  	return NULL;@@ -229,9 +140,9 @@ }  -/* bufputc: appends a single char to a buffer */+/* bufputc: appends a single uint8_t to a buffer */ void-bufputc(struct buf *buf, char c)+bufputc(struct buf *buf, int c) { 	if (!buf) 		return;@@ -250,10 +161,8 @@ 	if (!buf) 		return; -	if (--buf->ref == 0) {-		free(buf->data);-		free(buf);-	}+	free(buf->data);+	free(buf); }  @@ -269,20 +178,6 @@ 	buf->size = buf->asize = 0; } --/* bufset: safely assigns a buffer to another */-void-bufset(struct buf **dest, struct buf *src)-{-	if (src) {-		if (!src->asize) src = bufdup(src, 1);-		else src->ref += 1;-	}--	bufrelease(*dest);-	*dest = src;-}- /* bufslurp: removes a given number of bytes from the head of the array */ void bufslurp(struct buf *buf, size_t len)@@ -308,7 +203,7 @@ 	if (buf == 0 || (buf->size >= buf->asize && bufgrow(buf, buf->size + 1)) < 0) 		return; -	n = _buf_vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap);+	n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);  	if (n < 0) { #ifdef _MSC_VER@@ -322,7 +217,7 @@ 		if (bufgrow(buf, buf->size + n + 1) < 0) 			return; -		n = _buf_vsnprintf(buf->data + buf->size, buf->asize - buf->size, fmt, ap);+		n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap); 	}  	if (n < 0)
cbits/buffer.h view
@@ -20,6 +20,7 @@  #include <stddef.h> #include <stdarg.h>+#include <stdint.h>  #if defined(_MSC_VER) #define __attribute__(x)@@ -33,36 +34,23 @@  /* struct buf: character array buffer */ struct buf {-	char *data;		/* actual character data */+	uint8_t *data;		/* actual character data */ 	size_t size;	/* size of the string */ 	size_t asize;	/* allocated size (0 = volatile buffer) */ 	size_t unit;	/* reallocation unit size (0 = read-only buffer) */-	int	ref;		/* reference count */-};	+};  /* CONST_BUF: global buffer from a string litteral */ #define BUF_STATIC(string) \-	{ string, sizeof string -1, sizeof string, 0, 0 }+	{ (uint8_t *)string, sizeof string -1, sizeof string, 0, 0 }  /* VOLATILE_BUF: macro for creating a volatile buffer on the stack */ #define BUF_VOLATILE(strname) \-	{ strname, strlen(strname), 0, 0, 0 }+	{ (uint8_t *)strname, strlen(strname), 0, 0, 0 }  /* BUFPUTSL: optimized bufputs of a string litteral */-#define BUFPUTSL(output, litteral) \-	bufput(output, litteral, sizeof litteral - 1)--/* bufcmp: case-sensitive buffer comparison */-int bufcmp(const struct buf *, const struct buf *);--/* bufcmps: case-sensitive comparison of a string to a buffer */-int bufcmps(const struct buf *, const char *); --/* bufprefix: compare the beginning of a buffer with a string */-int bufprefix(const struct buf *buf, const char *prefix); --/* bufdup: buffer duplication */-struct buf *bufdup(const struct buf *, size_t) __attribute__ ((malloc));+#define BUFPUTSL(output, literal) \+	bufput(output, literal, sizeof literal - 1)  /* bufgrow: increasing the allocated size to the given value */ int bufgrow(struct buf *, size_t);@@ -73,17 +61,17 @@ /* bufnullterm: NUL-termination of the string array (making a C-string) */ const char *bufcstr(struct buf *); -/* bufprintf: formatted printing to a buffer */-void bufprintf(struct buf *, const char *, ...) __attribute__ ((format (printf, 2, 3)));+/* bufprefix: compare the beginning of a buffer with a string */+int bufprefix(const struct buf *buf, const char *prefix);  /* bufput: appends raw data to a buffer */-void bufput(struct buf *, const void*, size_t);+void bufput(struct buf *, const void *, size_t);  /* bufputs: appends a NUL-terminated string to a buffer */-void bufputs(struct buf *, const char*);+void bufputs(struct buf *, const char *);  /* bufputc: appends a single char to a buffer */-void bufputc(struct buf *, char);+void bufputc(struct buf *, int);  /* bufrelease: decrease the reference count and free the buffer if needed */ void bufrelease(struct buf *);@@ -91,13 +79,13 @@ /* bufreset: frees internal data of the buffer */ void bufreset(struct buf *); -/* bufset: safely assigns a buffer to another */-void bufset(struct buf **, struct buf *);- /* bufslurp: removes a given number of bytes from the head of the array */ void bufslurp(struct buf *, size_t); +/* bufprintf: formatted printing to a buffer */+void bufprintf(struct buf *, const char *, ...) __attribute__ ((format (printf, 2, 3)));+ /* vbufprintf: stdarg variant of formatted printing into a buffer */-void vbufprintf(struct buf *, const char*, va_list);+void vbufprintf(struct buf *, const char * , va_list);  #endif
+ cbits/houdini.h view
@@ -0,0 +1,28 @@+#ifndef __HOUDINI_H__+#define __HOUDINI_H__++#include "buffer.h"++#ifdef HOUDINI_USE_LOCALE+#	define _isxdigit(c) isxdigit(c)+#	define _isdigit(c) isdigit(c)+#else+/*+ * Helper _isdigit methods -- do not trust the current locale+ * */+#	define _isxdigit(c) (strchr("0123456789ABCDEFabcdef", (c)) != NULL)+#	define _isdigit(c) ((c) >= '0' && (c) <= '9')+#endif++extern void houdini_escape_html(struct buf *ob, const uint8_t *src, size_t size);+extern void houdini_escape_html0(struct buf *ob, const uint8_t *src, size_t size, int secure);+extern void houdini_unescape_html(struct buf *ob, const uint8_t *src, size_t size);+extern void houdini_escape_uri(struct buf *ob, const uint8_t *src, size_t size);+extern void houdini_escape_url(struct buf *ob, const uint8_t *src, size_t size);+extern void houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size);+extern void houdini_unescape_uri(struct buf *ob, const uint8_t *src, size_t size);+extern void houdini_unescape_url(struct buf *ob, const uint8_t *src, size_t size);+extern void houdini_escape_js(struct buf *ob, const uint8_t *src, size_t size);+extern void houdini_unescape_js(struct buf *ob, const uint8_t *src, size_t size);++#endif
+ cbits/houdini_href_e.c view
@@ -0,0 +1,108 @@+#include <assert.h>+#include <stdio.h>+#include <string.h>++#include "houdini.h"++#define ESCAPE_GROW_FACTOR(x) (((x) * 12) / 10)++/*+ * The following characters will not be escaped:+ *+ *		-_.+!*'(),%#@?=;:/,+&$ alphanum+ *+ * Note that this character set is the addition of:+ *+ *	- The characters which are safe to be in an URL+ *	- The characters which are *not* safe to be in+ *	an URL because they are RESERVED characters.+ *+ * We asume (lazily) that any RESERVED char that+ * appears inside an URL is actually meant to+ * have its native function (i.e. as an URL + * component/separator) and hence needs no escaping.+ *+ * There are two exceptions: the chacters & (amp)+ * and ' (single quote) do not appear in the table.+ * They are meant to appear in the URL as components,+ * yet they require special HTML-entity escaping+ * to generate valid HTML markup.+ *+ * All other characters will be escaped to %XX.+ *+ */+static const char HREF_SAFE[] = {+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, +	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+};++void+houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size)+{+	static const char hex_chars[] = "0123456789ABCDEF";+	size_t  i = 0, org;+	char hex_str[3];++	bufgrow(ob, ESCAPE_GROW_FACTOR(size));+	hex_str[0] = '%';++	while (i < size) {+		org = i;+		while (i < size && HREF_SAFE[src[i]] != 0)+			i++;++		if (i > org)+			bufput(ob, src + org, i - org);++		/* escaping */+		if (i >= size)+			break;++		switch (src[i]) {+		/* amp appears all the time in URLs, but needs+		 * HTML-entity escaping to be inside an href */+		case '&': +			BUFPUTSL(ob, "&amp;");+			break;++		/* the single quote is a valid URL character+		 * according to the standard; it needs HTML+		 * entity escaping too */+		case '\'':+			BUFPUTSL(ob, "&#x27;");+			break;+		+		/* the space can be escaped to %20 or a plus+		 * sign. we're going with the generic escape+		 * for now. the plus thing is more commonly seen+		 * when building GET strings */+#if 0+		case ' ':+			bufputc(ob, '+');+			break;+#endif++		/* every other character goes with a %XX escaping */+		default:+			hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];+			hex_str[2] = hex_chars[src[i] & 0xF];+			bufput(ob, hex_str, 3);+		}++		i++;+	}+}
+ cbits/houdini_html_e.c view
@@ -0,0 +1,84 @@+#include <assert.h>+#include <stdio.h>+#include <string.h>++#include "houdini.h"++#define ESCAPE_GROW_FACTOR(x) (((x) * 12) / 10) /* this is very scientific, yes */++/**+ * According to the OWASP rules:+ *+ * & --> &amp;+ * < --> &lt;+ * > --> &gt;+ * " --> &quot;+ * ' --> &#x27;     &apos; is not recommended+ * / --> &#x2F;     forward slash is included as it helps end an HTML entity+ *+ */+static const char HTML_ESCAPE_TABLE[] = {+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+};++static const char *HTML_ESCAPES[] = {+        "",+        "&quot;",+        "&amp;",+        "&#39;",+        "&#47;",+        "&lt;",+        "&gt;"+};++void+houdini_escape_html0(struct buf *ob, const uint8_t *src, size_t size, int secure)+{+	size_t  i = 0, org, esc;++	bufgrow(ob, ESCAPE_GROW_FACTOR(size));++	while (i < size) {+		org = i;+		while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)+			i++;++		if (i > org)+			bufput(ob, src + org, i - org);++		/* escaping */+		if (i >= size)+			break;++		/* The forward slash is only escaped in secure mode */+		if (src[i] == '/' && !secure) {+			bufputc(ob, '/');+		} else {+			bufputs(ob, HTML_ESCAPES[esc]);+		}++		i++;+	}+}++void+houdini_escape_html(struct buf *ob, const uint8_t *src, size_t size)+{+	houdini_escape_html0(ob, src, size, 1);+}+
cbits/html.c view
@@ -23,43 +23,12 @@ #include <stdio.h> #include <ctype.h> -#define USE_XHTML(opt) (opt->flags & HTML_USE_XHTML)--static inline void-put_scaped_char(struct buf *ob, char c)-{-	switch (c) {-		case '<': BUFPUTSL(ob, "&lt;"); break;-		case '>': BUFPUTSL(ob, "&gt;"); break;-		case '&': BUFPUTSL(ob, "&amp;"); break;-		case '"': BUFPUTSL(ob, "&quot;"); break;-		default: bufputc(ob, c); break;-	}-}--/* sdhtml_escape • copy the buffer entity-escaping '<', '>', '&' and '"' */-void-sdhtml_escape(struct buf *ob, const char *src, size_t size)-{-	size_t  i = 0, org;-	while (i < size) {-		/* copying directly unescaped characters */-		org = i;-		while (i < size && src[i] != '<' && src[i] != '>'-		&& src[i] != '&' && src[i] != '"')-			i += 1;-		if (i > org) bufput(ob, src + org, i - org);--		/* escaping */-		if (i >= size) break;+#include "houdini.h" -		put_scaped_char(ob, src[i]);-		i++;-	}-}+#define USE_XHTML(opt) (opt->flags & HTML_USE_XHTML)  int-sdhtml_tag(const char *tag_data, size_t tag_size, const char *tagname)+sdhtml_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname) { 	size_t i; 	int closed = 0;@@ -95,7 +64,7 @@  * GENERIC RENDERER *  ********************/ static int-rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque)+rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque) { 	struct html_renderopt *options = opaque; @@ -110,7 +79,7 @@ 	BUFPUTSL(ob, "<a href=\""); 	if (type == MKDA_EMAIL) 		BUFPUTSL(ob, "mailto:");-	sdhtml_escape(ob, link->data, link->size);+	houdini_escape_href(ob, link->data, link->size);  	if (options->link_attributes) { 		bufputc(ob, '\"');@@ -126,9 +95,9 @@ 	 * want to print the `mailto:` prefix 	 */ 	if (bufprefix(link, "mailto:") == 0) {-		sdhtml_escape(ob, link->data + 7, link->size - 7);+		houdini_escape_html(ob, link->data + 7, link->size - 7); 	} else {-		sdhtml_escape(ob, link->data, link->size);+		houdini_escape_html(ob, link->data, link->size); 	}  	BUFPUTSL(ob, "</a>");@@ -137,7 +106,7 @@ }  static void-rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)+rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque) { 	if (ob->size) bufputc(ob, '\n'); @@ -158,7 +127,7 @@ 					org++;  				if (cls) bufputc(ob, ' ');-				sdhtml_escape(ob, lang->data + org, i - org);+				houdini_escape_html(ob, lang->data + org, i - org); 			} 		} @@ -167,58 +136,13 @@ 		BUFPUTSL(ob, "<pre><code>");  	if (text)-		sdhtml_escape(ob, text->data, text->size);--	BUFPUTSL(ob, "</code></pre>\n");-}--/*- * GitHub style code block:- *- *		<pre lang="LANG"><code>- *		...- *		</pre></code>- *- * Unlike other parsers, we store the language identifier in the <pre>,- * and don't let the user generate custom classes.- *- * The language identifier in the <pre> block gets postprocessed and all- * the code inside gets syntax highlighted with Pygments. This is much safer- * than letting the user specify a CSS class for highlighting.- *- * Note that we only generate HTML for the first specifier.- * E.g.- *		~~~~ {.python .numbered}	=>	<pre lang="python"><code>- */-static void-rndr_blockcode_github(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)-{-	if (ob->size) bufputc(ob, '\n');--	if (lang && lang->size) {-		size_t i = 0;-		BUFPUTSL(ob, "<pre lang=\"");--		while (i < lang->size && !isspace(lang->data[i]))-			i++;--		if (lang->data[0] == '.')-			sdhtml_escape(ob, lang->data + 1, i - 1);-		else-			sdhtml_escape(ob, lang->data, i);--		BUFPUTSL(ob, "\"><code>");-	} else-		BUFPUTSL(ob, "<pre><code>");--	if (text)-		sdhtml_escape(ob, text->data, text->size);+		houdini_escape_html(ob, text->data, text->size);  	BUFPUTSL(ob, "</code></pre>\n"); }  static void-rndr_blockquote(struct buf *ob, struct buf *text, void *opaque)+rndr_blockquote(struct buf *ob, const struct buf *text, void *opaque) { 	if (ob->size) bufputc(ob, '\n'); 	BUFPUTSL(ob, "<blockquote>\n");@@ -227,16 +151,16 @@ }  static int-rndr_codespan(struct buf *ob, struct buf *text, void *opaque)+rndr_codespan(struct buf *ob, const struct buf *text, void *opaque) { 	BUFPUTSL(ob, "<code>");-	if (text) sdhtml_escape(ob, text->data, text->size);+	if (text) houdini_escape_html(ob, text->data, text->size); 	BUFPUTSL(ob, "</code>"); 	return 1; }  static int-rndr_strikethrough(struct buf *ob, struct buf *text, void *opaque)+rndr_strikethrough(struct buf *ob, const struct buf *text, void *opaque) { 	if (!text || !text->size) 		return 0;@@ -248,7 +172,7 @@ }  static int-rndr_double_emphasis(struct buf *ob, struct buf *text, void *opaque)+rndr_double_emphasis(struct buf *ob, const struct buf *text, void *opaque) { 	if (!text || !text->size) 		return 0;@@ -261,7 +185,7 @@ }  static int-rndr_emphasis(struct buf *ob, struct buf *text, void *opaque)+rndr_emphasis(struct buf *ob, const struct buf *text, void *opaque) { 	if (!text || !text->size) return 0; 	BUFPUTSL(ob, "<em>");@@ -273,16 +197,16 @@ static int rndr_linebreak(struct buf *ob, void *opaque) {-	struct html_renderopt *options = opaque;	+	struct html_renderopt *options = opaque; 	bufputs(ob, USE_XHTML(options) ? "<br/>\n" : "<br>\n"); 	return 1; }  static void-rndr_header(struct buf *ob, struct buf *text, int level, void *opaque)+rndr_header(struct buf *ob, const struct buf *text, int level, void *opaque) { 	struct html_renderopt *options = opaque;-	+ 	if (ob->size) 		bufputc(ob, '\n'); @@ -296,21 +220,21 @@ }  static int-rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque)+rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque) { 	struct html_renderopt *options = opaque;-	+ 	if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size)) 		return 0;  	BUFPUTSL(ob, "<a href=\"");  	if (link && link->size)-		sdhtml_escape(ob, link->data, link->size);+		houdini_escape_href(ob, link->data, link->size);  	if (title && title->size) { 		BUFPUTSL(ob, "\" title=\"");-		sdhtml_escape(ob, title->data, title->size);+		houdini_escape_html(ob, title->data, title->size); 	}  	if (options->link_attributes) {@@ -327,7 +251,7 @@ }  static void-rndr_list(struct buf *ob, struct buf *text, int flags, void *opaque)+rndr_list(struct buf *ob, const struct buf *text, int flags, void *opaque) { 	if (ob->size) bufputc(ob, '\n'); 	bufput(ob, flags & MKD_LIST_ORDERED ? "<ol>\n" : "<ul>\n", 5);@@ -336,18 +260,21 @@ }  static void-rndr_listitem(struct buf *ob, struct buf *text, int flags, void *opaque)+rndr_listitem(struct buf *ob, const struct buf *text, int flags, void *opaque) { 	BUFPUTSL(ob, "<li>"); 	if (text) {-		while (text->size && text->data[text->size - 1] == '\n')-			text->size -= 1;-		bufput(ob, text->data, text->size); }+		size_t size = text->size;+		while (size && text->data[size - 1] == '\n')+			size--;++		bufput(ob, text->data, size);+	} 	BUFPUTSL(ob, "</li>\n"); }  static void-rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)+rndr_paragraph(struct buf *ob, const struct buf *text, void *opaque) { 	struct html_renderopt *options = opaque; 	size_t i = 0;@@ -379,7 +306,7 @@ 			 */ 			if (i >= text->size - 1) 				break;-			+ 			rndr_linebreak(ob, opaque); 			i++; 		}@@ -390,7 +317,7 @@ }  static void-rndr_raw_block(struct buf *ob, struct buf *text, void *opaque)+rndr_raw_block(struct buf *ob, const struct buf *text, void *opaque) { 	size_t org, sz; 	if (!text) return;@@ -405,7 +332,7 @@ }  static int-rndr_triple_emphasis(struct buf *ob, struct buf *text, void *opaque)+rndr_triple_emphasis(struct buf *ob, const struct buf *text, void *opaque) { 	if (!text || !text->size) return 0; 	BUFPUTSL(ob, "<strong><em>");@@ -417,44 +344,50 @@ static void rndr_hrule(struct buf *ob, void *opaque) {-	struct html_renderopt *options = opaque;	+	struct html_renderopt *options = opaque; 	if (ob->size) bufputc(ob, '\n'); 	bufputs(ob, USE_XHTML(options) ? "<hr/>\n" : "<hr>\n"); }  static int-rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque)+rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque) {-	struct html_renderopt *options = opaque;	+	struct html_renderopt *options = opaque; 	if (!link || !link->size) return 0;+ 	BUFPUTSL(ob, "<img src=\"");-	sdhtml_escape(ob, link->data, link->size);+	houdini_escape_href(ob, link->data, link->size); 	BUFPUTSL(ob, "\" alt=\"");+ 	if (alt && alt->size)-		sdhtml_escape(ob, alt->data, alt->size);+		houdini_escape_html(ob, alt->data, alt->size);+ 	if (title && title->size) { 		BUFPUTSL(ob, "\" title=\"");-		sdhtml_escape(ob, title->data, title->size); }+		houdini_escape_html(ob, title->data, title->size); }  	bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">"); 	return 1; }  static int-rndr_raw_html(struct buf *ob, struct buf *text, void *opaque)+rndr_raw_html(struct buf *ob, const struct buf *text, void *opaque) {-	struct html_renderopt *options = opaque;	+	struct html_renderopt *options = opaque;  	if ((options->flags & HTML_SKIP_HTML) != 0) 		return 1; -	if ((options->flags & HTML_SKIP_STYLE) != 0 && sdhtml_tag(text->data, text->size, "style"))+	if ((options->flags & HTML_SKIP_STYLE) != 0 &&+		sdhtml_is_tag(text->data, text->size, "style")) 		return 1; -	if ((options->flags & HTML_SKIP_LINKS) != 0 && sdhtml_tag(text->data, text->size, "a"))+	if ((options->flags & HTML_SKIP_LINKS) != 0 &&+		sdhtml_is_tag(text->data, text->size, "a")) 		return 1; -	if ((options->flags & HTML_SKIP_IMAGES) != 0 && sdhtml_tag(text->data, text->size, "img"))+	if ((options->flags & HTML_SKIP_IMAGES) != 0 &&+		sdhtml_is_tag(text->data, text->size, "img")) 		return 1;  	bufput(ob, text->data, text->size);@@ -462,7 +395,7 @@ }  static void-rndr_table(struct buf *ob, struct buf *header, struct buf *body, void *opaque)+rndr_table(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque) { 	if (ob->size) bufputc(ob, '\n'); 	BUFPUTSL(ob, "<table><thead>\n");@@ -475,7 +408,7 @@ }  static void-rndr_tablerow(struct buf *ob, struct buf *text, void *opaque)+rndr_tablerow(struct buf *ob, const struct buf *text, void *opaque) { 	BUFPUTSL(ob, "<tr>\n"); 	if (text)@@ -484,7 +417,7 @@ }  static void-rndr_tablecell(struct buf *ob, struct buf *text, int flags, void *opaque)+rndr_tablecell(struct buf *ob, const struct buf *text, int flags, void *opaque) { 	if (flags & MKD_TABLE_HEADER) { 		BUFPUTSL(ob, "<th");@@ -520,7 +453,7 @@ }  static int-rndr_superscript(struct buf *ob, struct buf *text, void *opaque)+rndr_superscript(struct buf *ob, const struct buf *text, void *opaque) { 	if (!text || !text->size) return 0; 	BUFPUTSL(ob, "<sup>");@@ -530,14 +463,14 @@ }  static void-rndr_normal_text(struct buf *ob, struct buf *text, void *opaque)+rndr_normal_text(struct buf *ob, const struct buf *text, void *opaque) { 	if (text)-		sdhtml_escape(ob, text->data, text->size);+		houdini_escape_html(ob, text->data, text->size); }  static void-toc_header(struct buf *ob, struct buf *text, int level, void *opaque)+toc_header(struct buf *ob, const struct buf *text, int level, void *opaque) { 	struct html_renderopt *options = opaque; @@ -667,7 +600,4 @@  	if (render_flags & HTML_SKIP_HTML) 		callbacks->blockhtml = NULL;--	if (render_flags & HTML_GITHUB_BLOCKCODE)-		callbacks->blockcode = rndr_blockcode_github; }
cbits/html.h view
@@ -30,7 +30,7 @@ 	unsigned int flags;  	/* extra callbacks */-	void (*link_attributes)(struct buf *ob, struct buf *url, void *self);+	void (*link_attributes)(struct buf *ob, const struct buf *url, void *self); };  typedef enum {@@ -38,12 +38,11 @@ 	HTML_SKIP_STYLE = (1 << 1), 	HTML_SKIP_IMAGES = (1 << 2), 	HTML_SKIP_LINKS = (1 << 3),-	HTML_EXPAND_TABS = (1 << 5),-	HTML_SAFELINK = (1 << 7),-	HTML_TOC = (1 << 8),-	HTML_HARD_WRAP = (1 << 9),-	HTML_GITHUB_BLOCKCODE = (1 << 10),-	HTML_USE_XHTML = (1 << 11),+	HTML_EXPAND_TABS = (1 << 4),+	HTML_SAFELINK = (1 << 5),+	HTML_TOC = (1 << 6),+	HTML_HARD_WRAP = (1 << 7),+	HTML_USE_XHTML = (1 << 8), } html_render_mode;  typedef enum {@@ -52,11 +51,8 @@ 	HTML_TAG_CLOSE, } html_tag; -void-sdhtml_escape(struct buf *ob, const char *src, size_t size);- int-sdhtml_tag(const char *tag_data, size_t tag_size, const char *tagname);+sdhtml_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname);  extern void sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, unsigned int render_flags);@@ -65,7 +61,7 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr);  extern void-sdhtml_smartypants(struct buf *ob, struct buf *text);+sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size);  #endif 
cbits/html_smartypants.c view
@@ -27,19 +27,19 @@ 	int in_dquote; }; -static size_t smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__dquote(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__amp(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__period(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__parens(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__squote(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);-static size_t smartypants_cb__escape(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);+static size_t smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__dquote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__amp(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__period(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__parens(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);+static size_t smartypants_cb__escape(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);  static size_t (*smartypants_cb_ptrs[])-	(struct buf *, struct smartypants_data *, char, const char *, size_t) = +	(struct buf *, struct smartypants_data *, uint8_t, const uint8_t *, size_t) = { 	NULL,					/* 0 */ 	smartypants_cb__dash,	/* 1 */@@ -54,7 +54,7 @@ 	smartypants_cb__escape, /* 10 */ }; -static const char smartypants_cb_chars[] = {+static const uint8_t smartypants_cb_chars[] = { 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 	0, 0, 4, 0, 0, 0, 5, 3, 2, 0, 0, 0, 0, 1, 6, 0,@@ -74,13 +74,13 @@ };  static inline int-word_boundary(char c)+word_boundary(uint8_t c) { 	return c == 0 || isspace(c) || ispunct(c); }  static int-smartypants_quotes(struct buf *ob, char previous_char, char next_char, char quote, int *is_open)+smartypants_quotes(struct buf *ob, uint8_t previous_char, uint8_t next_char, uint8_t quote, int *is_open) { 	char ent[8]; @@ -97,10 +97,10 @@ }  static size_t-smartypants_cb__squote(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (size >= 2) {-		char t1 = tolower(text[1]);+		uint8_t t1 = tolower(text[1]);  		if (t1 == '\'') { 			if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote))@@ -114,7 +114,7 @@ 		}  		if (size >= 3) {-			char t2 = tolower(text[2]);+			uint8_t t2 = tolower(text[2]);  			if (((t1 == 'r' && t2 == 'e') || 				(t1 == 'l' && t2 == 'l') ||@@ -134,11 +134,11 @@ }  static size_t-smartypants_cb__parens(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__parens(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (size >= 3) {-		char t1 = tolower(text[1]);-		char t2 = tolower(text[2]);+		uint8_t t1 = tolower(text[1]);+		uint8_t t2 = tolower(text[2]);  		if (t1 == 'c' && t2 == ')') { 			BUFPUTSL(ob, "&copy;");@@ -155,13 +155,13 @@ 			return 3; 		} 	}-	+ 	bufputc(ob, text[0]); 	return 0; }  static size_t-smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (size >= 3 && text[1] == '-' && text[2] == '-') { 		BUFPUTSL(ob, "&mdash;");@@ -178,7 +178,7 @@ }  static size_t-smartypants_cb__amp(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__amp(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (size >= 6 && memcmp(text, "&quot;", 6) == 0) { 		if (smartypants_quotes(ob, previous_char, size >= 7 ? text[6] : 0, 'd', &smrt->in_dquote))@@ -193,7 +193,7 @@ }  static size_t-smartypants_cb__period(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__period(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (size >= 3 && text[1] == '.' && text[2] == '.') { 		BUFPUTSL(ob, "&hellip;");@@ -210,7 +210,7 @@ }  static size_t-smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (size >= 2 && text[1] == '`') { 		if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote))@@ -221,7 +221,7 @@ }  static size_t-smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (word_boundary(previous_char) && size >= 3) { 		if (text[0] == '1' && text[1] == '/' && text[2] == '2') {@@ -253,7 +253,7 @@ }  static size_t-smartypants_cb__dquote(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__dquote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (!smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 'd', &smrt->in_dquote)) 		BUFPUTSL(ob, "&quot;");@@ -262,7 +262,7 @@ }  static size_t-smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	static const char *skip_tags[] = {"pre", "code", "kbd", "script"}; 	static const size_t skip_tags_count = 4;@@ -273,7 +273,7 @@ 		i++;  	for (tag = 0; tag < skip_tags_count; ++tag) {-		if (sdhtml_tag(text, size, skip_tags[tag]) == HTML_TAG_OPEN)+		if (sdhtml_is_tag(text, size, skip_tags[tag]) == HTML_TAG_OPEN) 			break; 	} @@ -285,7 +285,7 @@ 			if (i == size) 				break; -			if (sdhtml_tag(text + i, size - i, skip_tags[tag]) == HTML_TAG_CLOSE)+			if (sdhtml_is_tag(text + i, size - i, skip_tags[tag]) == HTML_TAG_CLOSE) 				break;  			i++;@@ -300,7 +300,7 @@ }  static size_t-smartypants_cb__escape(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)+smartypants_cb__escape(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) { 	if (size < 2) 		return 0;@@ -323,9 +323,9 @@  #if 0 static struct {-    char c0;-    const char *pattern;-    const char *entity;+    uint8_t c0;+    const uint8_t *pattern;+    const uint8_t *entity;     int skip; } smartypants_subs[] = {     { '\'', "'s>",      "&rsquo;",  0 },@@ -352,7 +352,7 @@ #endif  void-sdhtml_smartypants(struct buf *ob, struct buf *text)+sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size) { 	size_t i; 	struct smartypants_data smrt = {0, 0};@@ -360,22 +360,22 @@ 	if (!text) 		return; -	bufgrow(ob, text->size);+	bufgrow(ob, size); -	for (i = 0; i < text->size; ++i) {+	for (i = 0; i < size; ++i) { 		size_t org;-		char action = 0;+		uint8_t action = 0;  		org = i;-		while (i < text->size && (action = smartypants_cb_chars[(unsigned char)text->data[i]]) == 0)+		while (i < size && (action = smartypants_cb_chars[text[i]]) == 0) 			i++;  		if (i > org)-			bufput(ob, text->data + org, i - org);+			bufput(ob, text + org, i - org); -		if (i < text->size) {+		if (i < size) { 			i += smartypants_cb_ptrs[(int)action]-				(ob, &smrt, i ? text->data[i - 1] : 0, text->data + i, text->size - i);+				(ob, &smrt, i ? text[i - 1] : 0, text + i, size - i); 		} 	} }
cbits/markdown.c view
@@ -45,8 +45,8 @@ struct link_ref { 	unsigned int id; -	struct buf link;-	struct buf title;+	struct buf *link;+	struct buf *title;  	struct link_ref *next; };@@ -57,19 +57,19 @@ /*   offset is the number of valid chars before data */ struct sd_markdown; typedef size_t-(*char_trigger)(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);+(*char_trigger)(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size); -static size_t char_emphasis(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_linebreak(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_codespan(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_escape(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_entity(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_langle_tag(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_autolink_url(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_autolink_email(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_autolink_www(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_link(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);-static size_t char_superscript(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size);+static size_t char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_linebreak(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_codespan(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_entity(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_langle_tag(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_autolink_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_autolink_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);+static size_t char_superscript(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);  enum markdown_char_t { 	MD_CHAR_NONE = 0,@@ -107,7 +107,7 @@ 	void *opaque;  	struct link_ref *refs[REF_TABLE_SIZE];-	char active_char[256];+	uint8_t active_char[256]; 	struct stack work_bufs[2]; 	unsigned int ext_flags; 	size_t max_nesting;@@ -163,7 +163,7 @@ }  static unsigned int-hash_link_ref(char *link_ref, size_t length)+hash_link_ref(const uint8_t *link_ref, size_t length) { 	size_t i; 	unsigned int hash = 0;@@ -174,31 +174,25 @@ 	return hash; } -static void add_link_ref(+static struct link_ref *+add_link_ref( 	struct link_ref **references,-	char *name, size_t name_size,-	char *link, size_t link_size,-	char *title, size_t title_size)+	const uint8_t *name, size_t name_size) { 	struct link_ref *ref = calloc(1, sizeof(struct link_ref));  	if (!ref)-		return;+		return NULL;  	ref->id = hash_link_ref(name, name_size); 	ref->next = references[ref->id % REF_TABLE_SIZE]; -	ref->link.data = link;-	ref->link.size = link_size;--	ref->title.data = title;-	ref->title.size = title_size;- 	references[ref->id % REF_TABLE_SIZE] = ref;+	return ref; }  static struct link_ref *-find_link_ref(struct link_ref **references, char *name, size_t length)+find_link_ref(struct link_ref **references, uint8_t *name, size_t length) { 	unsigned int hash = hash_link_ref(name, length); 	struct link_ref *ref = NULL;@@ -225,11 +219,32 @@ 		struct link_ref *next;  		while (r) {-			next = r->next; free(r); r = next;+			next = r->next;+			bufrelease(r->link);+			bufrelease(r->title);+			free(r);+			r = next; 		} 	} } +/*+ * Check whether a char is a Markdown space.++ * Right now we only consider spaces the actual+ * space and a newline: tabs and carriage returns+ * are filtered out during the preprocessing phase.+ *+ * If we wanted to actually be UTF-8 compliant, we+ * should instead extract an Unicode codepoint from+ * this character and check for space properties.+ */+static inline int+_isspace(int c)+{+	return c == ' ' || c == '\n';+}+ /****************************  * INLINE PARSING FUNCTIONS *  ****************************/@@ -237,7 +252,7 @@ /* is_mail_autolink • looks for the address part of a mail autolink and '>' */ /* this is less strict than the original markdown e-mail address matching */ static size_t-is_mail_autolink(char *data, size_t size)+is_mail_autolink(uint8_t *data, size_t size) { 	size_t i = 0, nb = 0; @@ -268,7 +283,7 @@  /* tag_length • returns the length of the given tag, or 0 is it's not valid */ static size_t-tag_length(char *data, size_t size, enum mkd_autolink *autolink)+tag_length(uint8_t *data, size_t size, enum mkd_autolink *autolink) { 	size_t i, j; @@ -311,7 +326,8 @@ 		while (i < size) { 			if (data[i] == '\\') i += 2; 			else if (data[i] == '>' || data[i] == '\'' ||-					data[i] == '"' || isspace(data[i])) break;+					data[i] == '"' || data[i] == ' ' || data[i] == '\n')+					break; 			else i++; 		} @@ -329,19 +345,19 @@  /* parse_inline • parses inline markdown elements */ static void-parse_inline(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size)+parse_inline(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t i = 0, end = 0;-	char action = 0;-	struct buf work = { 0, 0, 0, 0, 0 };+	uint8_t action = 0;+	struct buf work = { 0, 0, 0, 0 };  	if (rndr->work_bufs[BUFFER_SPAN].size +-		rndr->work_bufs[BUFFER_BLOCK].size > (int)rndr->max_nesting)+		rndr->work_bufs[BUFFER_BLOCK].size > rndr->max_nesting) 		return;  	while (i < size) { 		/* copying inactive chars into the output */-		while (end < size && (action = rndr->active_char[(unsigned char)data[end]]) == 0) {+		while (end < size && (action = rndr->active_char[data[end]]) == 0) { 			end++; 		} @@ -367,9 +383,9 @@ 	} } -/* find_emph_char • looks for the next emph char, skipping other constructs */+/* find_emph_char • looks for the next emph uint8_t, skipping other constructs */ static size_t-find_emph_char(char *data, size_t size, char c)+find_emph_char(uint8_t *data, size_t size, uint8_t c) { 	size_t i = 1; @@ -414,7 +430,7 @@ 		/* skipping a link */ 		else if (data[i] == '[') { 			size_t tmp_i = 0;-			char cc;+			uint8_t cc;  			i++; 			while (i < size && data[i] != ']') {@@ -423,7 +439,7 @@ 			}  			i++;-			while (i < size && (data[i] == ' ' || data[i] == '\t' || data[i] == '\n'))+			while (i < size && (data[i] == ' ' || data[i] == '\n')) 				i++;  			if (i >= size)@@ -462,7 +478,7 @@ /* parse_emph1 • parsing single emphase */ /* closed by a symbol not preceded by whitespace and not followed by symbol */ static size_t-parse_emph1(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, char c)+parse_emph1(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, uint8_t c) { 	size_t i = 0, len; 	struct buf *work = 0;@@ -479,10 +495,10 @@ 		i += len; 		if (i >= size) return 0; -		if (data[i] == c && !isspace(data[i - 1])) {+		if (data[i] == c && !_isspace(data[i - 1])) {  			if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {-				if (!(i + 1 == size || isspace(data[i + 1]) || ispunct(data[i + 1])))+				if (!(i + 1 == size || _isspace(data[i + 1]) || ispunct(data[i + 1]))) 					continue; 			} @@ -499,9 +515,9 @@  /* parse_emph2 • parsing single emphase */ static size_t-parse_emph2(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, char c)+parse_emph2(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, uint8_t c) {-	int (*render_method)(struct buf *ob, struct buf *text, void *opaque);+	int (*render_method)(struct buf *ob, const struct buf *text, void *opaque); 	size_t i = 0, len; 	struct buf *work = 0; 	int r;@@ -516,7 +532,7 @@ 		if (!len) return 0; 		i += len; -		if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !isspace(data[i - 1])) {+		if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !_isspace(data[i - 1])) { 			work = rndr_newbuf(rndr, BUFFER_SPAN); 			parse_inline(work, rndr, data, i); 			r = render_method(ob, work, rndr->opaque);@@ -531,7 +547,7 @@ /* parse_emph3 • parsing single emphase */ /* finds the first closing tag, and delegates to the other emph */ static size_t-parse_emph3(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, char c)+parse_emph3(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, uint8_t c) { 	size_t i = 0, len; 	int r;@@ -542,7 +558,7 @@ 		i += len;  		/* skip whitespace preceded symbols */-		if (data[i] != c || isspace(data[i - 1]))+		if (data[i] != c || _isspace(data[i - 1])) 			continue;  		if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && rndr->cb.triple_emphasis) {@@ -572,29 +588,29 @@  /* char_emphasis • single and double emphasis parsing */ static size_t-char_emphasis(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) {-	char c = data[0];+	uint8_t c = data[0]; 	size_t ret;  	if (size > 2 && data[1] != c) { 		/* whitespace cannot follow an opening emphasis; 		 * strikethrough only takes two characters '~~' */-		if (c == '~' || isspace(data[1]) || (ret = parse_emph1(ob, rndr, data + 1, size - 1, c)) == 0)+		if (c == '~' || _isspace(data[1]) || (ret = parse_emph1(ob, rndr, data + 1, size - 1, c)) == 0) 			return 0;  		return ret + 1; 	}  	if (size > 3 && data[1] == c && data[2] != c) {-		if (isspace(data[2]) || (ret = parse_emph2(ob, rndr, data + 2, size - 2, c)) == 0)+		if (_isspace(data[2]) || (ret = parse_emph2(ob, rndr, data + 2, size - 2, c)) == 0) 			return 0;  		return ret + 2; 	}  	if (size > 4 && data[1] == c && data[2] == c && data[3] != c) {-		if (c == '~' || isspace(data[3]) || (ret = parse_emph3(ob, rndr, data + 3, size - 3, c)) == 0)+		if (c == '~' || _isspace(data[3]) || (ret = parse_emph3(ob, rndr, data + 3, size - 3, c)) == 0) 			return 0;  		return ret + 3;@@ -606,7 +622,7 @@  /* char_linebreak • '\n' preceded by two spaces (assuming linebreak != 0) */ static size_t-char_linebreak(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_linebreak(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	if (offset < 2 || data[-1] != ' ' || data[-2] != ' ') 		return 0;@@ -621,7 +637,7 @@  /* char_codespan • '`' parsing a code span (assuming codespan != 0) */ static size_t-char_codespan(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_codespan(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	size_t end, nb = 0, i, f_begin, f_end; @@ -641,16 +657,16 @@  	/* trimming outside whitespaces */ 	f_begin = nb;-	while (f_begin < end && (data[f_begin] == ' ' || data[f_begin] == '\t'))+	while (f_begin < end && data[f_begin] == ' ') 		f_begin++;  	f_end = end - nb;-	while (f_end > nb && (data[f_end-1] == ' ' || data[f_end-1] == '\t'))+	while (f_end > nb && data[f_end-1] == ' ') 		f_end--;  	/* real code span */ 	if (f_begin < f_end) {-		struct buf work = { data + f_begin, f_end - f_begin, 0, 0, 0 };+		struct buf work = { data + f_begin, f_end - f_begin, 0, 0 }; 		if (!rndr->cb.codespan(ob, &work, rndr->opaque)) 			end = 0; 	} else {@@ -664,10 +680,10 @@  /* char_escape • '\\' backslash escape */ static size_t-char_escape(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>";-	struct buf work = { 0, 0, 0, 0, 0 };+	struct buf work = { 0, 0, 0, 0 };  	if (size > 1) { 		if (strchr(escape_chars, data[1]) == NULL)@@ -687,10 +703,10 @@ /* 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(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_entity(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	size_t end = 1;-	struct buf work;+	struct buf work = { 0, 0, 0, 0 };  	if (end < size && data[end] == '#') 		end++;@@ -715,11 +731,11 @@  /* char_langle_tag • '<' when tags or autolinks are allowed */ static size_t-char_langle_tag(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_langle_tag(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	enum mkd_autolink altype = MKDA_NOT_AUTOLINK; 	size_t end = tag_length(data, size, &altype);-	struct buf work = { data, end, 0, 0, 0 };+	struct buf work = { data, end, 0, 0 }; 	int ret = 0;  	if (end > 2) {@@ -740,7 +756,7 @@ }  static size_t-char_autolink_www(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_autolink_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	struct buf *link, *link_url; 	size_t link_len, rewind;@@ -765,7 +781,7 @@ }  static size_t-char_autolink_email(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_autolink_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	struct buf *link; 	size_t link_len, rewind;@@ -785,7 +801,7 @@ }  static size_t-char_autolink_url(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	struct buf *link; 	size_t link_len, rewind;@@ -806,7 +822,7 @@  /* char_link • '[': parsing a link or an image */ static size_t-char_link(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	int is_img = (offset && data[-1] == '!'), level; 	size_t i = 1, txt_e, link_b = 0, link_e = 0, title_b = 0, title_e = 0;@@ -847,7 +863,7 @@  	/* skip any amount of whitespace or newline */ 	/* (this is much more laxist than original markdown syntax) */-	while (i < size && isspace(data[i]))+	while (i < size && _isspace(data[i])) 		i++;  	/* inline style link */@@ -855,7 +871,7 @@ 		/* skipping initial whitespace */ 		i++; -		while (i < size && isspace(data[i]))+		while (i < size && _isspace(data[i])) 			i++;  		link_b = i;@@ -885,7 +901,7 @@  			/* skipping whitespaces after title */ 			title_e = i - 1;-			while (title_e > title_b && isspace(data[title_e]))+			while (title_e > title_b && _isspace(data[title_e])) 				title_e--;  			/* checking for closing quote presence */@@ -896,7 +912,7 @@ 		}  		/* remove whitespace at the end of the link */-		while (link_e > link_b && isspace(data[link_e - 1]))+		while (link_e > link_b && _isspace(data[link_e - 1])) 			link_e--;  		/* remove optional angle brackets around the link */@@ -919,7 +935,7 @@  	/* reference style link */ 	else if (i < size && data[i] == '[') {-		struct buf id = { 0, 0, 0, 0, 0 };+		struct buf id = { 0, 0, 0, 0 }; 		struct link_ref *lr;  		/* looking for the id */@@ -958,15 +974,14 @@ 			goto cleanup;  		/* keeping link and title from link_ref */-		link = &lr->link;-		if (lr->title.size)-			title = &lr->title;+		link = lr->link;+		title = lr->title; 		i++; 	}  	/* shortcut reference style link */ 	else {-		struct buf id = { 0, 0, 0, 0, 0 };+		struct buf id = { 0, 0, 0, 0 }; 		struct link_ref *lr;  		/* crafting the id */@@ -994,9 +1009,8 @@ 			goto cleanup;  		/* keeping link and title from link_ref */-		link = &lr->link;-		if (lr->title.size)-			title = &lr->title;+		link = lr->link;+		title = lr->title;  		/* rewinding the whitespace */ 		i = txt_e + 1;@@ -1031,7 +1045,7 @@ }  static size_t-char_superscript(struct buf *ob, struct sd_markdown *rndr, char *data, size_t offset, size_t size)+char_superscript(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { 	size_t sup_start, sup_len; 	struct buf *sup;@@ -1053,7 +1067,7 @@ 	} else { 		sup_start = sup_len = 1; -		while (sup_len < size && !isspace(data[sup_len]))+		while (sup_len < size && !_isspace(data[sup_len])) 			sup_len++; 	} @@ -1074,20 +1088,23 @@  /* is_empty • returns the line length when it is empty, 0 otherwise */ static size_t-is_empty(char *data, size_t size)+is_empty(uint8_t *data, size_t size) { 	size_t i;+ 	for (i = 0; i < size && data[i] != '\n'; i++)-		if (data[i] != ' ' && data[i] != '\t') return 0;+		if (data[i] != ' ')+			return 0;+ 	return i + 1; }  /* is_hrule • returns whether a line is a horizontal rule */ static int-is_hrule(char *data, size_t size)+is_hrule(uint8_t *data, size_t size) { 	size_t i = 0, n = 0;-	char c;+	uint8_t c;  	/* skipping initial spaces */ 	if (size < 3) return 0;@@ -1095,7 +1112,7 @@ 	if (data[1] == ' ') { i++; 	if (data[2] == ' ') { i++; } } } -	/* looking at the hrule char */+	/* looking at the hrule uint8_t */ 	if (i + 2 >= size 	|| (data[i] != '*' && data[i] != '-' && data[i] != '_')) 		return 0;@@ -1104,19 +1121,21 @@ 	/* the whole line must be the char or whitespace */ 	while (i < size && data[i] != '\n') { 		if (data[i] == c) n++;-		else if (data[i] != ' ' && data[i] != '\t')+		else if (data[i] != ' ') 			return 0;-		i++; } +		i++;+	}+ 	return n >= 3; }  /* check if a line is a code fence; return its size if it is */ static size_t-is_codefence(char *data, size_t size, struct buf *syntax)+is_codefence(uint8_t *data, size_t size, struct buf *syntax) { 	size_t i = 0, n = 0;-	char c;+	uint8_t c;  	/* skipping initial spaces */ 	if (size < 3) return 0;@@ -1124,13 +1143,13 @@ 	if (data[1] == ' ') { i++; 	if (data[2] == ' ') { i++; } } } -	/* looking at the hrule char */+	/* looking at the hrule uint8_t */ 	if (i + 2 >= size || !(data[i] == '~' || data[i] == '`')) 		return 0;  	c = data[i]; -	/* the whole line must be the char or whitespace */+	/* the whole line must be the uint8_t or whitespace */ 	while (i < size && data[i] == c) { 		n++; i++; 	}@@ -1141,7 +1160,7 @@ 	if (syntax != NULL) { 		size_t syn = 0; -		while (i < size && (data[i] == ' ' || data[i] == '\t'))+		while (i < size && data[i] == ' ') 			i++;  		syntax->data = data + i;@@ -1158,16 +1177,16 @@  			/* strip all whitespace at the beginning and the end 			 * of the {} block */-			while (syn > 0 && isspace(syntax->data[0])) {+			while (syn > 0 && _isspace(syntax->data[0])) { 				syntax->data++; syn--; 			} -			while (syn > 0 && isspace(syntax->data[syn - 1]))+			while (syn > 0 && _isspace(syntax->data[syn - 1])) 				syn--;  			i++; 		} else {-			while (i < size && !isspace(data[i])) {+			while (i < size && !_isspace(data[i])) { 				syn++; i++; 			} 		}@@ -1176,7 +1195,7 @@ 	}  	while (i < size && data[i] != '\n') {-		if (!isspace(data[i]))+		if (!_isspace(data[i])) 			return 0;  		i++;@@ -1187,7 +1206,7 @@  /* is_atxheader • returns whether the line is a hash-prefixed header */ static int-is_atxheader(struct sd_markdown *rndr, char *data, size_t size)+is_atxheader(struct sd_markdown *rndr, uint8_t *data, size_t size) { 	if (data[0] != '#') 		return 0;@@ -1198,7 +1217,7 @@ 		while (level < size && level < 6 && data[level] == '#') 			level++; -		if (level < size && data[level] != ' ' && data[level] != '\t')+		if (level < size && data[level] != ' ') 			return 0; 	} @@ -1207,30 +1226,30 @@  /* is_headerline • returns whether the line is a setext-style hdr underline */ static int-is_headerline(char *data, size_t size)+is_headerline(uint8_t *data, size_t size) { 	size_t i = 0;  	/* test of level 1 header */ 	if (data[i] == '=') { 		for (i = 1; i < size && data[i] == '='; i++);-		while (i < size && (data[i] == ' ' || data[i] == '\t')) i++;+		while (i < size && data[i] == ' ') i++; 		return (i >= size || data[i] == '\n') ? 1 : 0; }  	/* test of level 2 header */ 	if (data[i] == '-') { 		for (i = 1; i < size && data[i] == '-'; i++);-		while (i < size && (data[i] == ' ' || data[i] == '\t')) i++;+		while (i < size && data[i] == ' ') i++; 		return (i >= size || data[i] == '\n') ? 2 : 0; }  	return 0; }  static int-is_next_headerline(char *data, size_t size)+is_next_headerline(uint8_t *data, size_t size) { 	size_t i = 0;-	+ 	while (i < size && data[i] != '\n') 		i++; @@ -1242,32 +1261,36 @@  /* prefix_quote • returns blockquote prefix length */ static size_t-prefix_quote(char *data, size_t size)+prefix_quote(uint8_t *data, size_t size) { 	size_t i = 0; 	if (i < size && data[i] == ' ') i++; 	if (i < size && data[i] == ' ') i++; 	if (i < size && data[i] == ' ') i++;+ 	if (i < size && data[i] == '>') {-		if (i + 1 < size && (data[i + 1] == ' ' || data[i+1] == '\t'))+		if (i + 1 < size && data[i + 1] == ' ') 			return i + 2;-		else return i + 1; }-	else return 0;++		return i + 1;+	}++	return 0; }  /* prefix_code • returns prefix length for block code*/ static size_t-prefix_code(char *data, size_t size)+prefix_code(uint8_t *data, size_t size) {-	if (size > 0 && data[0] == '\t') return 1; 	if (size > 3 && data[0] == ' ' && data[1] == ' '-			&& data[2] == ' ' && data[3] == ' ') return 4;+		&& data[2] == ' ' && data[3] == ' ') return 4;+ 	return 0; }  /* prefix_oli • returns ordered list item prefix */ static size_t-prefix_oli(char *data, size_t size)+prefix_oli(uint8_t *data, size_t size) { 	size_t i = 0; @@ -1281,9 +1304,7 @@ 	while (i < size && data[i] >= '0' && data[i] <= '9') 		i++; -	if (i + 1 >= size ||-		data[i] != '.' ||-		(data[i + 1] != ' ' && data[i + 1] != '\t'))+	if (i + 1 >= size || data[i] != '.' || data[i + 1] != ' ') 		return 0;  	if (is_next_headerline(data + i, size - i))@@ -1294,7 +1315,7 @@  /* prefix_uli • returns ordered list item prefix */ static size_t-prefix_uli(char *data, size_t size)+prefix_uli(uint8_t *data, size_t size) { 	size_t i = 0; @@ -1302,9 +1323,9 @@ 	if (i < size && data[i] == ' ') i++; 	if (i < size && data[i] == ' ') i++; -	if (i + 1 >= size || +	if (i + 1 >= size || 		(data[i] != '*' && data[i] != '+' && data[i] != '-') ||-		(data[i + 1] != ' ' && data[i + 1] != '\t'))+		data[i + 1] != ' ') 		return 0;  	if (is_next_headerline(data + i, size - i))@@ -1314,17 +1335,17 @@ }  -/* parse_block • parsing of one block, returning next char to parse */+/* parse_block • parsing of one block, returning next uint8_t to parse */ static void parse_block(struct buf *ob, struct sd_markdown *rndr,-			char *data, size_t size);+			uint8_t *data, size_t size);   /* parse_blockquote • handles parsing of a blockquote fragment */ static size_t-parse_blockquote(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size)+parse_blockquote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t beg, end = 0, pre, work_size = 0;-	char *work_data = 0;+	uint8_t *work_data = 0; 	struct buf *out = 0;  	out = rndr_newbuf(rndr, BUFFER_BLOCK);@@ -1362,15 +1383,15 @@ }  static size_t-parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, int do_render);+parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render);  /* parse_blockquote • handles parsing of a regular paragraph */ static size_t-parse_paragraph(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size)+parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t i = 0, end = 0; 	int level = 0;-	struct buf work = { data, 0, 0, 0, 0 }; /* volatile working buffer */+	struct buf work = { data, 0, 0, 0 };  	while (i < size) { 		for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;@@ -1446,11 +1467,11 @@  /* parse_fencedcode • handles parsing of a block-level code fragment */ static size_t-parse_fencedcode(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size)+parse_fencedcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t beg, end; 	struct buf *work = 0;-	struct buf lang = { 0, 0, 0, 0, 0 };+	struct buf lang = { 0, 0, 0, 0 };  	beg = is_codefence(data, size, &lang); 	if (beg == 0) return 0;@@ -1489,7 +1510,7 @@ }  static size_t-parse_blockcode(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size)+parse_blockcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t beg, end, pre; 	struct buf *work = 0;@@ -1532,7 +1553,7 @@ /* parse_listitem • parsing of a single list item */ /*	assuming initial prefix is already removed */ static size_t-parse_listitem(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, int *flags)+parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int *flags) { 	struct buf *work = 0, *inter = 0; 	size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;@@ -1582,7 +1603,6 @@ 			i++;  		pre = i;-		if (data[beg] == '\t') { i = 1; pre = 8; }  		/* checking for a new item */ 		if ((prefix_uli(data + beg + i, end - beg - i) &&@@ -1598,7 +1618,7 @@ 				sublist = work->size; 		} 		/* joining only indented stuff after empty lines */-		else if (in_empty && i < 4 && data[beg] != '\t') {+		else if (in_empty && i < 4) { 				*flags |= MKD_LI_END; 				break; 		}@@ -1648,7 +1668,7 @@  /* parse_list • parsing ordered or unordered list block */ static size_t-parse_list(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, int flags)+parse_list(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int flags) { 	struct buf *work = 0; 	size_t i = 0, j;@@ -1671,7 +1691,7 @@  /* parse_atxheader • parsing of atx-style headers */ static size_t-parse_atxheader(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size)+parse_atxheader(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t level = 0; 	size_t i, end, skip;@@ -1679,7 +1699,7 @@ 	while (level < size && level < 6 && data[level] == '#') 		level++; -	for (i = level; i < size && (data[i] == ' ' || data[i] == '\t'); i++);+	for (i = level; i < size && data[i] == ' '; i++);  	for (end = i; end < size && data[end] != '\n'; end++); 	skip = end;@@ -1687,7 +1707,7 @@ 	while (end && data[end - 1] == '#') 		end--; -	while (end && (data[end - 1] == ' ' || data[end - 1] == '\t'))+	while (end && data[end - 1] == ' ') 		end--;  	if (end > i) {@@ -1708,13 +1728,13 @@ /* htmlblock_end • checking end of HTML block : </tag>[ \t]*\n[ \t*]\n */ /*	returns the length on match, 0 otherwise */ static size_t-htmlblock_end(const char *tag, size_t tag_len, struct sd_markdown *rndr, char *data, size_t size)+htmlblock_end(const char *tag, size_t tag_len, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t i, w;  	/* checking if tag is a match */ 	if (tag_len + 3 >= size ||-		strncasecmp(data + 2, tag, tag_len) != 0 ||+		strncasecmp((char *)data + 2, tag, tag_len) != 0 || 		data[tag_len + 2] != '>') 		return 0; @@ -1740,17 +1760,24 @@  /* parse_htmlblock • parsing of inline HTML block */ static size_t-parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, int do_render)+parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render) { 	size_t i, j = 0;-	const char *curtag;+	const char *curtag = NULL; 	int found;-	struct buf work = { data, 0, 0, 0, 0 };+	struct buf work = { data, 0, 0, 0 };  	/* identification of the opening tag */-	if (size < 2 || data[0] != '<') return 0;-	curtag = find_block_tag(data + 1, size - 1);+	if (size < 2 || data[0] != '<')+		return 0; +	i = 1;+	while (i < size && data[i] != '>' && data[i] != ' ')+		i++;++	if (i < size && data[i] == '>')+		curtag = find_block_tag((char *)data + 1, i - 1);+ 	/* handling of special cases */ 	if (!curtag) { @@ -1835,7 +1862,7 @@ }  static void-parse_table_row(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, size_t columns, int *col_data)+parse_table_row(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, size_t columns, int *col_data) { 	size_t i = 0, col; 	struct buf *row_work = 0;@@ -1854,7 +1881,7 @@  		cell_work = rndr_newbuf(rndr, BUFFER_SPAN); -		while (i < size && isspace(data[i]))+		while (i < size && _isspace(data[i])) 			i++;  		cell_start = i;@@ -1864,7 +1891,7 @@  		cell_end = i - 1; -		while (cell_end > cell_start && isspace(data[cell_end]))+		while (cell_end > cell_start && _isspace(data[cell_end])) 			cell_end--;  		parse_inline(cell_work, rndr, data + cell_start, 1 + cell_end - cell_start);@@ -1875,7 +1902,7 @@ 	}  	for (; col < columns; ++col) {-		struct buf empty_cell = {0, 0, 0, 0, 0};+		struct buf empty_cell = { 0, 0, 0, 0 }; 		rndr->cb.table_cell(row_work, &empty_cell, col_data[col], rndr->opaque); 	} @@ -1885,7 +1912,7 @@ }  static size_t-parse_table_header(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size, size_t *columns, int **column_data)+parse_table_header(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, size_t *columns, int **column_data) { 	int pipes; 	size_t i = 0, col, header_end, under_end;@@ -1923,7 +1950,7 @@  		(*column_data)[col] |= MKD_TABLE_HEADER; -		while (i < under_end && (data[i] == ' ' || data[i] == '\t'))+		while (i < under_end && data[i] == ' ') 			i++;  		if (data[i] == ':') {@@ -1940,7 +1967,7 @@ 			dashes++; 		} -		while (i < under_end && (data[i] == ' ' || data[i] == '\t'))+		while (i < under_end && data[i] == ' ') 			i++;  		if (i < under_end && data[i] != '|')@@ -1960,7 +1987,7 @@ }  static size_t-parse_table(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size)+parse_table(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t i; @@ -2005,16 +2032,16 @@ 	return i; } -/* parse_block • parsing of one block, returning next char to parse */+/* parse_block • parsing of one block, returning next uint8_t to parse */ static void-parse_block(struct buf *ob, struct sd_markdown *rndr, char *data, size_t size)+parse_block(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) { 	size_t beg, end, i;-	char *txt_data;+	uint8_t *txt_data; 	beg = 0;  	if (rndr->work_bufs[BUFFER_SPAN].size +-		rndr->work_bufs[BUFFER_BLOCK].size > (int)rndr->max_nesting)+		rndr->work_bufs[BUFFER_BLOCK].size > rndr->max_nesting) 		return;  	while (beg < size) {@@ -2074,7 +2101,7 @@  /* is_ref • returns whether a line is a reference or not */ static int-is_ref(char *data, size_t beg, size_t end, size_t *last, struct link_ref **refs)+is_ref(const uint8_t *data, size_t beg, size_t end, size_t *last, struct link_ref **refs) { /*	int n; */ 	size_t i = 0;@@ -2104,23 +2131,27 @@ 	i++; 	if (i >= end || data[i] != ':') return 0; 	i++;-	while (i < end && (data[i] == ' ' || data[i] == '\t')) i++;+	while (i < end && data[i] == ' ') i++; 	if (i < end && (data[i] == '\n' || data[i] == '\r')) { 		i++; 		if (i < end && data[i] == '\r' && data[i - 1] == '\n') i++; }-	while (i < end && (data[i] == ' ' || data[i] == '\t')) i++;+	while (i < end && data[i] == ' ') i++; 	if (i >= end) return 0;  	/* link: whitespace-free sequence, optionally between angle brackets */-	if (data[i] == '<') i++;+	if (data[i] == '<')+		i++;+ 	link_offset = i;-	while (i < end && data[i] != ' ' && data[i] != '\t'-			&& data[i] != '\n' && data[i] != '\r') i++;++	while (i < end && data[i] != ' ' && data[i] != '\n' && data[i] != '\r')+		i++;+ 	if (data[i - 1] == '>') link_end = i - 1; 	else link_end = i;  	/* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */-	while (i < end && (data[i] == ' ' || data[i] == '\t')) i++;+	while (i < end && data[i] == ' ') i++; 	if (i < end && data[i] != '\n' && data[i] != '\r' 			&& data[i] != '\'' && data[i] != '"' && data[i] != '(') 		return 0;@@ -2133,7 +2164,7 @@ 	/* optional (space|tab)* spacer after a newline */ 	if (line_end) { 		i = line_end + 1;-		while (i < end && (data[i] == ' ' || data[i] == '\t')) i++; }+		while (i < end && data[i] == ' ') i++; }  	/* optional title: any non-newline sequence enclosed in '"() 					alone on its line */@@ -2149,7 +2180,7 @@ 		else	title_end = i; 		/* stepping back */ 		i -= 1;-		while (i > title_offset && (data[i] == ' ' || data[i] == '\t'))+		while (i > title_offset && data[i] == ' ') 			i -= 1; 		if (i > title_offset 		&& (data[i] == '\'' || data[i] == '"' || data[i] == ')')) {@@ -2164,27 +2195,23 @@ 		*last = line_end;  	if (refs) {-		char *title_str = NULL;-		size_t title_size = 0;+		struct link_ref *ref; +		ref = add_link_ref(refs, data + id_offset, id_end - id_offset);++		ref->link = bufnew(link_end - link_offset);+		bufput(ref->link, data + link_offset, link_end - link_offset);+ 		if (title_end > title_offset) {-			title_str = data + title_offset;-			title_size = title_end - title_offset;+			ref->title = bufnew(title_end - title_offset);+			bufput(ref->title, data + title_offset, title_end - title_offset); 		}--		add_link_ref( refs,-			data + id_offset, /* identifier */-			id_end - id_offset,-			data + link_offset, /* link url */-			link_end - link_offset,-			title_str, /* title (optional) */-			title_size); 	}  	return 1; } -static void expand_tabs(struct buf *ob, const char *line, size_t size)+static void expand_tabs(struct buf *ob, const uint8_t *line, size_t size) { 	size_t  i = 0, tab = 0; @@ -2273,7 +2300,7 @@ }  void-sd_markdown_render(struct buf *ob, const struct buf *ib, struct sd_markdown *md)+sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, struct sd_markdown *md) { 	static const float MARKDOWN_GROW_FACTOR = 1.4f; @@ -2285,28 +2312,28 @@ 		return;  	/* Preallocate enough space for our buffer to avoid expanding while copying */-	bufgrow(text, ib->size);+	bufgrow(text, doc_size);  	/* reset the references table */ 	memset(&md->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));  	/* first pass: looking for references, copying everything else */ 	beg = 0;-	while (beg < ib->size) /* iterating over lines */-		if (is_ref(ib->data, beg, ib->size, &end, md->refs))+	while (beg < doc_size) /* iterating over lines */+		if (is_ref(document, beg, doc_size, &end, md->refs)) 			beg = end; 		else { /* skipping to the next line */ 			end = beg;-			while (end < ib->size && ib->data[end] != '\n' && ib->data[end] != '\r')+			while (end < doc_size && document[end] != '\n' && document[end] != '\r') 				end++;  			/* adding the line body if present */ 			if (end > beg)-				expand_tabs(text, ib->data + beg, end - beg);+				expand_tabs(text, document + beg, end - beg); -			while (end < ib->size && (ib->data[end] == '\n' || ib->data[end] == '\r')) {+			while (end < doc_size && (document[end] == '\n' || document[end] == '\r')) { 				/* add one \n per newline */-				if (ib->data[end] == '\n' || (end + 1 < ib->size && ib->data[end + 1] != '\n'))+				if (document[end] == '\n' || (end + 1 < doc_size && document[end + 1] != '\n')) 					bufputc(text, '\n'); 				end++; 			}
cbits/markdown.h view
@@ -60,35 +60,35 @@ /* sd_callbacks - functions for rendering parsed data */ struct sd_callbacks { 	/* block level callbacks - NULL skips the block */-	void (*blockcode)(struct buf *ob, struct buf *text, struct buf *lang, void *opaque);-	void (*blockquote)(struct buf *ob, struct buf *text, void *opaque);-	void (*blockhtml)(struct buf *ob, struct buf *text, void *opaque);-	void (*header)(struct buf *ob, struct buf *text, int level, void *opaque);+	void (*blockcode)(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque);+	void (*blockquote)(struct buf *ob, const struct buf *text, void *opaque);+	void (*blockhtml)(struct buf *ob,const  struct buf *text, void *opaque);+	void (*header)(struct buf *ob, const struct buf *text, int level, void *opaque); 	void (*hrule)(struct buf *ob, void *opaque);-	void (*list)(struct buf *ob, struct buf *text, int flags, void *opaque);-	void (*listitem)(struct buf *ob, struct buf *text, int flags, void *opaque);-	void (*paragraph)(struct buf *ob, struct buf *text, void *opaque);-	void (*table)(struct buf *ob, struct buf *header, struct buf *body, void *opaque);-	void (*table_row)(struct buf *ob, struct buf *text, void *opaque);-	void (*table_cell)(struct buf *ob, struct buf *text, int flags, void *opaque);+	void (*list)(struct buf *ob, const struct buf *text, int flags, void *opaque);+	void (*listitem)(struct buf *ob, const struct buf *text, int flags, void *opaque);+	void (*paragraph)(struct buf *ob, const struct buf *text, void *opaque);+	void (*table)(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque);+	void (*table_row)(struct buf *ob, const struct buf *text, void *opaque);+	void (*table_cell)(struct buf *ob, const struct buf *text, int flags, void *opaque);   	/* span level callbacks - NULL or return 0 prints the span verbatim */-	int (*autolink)(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque);-	int (*codespan)(struct buf *ob, struct buf *text, void *opaque);-	int (*double_emphasis)(struct buf *ob, struct buf *text, void *opaque);-	int (*emphasis)(struct buf *ob, struct buf *text, void *opaque);-	int (*image)(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque);+	int (*autolink)(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque);+	int (*codespan)(struct buf *ob, const struct buf *text, void *opaque);+	int (*double_emphasis)(struct buf *ob, const struct buf *text, void *opaque);+	int (*emphasis)(struct buf *ob, const struct buf *text, void *opaque);+	int (*image)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque); 	int (*linebreak)(struct buf *ob, void *opaque);-	int (*link)(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque);-	int (*raw_html_tag)(struct buf *ob, struct buf *tag, void *opaque);-	int (*triple_emphasis)(struct buf *ob, struct buf *text, void *opaque);-	int (*strikethrough)(struct buf *ob, struct buf *text, void *opaque);-	int (*superscript)(struct buf *ob, struct buf *text, void *opaque);+	int (*link)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque);+	int (*raw_html_tag)(struct buf *ob, const struct buf *tag, void *opaque);+	int (*triple_emphasis)(struct buf *ob, const struct buf *text, void *opaque);+	int (*strikethrough)(struct buf *ob, const struct buf *text, void *opaque);+	int (*superscript)(struct buf *ob, const struct buf *text, void *opaque);  	/* low level callbacks - NULL copies input directly into the output */-	void (*entity)(struct buf *ob, struct buf *entity, void *opaque);-	void (*normal_text)(struct buf *ob, struct buf *text, void *opaque);+	void (*entity)(struct buf *ob, const struct buf *entity, void *opaque);+	void (*normal_text)(struct buf *ob, const struct buf *text, void *opaque);  	/* header and footer */ 	void (*doc_header)(struct buf *ob, void *opaque);@@ -114,10 +114,10 @@ 	unsigned int extensions, 	size_t max_nesting, 	const struct sd_callbacks *callbacks,-	void *opaque); +	void *opaque);  extern void-sd_markdown_render(struct buf *ob, const struct buf *ib, struct sd_markdown *md);+sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, struct sd_markdown *md);  extern void sd_markdown_free(struct sd_markdown *md);
cbits/stack.c view
@@ -57,7 +57,7 @@ 	if (!st->size) 		return NULL; -	return st->item[st->size--];+	return st->item[--st->size]; }  int
src/Text/Sundown/Buffer/Foreign.hsc view
@@ -2,25 +2,25 @@  module Text.Sundown.Buffer.Foreign        ( Buffer (..)+       , getBufferData        , c_bufnew        , c_bufputs        , c_bufgrow        , c_bufrelease        ) where -import Foreign-import Foreign.C.Types-import Foreign.C.String import Data.ByteString         (ByteString) import qualified Data.ByteString as BS+import Foreign+import Foreign.C.String+import Foreign.C.Types  #include "buffer.h" -data Buffer = Buffer { bufData  :: ByteString-                     , bufSize  :: Int-                     , bufASize :: Int-                     , bufUnit  :: Int-                     , bufRef   :: Int+data Buffer = Buffer { bufData  :: CString+                     , bufSize  :: CSize+                     , bufASize :: CSize+                     , bufUnit  :: CSize                      }  instance Storable Buffer where@@ -29,14 +29,14 @@   peek ptr = do     d  <- (#peek struct buf, data) ptr     s  <- (#peek struct buf, size) ptr-    dbs <- if d == nullPtr-           then return $ BS.pack [0]-           else BS.packCStringLen (d, s)     as <- (#peek struct buf, asize) ptr     u  <- (#peek struct buf, unit) ptr-    r  <- (#peek struct buf, ref) ptr-    return $ Buffer dbs s as u r+    return $ Buffer d s as u   poke _ _ = error "Buffer.poke not implemented."++getBufferData :: Buffer -> IO ByteString+getBufferData (Buffer d s _ _) | d == nullPtr = return $ BS.pack [0]+                               | otherwise = BS.packCStringLen (d, fromIntegral s)  foreign import ccall "buffer.h bufnew"   c_bufnew :: CSize -> IO (Ptr Buffer)
src/Text/Sundown/Markdown.hs view
@@ -8,8 +8,8 @@  -- | All 'Extensions' disabled noExtensions :: Extensions-noExtensions = Extensions False False False False False False +noExtensions = Extensions False False False False False False False False  -- | All 'Extensions' enabled allExtensions :: Extensions-allExtensions = Extensions True True True True True True+allExtensions = Extensions True True True True True True True True
src/Text/Sundown/Markdown/Foreign.hsc view
@@ -9,20 +9,29 @@        ) where  import Foreign+import Foreign.C.String import Foreign.C.Types- import Text.Sundown.Buffer.Foreign import Text.Sundown.Flag  #include "markdown.h"  -- | A set of switches to enable or disable markdown features.-data Extensions = Extensions { extNoIntraEmphasis :: Bool -- ^ Turn off underscores insode a word does designating emphasis.-                             , extTables          :: Bool-                             , extFencedCode      :: Bool -- ^ Turns on a non-indentation form of code-blocks, by blocking off a region with ~ or \`.-                             , extAutolink        :: Bool -- ^ Turn things that look like URLs and email addresses into links-                             , extStrikethrough   :: Bool -- ^ Surround text with `~` to designate it as struck through-                             , extLaxHtmlBlocks   :: Bool -- ^ Allow HTML markup inside of paragraphs, instead requireing tags to be on separate lines+data Extensions = Extensions { extNoIntraEmphasis :: Bool -- ^ Turn off underscores insode a word+                                                         --   does designating emphasis.+                             , extTables :: Bool+                             , extFencedCode :: Bool -- ^ Turns on a non-indentation form of+                                                    -- code-blocks, by blocking off a regionwith ~+                                                    -- or \`.+                             , extAutolink :: Bool -- ^ Turn things that look like URLs and email+                                                  -- addresses into links+                             , extStrikethrough :: Bool -- ^ Surround text with `~` to designate it+                                                       -- as struck through+                             , extLaxHtmlBlocks :: Bool -- ^ Allow HTML markup inside of paragraphs,+                                                       -- instead requireing tags to be on separate+                                                       -- lines+                             , extSpaceHeaders :: Bool+                             , extSuperscript :: Bool                              }  instance Flag Extensions where@@ -32,6 +41,8 @@                      , (3, extAutolink exts)                      , (4, extStrikethrough exts)                      , (5, extLaxHtmlBlocks exts)+                     , (6, extSpaceHeaders exts)+                     , (7, extSuperscript exts)                      ]  @@ -58,7 +69,7 @@   c_sd_markdown_new' :: CUInt -> CSize -> Ptr Callbacks -> Ptr () -> IO (Ptr Markdown)  foreign import ccall "markdown.h sd_markdown_render"-  c_sd_markdown_render :: Ptr Buffer -> Ptr Buffer -> Ptr Markdown -> IO ()+  c_sd_markdown_render :: Ptr Buffer -> CString -> CSize -> Ptr Markdown -> IO ()  foreign import ccall "markdown.h sd_markdown_free"   c_sd_markdown_free :: Ptr Markdown -> IO ()
src/Text/Sundown/Renderers/Html.hs view
@@ -44,13 +44,17 @@          -- Do the markdown     c_sdhtml_renderer callbacks options mode+         let maxNesting = fromIntegral $ fromMaybe defaultMaxNesting maxNestingM     markdown <- c_sd_markdown_new exts maxNesting callbacks (castPtr options)-    c_sd_markdown_render ob ib markdown++    Buffer {bufData = cs, bufSize = size} <- peek ib+    c_sd_markdown_render ob cs size markdown+     c_sd_markdown_free markdown          -- Get the result-    Buffer {bufData = output} <- peek ob+    output <- peek ob >>= getBufferData          c_bufrelease ib     c_bufrelease ob    @@ -59,11 +63,11 @@  -- | All the 'HtmlRenderMode' disabled noHtmlModes :: HtmlRenderMode-noHtmlModes = HtmlRenderMode False False False False False False False False False False+noHtmlModes = HtmlRenderMode False False False False False False False False False  -- | All the 'HtmlRenderMode' enabled allHtmlModes :: HtmlRenderMode-allHtmlModes = HtmlRenderMode True True True True True True True True True True+allHtmlModes = HtmlRenderMode True True True True True True True True True  -- | Converts punctuation in Html entities, -- <http://daringfireball.net/projects/smartypants/>@@ -75,10 +79,11 @@     ib <- c_bufnew $ fromInteger . toInteger $ BS.length input          c_bufputs ib input-    -    c_sdhtml_smartypants ob ib++    Buffer {bufData = cs, bufSize = size} <- peek ib+    c_sdhtml_smartypants ob cs size     -    Buffer {bufData = output} <- peek ob+    output <- peek ob >>= getBufferData          c_bufrelease ib     c_bufrelease ob
src/Text/Sundown/Renderers/Html/Foreign.hsc view
@@ -9,38 +9,39 @@   import Foreign+import Foreign.C.String import Foreign.C.Types- import Text.Sundown.Buffer.Foreign-import Text.Sundown.Markdown.Foreign import Text.Sundown.Flag+import Text.Sundown.Markdown.Foreign  #include "html.h" -data HtmlRenderMode = HtmlRenderMode { htmlSkipHtml :: Bool -- ^ Drop in-line HTML tags from the output-                                     , htmlSkipStyle :: Bool -- ^ Don't add any style tags to the output+data HtmlRenderMode = HtmlRenderMode { htmlSkipHtml :: Bool -- ^ Drop in-line HTML tags from the+                                                           -- output+                                     , htmlSkipStyle :: Bool -- ^ Don't add any style tags to the+                                                            -- output                                      , htmlSkipImages :: Bool -- ^ Don't include images in the output                                      , htmlSkipLinks :: Bool -- ^ Don't include links in the output                                      , htmlExpandTabs :: Bool-                                     , htmlSafelink :: Bool -- ^ Sanity check links for known URL schemes+                                     , htmlSafelink :: Bool -- ^ Sanity check links for known URL+                                                           -- schemes                                      , htmlToc :: Bool -- ^ Include a table of contents in the output                                      , htmlHardWrap :: Bool-                                     , htmlGithubBlockcode :: Bool                                      , htmlUseXhtml :: Bool -- ^ Produce XHTML output instead of HTML                                      }   instance Flag HtmlRenderMode where-  flagIndexes mode = [ (0,  htmlSkipHtml mode)-                     , (1,  htmlSkipStyle mode)-                     , (2,  htmlSkipImages mode)-                     , (3,  htmlSkipLinks mode)-                     , (5,  htmlExpandTabs mode)-                     , (7,  htmlSafelink mode)-                     , (8,  htmlToc mode)-                     , (9,  htmlHardWrap mode)-                     , (10, htmlGithubBlockcode mode)-                     , (11, htmlUseXhtml mode)+  flagIndexes mode = [ (0, htmlSkipHtml mode)+                     , (1, htmlSkipStyle mode)+                     , (2, htmlSkipImages mode)+                     , (3, htmlSkipLinks mode)+                     , (4, htmlExpandTabs mode)+                     , (5, htmlSafelink mode)+                     , (6, htmlToc mode)+                     , (7, htmlHardWrap mode)+                     , (8, htmlUseXhtml mode)                      ]  data HtmlRenderOptions@@ -60,4 +61,4 @@   c_sdhtml_toc_renderer :: Ptr Callbacks -> Ptr HtmlRenderOptions -> IO ()  foreign import ccall "html.h sdhtml_smartypants"-  c_sdhtml_smartypants :: Ptr Buffer -> Ptr Buffer -> IO ()+  c_sdhtml_smartypants :: Ptr Buffer -> CString -> CSize -> IO ()
sundown.cabal view
@@ -1,6 +1,6 @@ Cabal-version:          >= 1.6 Name:                   sundown-Version:                0.2.3+Version:                0.3 Author:                 Francesco Mazzoli (f@mazzo.li) Maintainer:             Francesco Mazzoli (f@mazzo.li) Build-Type:             Simple@@ -36,14 +36,12 @@                       , Text.Sundown.Flag                       , Text.Sundown.Markdown.Foreign -  C-Sources:            cbits/autolink.c, cbits/buffer.c, cbits/html.c,-                        cbits/html_smartypants.c, cbits/markdown.c,-                        cbits/stack.c+  C-Sources:            cbits/autolink.c, cbits/buffer.c, cbits/houdini_href_e.c,+                        cbits/houdini_html_e.c, cbits/html.c, cbits/html_smartypants.c,+                        cbits/markdown.c, cbits/stack.c      Include-Dirs:         cbits   -  Includes:             autolink.h, buffer.h, html.h, html_blocks.h, markdown.h,-                        stack.h+  Includes:             autolink.h, buffer.h, html.h, html_blocks.h, markdown.h, stack.h -  Install-includes:     autolink.h, buffer.h, html.h, html_blocks.h, markdown.h,-                        stack.h+  Install-includes:     autolink.h, buffer.h, houdini.h, html.h, html_blocks.h, markdown.h, stack.h