sundown 0.4 → 0.4.1
raw patch · 16 files changed
+172/−127 lines, 16 files
Files
- cbits/autolink.c +5/−6
- cbits/buffer.c +39/−44
- cbits/buffer.h +2/−5
- cbits/houdini.h +3/−2
- cbits/houdini_html_e.c +1/−1
- cbits/html.c +32/−15
- cbits/html.h +1/−0
- cbits/html_blocks.h +3/−2
- cbits/html_smartypants.c +4/−2
- cbits/markdown.c +47/−16
- cbits/stack.h +2/−2
- src/Text/Sundown/Flag.hs +2/−6
- src/Text/Sundown/Markdown/Foreign.hsc +8/−8
- src/Text/Sundown/Renderers/Html.hs +6/−3
- src/Text/Sundown/Renderers/Html/Foreign.hsc +11/−9
- sundown.cabal +6/−6
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