packages feed

sundown 0.4 → 0.4.1

raw patch · 16 files changed

+172/−127 lines, 16 files

Files

cbits/autolink.c view
@@ -24,9 +24,9 @@ int sd_autolink_issafe(const uint8_t *link, size_t link_len) {-	static const size_t valid_uris_count = 4;+	static const size_t valid_uris_count = 5; 	static const char *valid_uris[] = {-		"http://", "https://", "ftp://", "mailto://"+		"/", "http://", "https://", "ftp://", "mailto:" 	};  	size_t i;@@ -140,10 +140,9 @@ 		else if (!isalnum(data[i]) && data[i] != '-') break; 	} -	if (!isalnum(data[i - 1]) || np == 0)-		return 0;--	return i;+	/* a valid domain needs to have at least a dot.+	 * that's as far as we get */+	return np ? i : 0; }  size_t
cbits/buffer.c view
@@ -22,6 +22,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h>+#include <assert.h>  /* MSVC compat */ #if defined(_MSC_VER)@@ -34,6 +35,7 @@ bufprefix(const struct buf *buf, const char *prefix) { 	size_t i;+	assert(buf && buf->unit);  	for (i = 0; i < buf->size; ++i) { 		if (prefix[i] == 0)@@ -52,7 +54,10 @@ { 	size_t neoasz; 	void *neodata;-	if (!buf || !buf->unit || neosz > BUFFER_MAX_ALLOC_SIZE)++	assert(buf && buf->unit);++	if (neosz > BUFFER_MAX_ALLOC_SIZE) 		return BUF_ENOMEM;  	if (buf->asize >= neosz)@@ -91,8 +96,7 @@ const char * bufcstr(struct buf *buf) {-	if (!buf || !buf->unit)-		return NULL;+	assert(buf && buf->unit);  	if (buf->size < buf->asize && buf->data[buf->size] == 0) 		return (char *)buf->data;@@ -110,20 +114,45 @@ bufprintf(struct buf *buf, const char *fmt, ...) { 	va_list ap;-	if (!buf || !buf->unit)-		return;+	int n; +	assert(buf && buf->unit);++	if (buf->size >= buf->asize && bufgrow(buf, buf->size + 1) < 0)+		return;+	 	va_start(ap, fmt);-	vbufprintf(buf, fmt, ap);+	n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap); 	va_end(ap);++	if (n < 0) {+#ifdef _MSC_VER+		n = _vscprintf(fmt, ap);+#else+		return;+#endif+	}++	if ((size_t)n >= buf->asize - buf->size) {+		if (bufgrow(buf, buf->size + n + 1) < 0)+			return;++		va_start(ap, fmt);+		n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);+		va_end(ap);+	}++	if (n < 0)+		return;++	buf->size += n; }  /* bufput: appends raw data to a buffer */ void bufput(struct buf *buf, const void *data, size_t len) {-	if (!buf)-		return;+	assert(buf && buf->unit);  	if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0) 		return;@@ -144,8 +173,7 @@ void bufputc(struct buf *buf, int c) {-	if (!buf)-		return;+	assert(buf && buf->unit);  	if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0) 		return;@@ -182,8 +210,7 @@ void bufslurp(struct buf *buf, size_t len) {-	if (!buf || !buf->unit || len <= 0)-		return;+	assert(buf && buf->unit);  	if (len >= buf->size) { 		buf->size = 0;@@ -192,37 +219,5 @@  	buf->size -= len; 	memmove(buf->data, buf->data + len, buf->size);-}--/* vbufprintf: stdarg variant of formatted printing into a buffer */-void-vbufprintf(struct buf *buf, const char *fmt, va_list ap)-{-	int n;--	if (buf == 0 || (buf->size >= buf->asize && bufgrow(buf, buf->size + 1)) < 0)-		return;--	n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);--	if (n < 0) {-#ifdef _MSC_VER-		n = _vscprintf(fmt, ap);-#else-		return;-#endif-	}--	if ((size_t)n >= buf->asize - buf->size) {-		if (bufgrow(buf, buf->size + n + 1) < 0)-			return;--		n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);-	}--	if (n < 0)-		return;--	buf->size += n; } 
cbits/buffer.h view
@@ -15,8 +15,8 @@  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  */ -#ifndef __GEN_BUFFER_H__-#define __GEN_BUFFER_H__+#ifndef BUFFER_H__+#define BUFFER_H__  #include <stddef.h> #include <stdarg.h>@@ -84,8 +84,5 @@  /* 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);  #endif
cbits/houdini.h view
@@ -1,5 +1,5 @@-#ifndef __HOUDINI_H__-#define __HOUDINI_H__+#ifndef HOUDINI_H__+#define HOUDINI_H__  #include "buffer.h" @@ -17,6 +17,7 @@ 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_xml(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);
cbits/houdini_html_e.c view
@@ -49,7 +49,7 @@ void houdini_escape_html0(struct buf *ob, const uint8_t *src, size_t size, int secure) {-	size_t  i = 0, org, esc;+	size_t i = 0, org, esc = 0;  	bufgrow(ob, ESCAPE_GROW_FACTOR(size)); 
cbits/html.c view
@@ -60,6 +60,16 @@ 	return HTML_TAG_NONE; } +static inline void escape_html(struct buf *ob, const uint8_t *source, size_t length)+{+	houdini_escape_html0(ob, source, length, 0);+}++static inline void escape_href(struct buf *ob, const uint8_t *source, size_t length)+{+	houdini_escape_href(ob, source, length);+}+ /********************  * GENERIC RENDERER *  ********************/@@ -79,7 +89,7 @@ 	BUFPUTSL(ob, "<a href=\""); 	if (type == MKDA_EMAIL) 		BUFPUTSL(ob, "mailto:");-	houdini_escape_href(ob, link->data, link->size);+	escape_href(ob, link->data, link->size);  	if (options->link_attributes) { 		bufputc(ob, '\"');@@ -95,9 +105,9 @@ 	 * want to print the `mailto:` prefix 	 */ 	if (bufprefix(link, "mailto:") == 0) {-		houdini_escape_html(ob, link->data + 7, link->size - 7);+		escape_html(ob, link->data + 7, link->size - 7); 	} else {-		houdini_escape_html(ob, link->data, link->size);+		escape_html(ob, link->data, link->size); 	}  	BUFPUTSL(ob, "</a>");@@ -127,7 +137,7 @@ 					org++;  				if (cls) bufputc(ob, ' ');-				houdini_escape_html(ob, lang->data + org, i - org);+				escape_html(ob, lang->data + org, i - org); 			} 		} @@ -136,7 +146,7 @@ 		BUFPUTSL(ob, "<pre><code>");  	if (text)-		houdini_escape_html(ob, text->data, text->size);+		escape_html(ob, text->data, text->size);  	BUFPUTSL(ob, "</code></pre>\n"); }@@ -154,7 +164,7 @@ rndr_codespan(struct buf *ob, const struct buf *text, void *opaque) { 	BUFPUTSL(ob, "<code>");-	if (text) houdini_escape_html(ob, text->data, text->size);+	if (text) escape_html(ob, text->data, text->size); 	BUFPUTSL(ob, "</code>"); 	return 1; }@@ -230,11 +240,11 @@ 	BUFPUTSL(ob, "<a href=\"");  	if (link && link->size)-		houdini_escape_href(ob, link->data, link->size);+		escape_href(ob, link->data, link->size);  	if (title && title->size) { 		BUFPUTSL(ob, "\" title=\"");-		houdini_escape_html(ob, title->data, title->size);+		escape_html(ob, title->data, title->size); 	}  	if (options->link_attributes) {@@ -322,9 +332,9 @@ 	size_t org, sz; 	if (!text) return; 	sz = text->size;-	while (sz > 0 && text->data[sz - 1] == '\n') sz -= 1;+	while (sz > 0 && text->data[sz - 1] == '\n') sz--; 	org = 0;-	while (org < sz && text->data[org] == '\n') org += 1;+	while (org < sz && text->data[org] == '\n') org++; 	if (org >= sz) return; 	if (ob->size) bufputc(ob, '\n'); 	bufput(ob, text->data + org, sz - org);@@ -356,15 +366,15 @@ 	if (!link || !link->size) return 0;  	BUFPUTSL(ob, "<img src=\"");-	houdini_escape_href(ob, link->data, link->size);+	escape_href(ob, link->data, link->size); 	BUFPUTSL(ob, "\" alt=\"");  	if (alt && alt->size)-		houdini_escape_html(ob, alt->data, alt->size);+		escape_html(ob, alt->data, alt->size);  	if (title && title->size) { 		BUFPUTSL(ob, "\" title=\"");-		houdini_escape_html(ob, title->data, title->size); }+		escape_html(ob, title->data, title->size); }  	bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">"); 	return 1;@@ -375,6 +385,13 @@ { 	struct html_renderopt *options = opaque; +	/* HTML_ESCAPE overrides SKIP_HTML, SKIP_STYLE, SKIP_LINKS and SKIP_IMAGES+	* It doens't see if there are any valid tags, just escape all of them. */+	if((options->flags & HTML_ESCAPE) != 0) {+		escape_html(ob, text->data, text->size);+		return 1;+	}+ 	if ((options->flags & HTML_SKIP_HTML) != 0) 		return 1; @@ -466,7 +483,7 @@ rndr_normal_text(struct buf *ob, const struct buf *text, void *opaque) { 	if (text)-		houdini_escape_html(ob, text->data, text->size);+		escape_html(ob, text->data, text->size); }  static void@@ -598,6 +615,6 @@ 		callbacks->autolink = NULL; 	} -	if (render_flags & HTML_SKIP_HTML)+	if (render_flags & HTML_SKIP_HTML || render_flags & HTML_ESCAPE) 		callbacks->blockhtml = NULL; }
cbits/html.h view
@@ -43,6 +43,7 @@ 	HTML_TOC = (1 << 6), 	HTML_HARD_WRAP = (1 << 7), 	HTML_USE_XHTML = (1 << 8),+	HTML_ESCAPE = (1 << 9), } html_render_mode;  typedef enum {
cbits/html_blocks.h view
@@ -147,7 +147,7 @@ {   enum     {-      TOTAL_KEYWORDS = 23,+      TOTAL_KEYWORDS = 24,       MIN_WORD_LENGTH = 1,       MAX_WORD_LENGTH = 10,       MIN_HASH_VALUE = 1,@@ -179,7 +179,8 @@       "script",       "h5",       "noscript",-      "", "",+      "",+      "style",       "iframe",       "h4",       "ins",
cbits/html_smartypants.c view
@@ -264,8 +264,10 @@ 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 const char *skip_tags[] = {"pre", "code", "kbd", "script"};-	static const size_t skip_tags_count = 4;+	static const char *skip_tags[] = {+	  "pre", "code", "var", "samp", "kbd", "math", "script", "style"+	};+	static const size_t skip_tags_count = 8;  	size_t tag, i = 0; 
cbits/markdown.c view
@@ -111,6 +111,7 @@ 	struct stack work_bufs[2]; 	unsigned int ext_flags; 	size_t max_nesting;+	int in_link_body; };  /***************************@@ -372,7 +373,6 @@ 		if (end >= size) break; 		i = end; -		/* calling the trigger */ 		end = markdown_char_ptrs[(int)action](ob, rndr, data + i, i, size - i); 		if (!end) /* no action from the callback */ 			end = i + 1;@@ -425,7 +425,6 @@ 			}  			if (i >= size) return tmp_i;-			i++; 		} 		/* skipping a link */ 		else if (data[i] == '[') {@@ -682,7 +681,7 @@ static size_t char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) {-	static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>";+	static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~"; 	struct buf work = { 0, 0, 0, 0 };  	if (size > 1) {@@ -695,6 +694,8 @@ 			rndr->cb.normal_text(ob, &work, rndr->opaque); 		} 		else bufputc(ob, data[1]);+	} else if (size == 1) {+		bufputc(ob, data[0]); 	}  	return 2;@@ -761,7 +762,7 @@ 	struct buf *link, *link_url, *link_text; 	size_t link_len, rewind; -	if (!rndr->cb.link)+	if (!rndr->cb.link || rndr->in_link_body) 		return 0;  	link = rndr_newbuf(rndr, BUFFER_SPAN);@@ -793,7 +794,7 @@ 	struct buf *link; 	size_t link_len, rewind; -	if (!rndr->cb.autolink)+	if (!rndr->cb.autolink || rndr->in_link_body) 		return 0;  	link = rndr_newbuf(rndr, BUFFER_SPAN);@@ -813,7 +814,7 @@ 	struct buf *link; 	size_t link_len, rewind; -	if (!rndr->cb.autolink)+	if (!rndr->cb.autolink || rndr->in_link_body) 		return 0;  	link = rndr_newbuf(rndr, BUFFER_SPAN);@@ -839,6 +840,7 @@ 	struct buf *u_link = 0; 	size_t org_work_size = rndr->work_bufs[BUFFER_SPAN].size; 	int text_has_nl = 0, ret = 0;+	int in_title = 0, qtype = 0;  	/* checking whether the correct renderer exists */ 	if ((is_img && !rndr->cb.image) || (!is_img && !rndr->cb.link))@@ -886,7 +888,8 @@ 		/* looking for link end: ' " ) */ 		while (i < size) { 			if (data[i] == '\\') i += 2;-			else if (data[i] == ')' || data[i] == '\'' || data[i] == '"') break;+			else if (data[i] == ')') break;+			else if (i >= 1 && _isspace(data[i-1]) && (data[i] == '\'' || data[i] == '"')) break; 			else i++; 		} @@ -895,12 +898,15 @@  		/* looking for title end if present */ 		if (data[i] == '\'' || data[i] == '"') {+			qtype = data[i];+			in_title = 1; 			i++; 			title_b = i;  			while (i < size) { 				if (data[i] == '\\') i += 2;-				else if (data[i] == ')') break;+				else if (data[i] == qtype) {in_title = 0; i++;}+				else if ((data[i] == ')') && !in_title) break; 				else i++; 			} @@ -1026,8 +1032,15 @@ 	/* building content: img alt is escaped, link content is parsed */ 	if (txt_e > 1) { 		content = rndr_newbuf(rndr, BUFFER_SPAN);-		if (is_img) bufput(content, data + 1, txt_e - 1);-		else parse_inline(content, rndr, data + 1, txt_e - 1);+		if (is_img) {+			bufput(content, data + 1, txt_e - 1);+		} else {+			/* disable autolinking when parsing inline the+			 * content of a link */+			rndr->in_link_body = 1;+			parse_inline(content, rndr, data + 1, txt_e - 1);+			rndr->in_link_body = 0;+		} 	}  	if (link) {@@ -1565,6 +1578,7 @@ 	struct buf *work = 0, *inter = 0; 	size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; 	int in_empty = 0, has_inside_empty = 0;+	size_t has_next_uli, has_next_oli;  	/* keeping track of the first indentation prefix */ 	while (orgpre < 3 && orgpre < size && data[orgpre] == ' ')@@ -1611,10 +1625,19 @@  		pre = i; +		has_next_uli = prefix_uli(data + beg + i, end - beg - i);+		has_next_oli = prefix_oli(data + beg + i, end - beg - i);++		/* checking for ul/ol switch */+		if (in_empty && (+			((*flags & MKD_LIST_ORDERED) && has_next_uli) ||+			(!(*flags & MKD_LIST_ORDERED) && has_next_oli))){+			*flags |= MKD_LI_END;+			break; /* the following item must have same list type */+		}+ 		/* checking for a new item */-		if ((prefix_uli(data + beg + i, end - beg - i) &&-			!is_hrule(data + beg + i, end - beg - i)) ||-			prefix_oli(data + beg + i, end - beg - i)) {+		if ((has_next_uli && !is_hrule(data + beg + i, end - beg - i)) || has_next_oli) { 			if (in_empty) 				has_inside_empty = 1; @@ -1783,7 +1806,7 @@ 		i++;  	if (i < size)-		curtag = find_block_tag((char *)data + 1, i - 1);+		curtag = find_block_tag((char *)data + 1, (int)i - 1);  	/* handling of special cases */ 	if (!curtag) {@@ -2332,6 +2355,7 @@ 	md->ext_flags = extensions; 	md->opaque = opaque; 	md->max_nesting = max_nesting;+	md->in_link_body = 0;  	return md; }@@ -2339,7 +2363,8 @@ void 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;+#define MARKDOWN_GROW(x) ((x) + ((x) >> 1))+	static const char UTF8_BOM[] = {0xEF, 0xBB, 0xBF};  	struct buf *text; 	size_t beg, end;@@ -2356,6 +2381,12 @@  	/* first pass: looking for references, copying everything else */ 	beg = 0;++	/* Skip a possible UTF-8 BOM, even though the Unicode standard+	 * discourages having these in UTF-8 documents */+	if (doc_size >= 3 && memcmp(document, UTF8_BOM, 3) == 0)+		beg += 3;+ 	while (beg < doc_size) /* iterating over lines */ 		if (is_ref(document, beg, doc_size, &end, md->refs)) 			beg = end;@@ -2379,7 +2410,7 @@ 		}  	/* pre-grow the output buffer to minimize allocations */-	bufgrow(ob, text->size * MARKDOWN_GROW_FACTOR);+	bufgrow(ob, MARKDOWN_GROW(text->size));  	/* second pass: actual rendering */ 	if (md->cb.doc_header)
cbits/stack.h view
@@ -1,5 +1,5 @@-#ifndef __CR_STACK_H__-#define __CR_STACK_H__+#ifndef STACK_H__+#define STACK_H__  #include <stdlib.h> 
src/Text/Sundown/Flag.hs view
@@ -3,16 +3,12 @@        , toCUInt        ) where - import Foreign.C.Types import Data.Bits  class Flag a where-  flagIndexes :: a -> [(Int, Bool)]+  flagIndexes :: a -> [(CUInt, Bool)]  toCUInt :: Flag a => a -> CUInt-toCUInt flag = foldl (\uint (ix, b) -> shiftL (fromIntegral . fromEnum $ b) ix .|. uint)+toCUInt flag = foldl (\uint (f, b) -> (if b then f else 0) .|. uint)                      0 (flagIndexes flag)---
src/Text/Sundown/Markdown/Foreign.hsc view
@@ -35,14 +35,14 @@                              }  instance Flag Extensions where-  flagIndexes exts = [ (0, extNoIntraEmphasis exts)-                     , (1, extTables exts)-                     , (2, extFencedCode exts)-                     , (3, extAutolink exts)-                     , (4, extStrikethrough exts)-                     , (5, extLaxHtmlBlocks exts)-                     , (6, extSpaceHeaders exts)-                     , (7, extSuperscript exts)+  flagIndexes exts = [ (#{const MKDEXT_NO_INTRA_EMPHASIS}, extNoIntraEmphasis exts)+                     , (#{const MKDEXT_TABLES}, extTables exts)+                     , (#{const MKDEXT_FENCED_CODE}, extFencedCode exts)+                     , (#{const MKDEXT_AUTOLINK}, extAutolink exts)+                     , (#{const MKDEXT_STRIKETHROUGH}, extStrikethrough exts)+                     , (#{const MKDEXT_LAX_HTML_BLOCKS}, extLaxHtmlBlocks exts)+                     , (#{const MKDEXT_SPACE_HEADERS}, extSpaceHeaders exts)+                     , (#{const MKDEXT_SUPERSCRIPT}, extSuperscript exts)                      ]  
src/Text/Sundown/Renderers/Html.hs view
@@ -8,8 +8,11 @@        , HtmlRenderMode (..)        ) where +import Foreign.Marshal+import Foreign.Ptr+import Foreign.Storable -import Foreign+import System.IO.Unsafe  import Data.ByteString (ByteString) import qualified Data.ByteString as BS@@ -63,11 +66,11 @@  -- | All the 'HtmlRenderMode' disabled noHtmlModes :: HtmlRenderMode-noHtmlModes = HtmlRenderMode False False False False False False False False False+noHtmlModes = HtmlRenderMode False 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+allHtmlModes = HtmlRenderMode True True True True True True True True True True  -- | Converts punctuation in Html entities, -- <http://daringfireball.net/projects/smartypants/>
src/Text/Sundown/Renderers/Html/Foreign.hsc view
@@ -28,19 +28,21 @@                                      , htmlToc :: Bool -- ^ Include a table of contents in the output                                      , htmlHardWrap :: Bool                                      , htmlUseXhtml :: Bool -- ^ Produce XHTML output instead of HTML+                                     , htmlEscape :: Bool                                      }   instance Flag HtmlRenderMode where-  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)+  flagIndexes mode = [ (#{const HTML_SKIP_HTML}, htmlSkipHtml mode)+                     , (#{const HTML_SKIP_STYLE}, htmlSkipStyle mode)+                     , (#{const HTML_SKIP_IMAGES}, htmlSkipImages mode)+                     , (#{const HTML_SKIP_LINKS}, htmlSkipLinks mode)+                     , (#{const HTML_EXPAND_TABS}, htmlExpandTabs mode)+                     , (#{const HTML_SAFELINK}, htmlSafelink mode)+                     , (#{const HTML_TOC}, htmlToc mode)+                     , (#{const HTML_HARD_WRAP}, htmlHardWrap mode)+                     , (#{const HTML_USE_XHTML}, htmlUseXhtml mode)+                     , (#{const HTML_ESCAPE}, htmlEscape mode)                      ]  data HtmlRenderOptions
sundown.cabal view
@@ -1,6 +1,6 @@ Cabal-version:          >= 1.6 Name:                   sundown-Version:                0.4+Version:                0.4.1 Author:                 Francesco Mazzoli (f@mazzo.li) Maintainer:             Francesco Mazzoli (f@mazzo.li) Build-Type:             Simple@@ -8,7 +8,7 @@ Build-Type:             Simple Category:               Foreign binding, Text Synopsis:               Bindings to the sundown markdown library-Tested-With:            GHC==7.0.2+Tested-With:            GHC==7.2.2 Description:   Bindings to the github fork of sundown, a nice C markdown library:   <https://github.com/tanoku/sundown>@@ -24,9 +24,9 @@                       , bytestring    GHC-Options:          -Wall -O2 -fno-cse-  +   Extensions:           ForeignFunctionInterface, EmptyDataDecls-  +   Exposed-Modules:      Text.Sundown                       , Text.Sundown.Markdown                       , Text.Sundown.Renderers.Html@@ -39,9 +39,9 @@   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    Install-includes:     autolink.h, buffer.h, houdini.h, html.h, html_blocks.h, markdown.h, stack.h