aboutsummaryrefslogtreecommitdiff
path: root/libraries/hoedown
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/hoedown')
-rw-r--r--libraries/hoedown/CMakeLists.txt26
-rw-r--r--libraries/hoedown/LICENSE15
-rw-r--r--libraries/hoedown/README.md9
-rw-r--r--libraries/hoedown/include/hoedown/autolink.h46
-rw-r--r--libraries/hoedown/include/hoedown/buffer.h134
-rw-r--r--libraries/hoedown/include/hoedown/document.h172
-rw-r--r--libraries/hoedown/include/hoedown/escape.h28
-rw-r--r--libraries/hoedown/include/hoedown/html.h84
-rw-r--r--libraries/hoedown/include/hoedown/stack.h52
-rw-r--r--libraries/hoedown/include/hoedown/version.h33
-rw-r--r--libraries/hoedown/src/autolink.c281
-rw-r--r--libraries/hoedown/src/buffer.c308
-rw-r--r--libraries/hoedown/src/document.c2958
-rw-r--r--libraries/hoedown/src/escape.c188
-rw-r--r--libraries/hoedown/src/html.c754
-rw-r--r--libraries/hoedown/src/html_blocks.c240
-rw-r--r--libraries/hoedown/src/html_smartypants.c435
-rw-r--r--libraries/hoedown/src/stack.c79
-rw-r--r--libraries/hoedown/src/version.c9
19 files changed, 5851 insertions, 0 deletions
diff --git a/libraries/hoedown/CMakeLists.txt b/libraries/hoedown/CMakeLists.txt
new file mode 100644
index 00000000..7902e734
--- /dev/null
+++ b/libraries/hoedown/CMakeLists.txt
@@ -0,0 +1,26 @@
+# hoedown 3.0.2 - https://github.com/hoedown/hoedown/archive/3.0.2.tar.gz
+project(hoedown LANGUAGES C VERSION 3.0.2)
+
+set(HOEDOWN_SOURCES
+include/hoedown/autolink.h
+include/hoedown/buffer.h
+include/hoedown/document.h
+include/hoedown/escape.h
+include/hoedown/html.h
+include/hoedown/stack.h
+include/hoedown/version.h
+src/autolink.c
+src/buffer.c
+src/document.c
+src/escape.c
+src/html.c
+src/html_blocks.c
+src/html_smartypants.c
+src/stack.c
+src/version.c
+)
+
+# Include self.
+add_library(hoedown STATIC ${HOEDOWN_SOURCES})
+
+target_include_directories(hoedown PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
diff --git a/libraries/hoedown/LICENSE b/libraries/hoedown/LICENSE
new file mode 100644
index 00000000..4e75de4d
--- /dev/null
+++ b/libraries/hoedown/LICENSE
@@ -0,0 +1,15 @@
+Copyright (c) 2008, Natacha Porté
+Copyright (c) 2011, Vicent Martí
+Copyright (c) 2014, Xavier Mendez, Devin Torres and the Hoedown authors
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/libraries/hoedown/README.md b/libraries/hoedown/README.md
new file mode 100644
index 00000000..abe2b6ca
--- /dev/null
+++ b/libraries/hoedown/README.md
@@ -0,0 +1,9 @@
+Hoedown
+=======
+
+This is Hoedown 3.0.2, taken from [the hoedown github repo](https://github.com/hoedown/hoedown).
+
+`Hoedown` is a revived fork of [Sundown](https://github.com/vmg/sundown),
+the Markdown parser based on the original code of the
+[Upskirt library](http://fossil.instinctive.eu/libupskirt/index)
+by Natacha Porté.
diff --git a/libraries/hoedown/include/hoedown/autolink.h b/libraries/hoedown/include/hoedown/autolink.h
new file mode 100644
index 00000000..528885c9
--- /dev/null
+++ b/libraries/hoedown/include/hoedown/autolink.h
@@ -0,0 +1,46 @@
+/* autolink.h - versatile autolinker */
+
+#ifndef HOEDOWN_AUTOLINK_H
+#define HOEDOWN_AUTOLINK_H
+
+#include "buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * CONSTANTS *
+ *************/
+
+typedef enum hoedown_autolink_flags {
+ HOEDOWN_AUTOLINK_SHORT_DOMAINS = (1 << 0)
+} hoedown_autolink_flags;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_autolink_is_safe: verify that a URL has a safe protocol */
+int hoedown_autolink_is_safe(const uint8_t *data, size_t size);
+
+/* hoedown_autolink__www: search for the next www link in data */
+size_t hoedown_autolink__www(size_t *rewind_p, hoedown_buffer *link,
+ uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+
+/* hoedown_autolink__email: search for the next email in data */
+size_t hoedown_autolink__email(size_t *rewind_p, hoedown_buffer *link,
+ uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+
+/* hoedown_autolink__url: search for the next URL in data */
+size_t hoedown_autolink__url(size_t *rewind_p, hoedown_buffer *link,
+ uint8_t *data, size_t offset, size_t size, hoedown_autolink_flags flags);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_AUTOLINK_H **/
diff --git a/libraries/hoedown/include/hoedown/buffer.h b/libraries/hoedown/include/hoedown/buffer.h
new file mode 100644
index 00000000..d7703f8d
--- /dev/null
+++ b/libraries/hoedown/include/hoedown/buffer.h
@@ -0,0 +1,134 @@
+/* buffer.h - simple, fast buffers */
+
+#ifndef HOEDOWN_BUFFER_H
+#define HOEDOWN_BUFFER_H
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_MSC_VER)
+#define __attribute__(x)
+#define inline __inline
+#define __builtin_expect(x,n) x
+#endif
+
+
+/*********
+ * TYPES *
+ *********/
+
+typedef void *(*hoedown_realloc_callback)(void *, size_t);
+typedef void (*hoedown_free_callback)(void *);
+
+struct hoedown_buffer {
+ 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) */
+
+ hoedown_realloc_callback data_realloc;
+ hoedown_free_callback data_free;
+ hoedown_free_callback buffer_free;
+};
+
+typedef struct hoedown_buffer hoedown_buffer;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* allocation wrappers */
+void *hoedown_malloc(size_t size) __attribute__ ((malloc));
+void *hoedown_calloc(size_t nmemb, size_t size) __attribute__ ((malloc));
+void *hoedown_realloc(void *ptr, size_t size) __attribute__ ((malloc));
+
+/* hoedown_buffer_init: initialize a buffer with custom allocators */
+void hoedown_buffer_init(
+ hoedown_buffer *buffer,
+ size_t unit,
+ hoedown_realloc_callback data_realloc,
+ hoedown_free_callback data_free,
+ hoedown_free_callback buffer_free
+);
+
+/* hoedown_buffer_uninit: uninitialize an existing buffer */
+void hoedown_buffer_uninit(hoedown_buffer *buf);
+
+/* hoedown_buffer_new: allocate a new buffer */
+hoedown_buffer *hoedown_buffer_new(size_t unit) __attribute__ ((malloc));
+
+/* hoedown_buffer_reset: free internal data of the buffer */
+void hoedown_buffer_reset(hoedown_buffer *buf);
+
+/* hoedown_buffer_grow: increase the allocated size to the given value */
+void hoedown_buffer_grow(hoedown_buffer *buf, size_t neosz);
+
+/* hoedown_buffer_put: append raw data to a buffer */
+void hoedown_buffer_put(hoedown_buffer *buf, const uint8_t *data, size_t size);
+
+/* hoedown_buffer_puts: append a NUL-terminated string to a buffer */
+void hoedown_buffer_puts(hoedown_buffer *buf, const char *str);
+
+/* hoedown_buffer_putc: append a single char to a buffer */
+void hoedown_buffer_putc(hoedown_buffer *buf, uint8_t c);
+
+/* hoedown_buffer_putf: read from a file and append to a buffer, until EOF or error */
+int hoedown_buffer_putf(hoedown_buffer *buf, FILE* file);
+
+/* hoedown_buffer_set: replace the buffer's contents with raw data */
+void hoedown_buffer_set(hoedown_buffer *buf, const uint8_t *data, size_t size);
+
+/* hoedown_buffer_sets: replace the buffer's contents with a NUL-terminated string */
+void hoedown_buffer_sets(hoedown_buffer *buf, const char *str);
+
+/* hoedown_buffer_eq: compare a buffer's data with other data for equality */
+int hoedown_buffer_eq(const hoedown_buffer *buf, const uint8_t *data, size_t size);
+
+/* hoedown_buffer_eq: compare a buffer's data with NUL-terminated string for equality */
+int hoedown_buffer_eqs(const hoedown_buffer *buf, const char *str);
+
+/* hoedown_buffer_prefix: compare the beginning of a buffer with a string */
+int hoedown_buffer_prefix(const hoedown_buffer *buf, const char *prefix);
+
+/* hoedown_buffer_slurp: remove a given number of bytes from the head of the buffer */
+void hoedown_buffer_slurp(hoedown_buffer *buf, size_t size);
+
+/* hoedown_buffer_cstr: NUL-termination of the string array (making a C-string) */
+const char *hoedown_buffer_cstr(hoedown_buffer *buf);
+
+/* hoedown_buffer_printf: formatted printing to a buffer */
+void hoedown_buffer_printf(hoedown_buffer *buf, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+/* hoedown_buffer_put_utf8: put a Unicode character encoded as UTF-8 */
+void hoedown_buffer_put_utf8(hoedown_buffer *buf, unsigned int codepoint);
+
+/* hoedown_buffer_free: free the buffer */
+void hoedown_buffer_free(hoedown_buffer *buf);
+
+
+/* HOEDOWN_BUFPUTSL: optimized hoedown_buffer_puts of a string literal */
+#define HOEDOWN_BUFPUTSL(output, literal) \
+ hoedown_buffer_put(output, (const uint8_t *)literal, sizeof(literal) - 1)
+
+/* HOEDOWN_BUFSETSL: optimized hoedown_buffer_sets of a string literal */
+#define HOEDOWN_BUFSETSL(output, literal) \
+ hoedown_buffer_set(output, (const uint8_t *)literal, sizeof(literal) - 1)
+
+/* HOEDOWN_BUFEQSL: optimized hoedown_buffer_eqs of a string literal */
+#define HOEDOWN_BUFEQSL(output, literal) \
+ hoedown_buffer_eq(output, (const uint8_t *)literal, sizeof(literal) - 1)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_BUFFER_H **/
diff --git a/libraries/hoedown/include/hoedown/document.h b/libraries/hoedown/include/hoedown/document.h
new file mode 100644
index 00000000..a8178fec
--- /dev/null
+++ b/libraries/hoedown/include/hoedown/document.h
@@ -0,0 +1,172 @@
+/* document.h - generic markdown parser */
+
+#ifndef HOEDOWN_DOCUMENT_H
+#define HOEDOWN_DOCUMENT_H
+
+#include "buffer.h"
+#include "autolink.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * CONSTANTS *
+ *************/
+
+typedef enum hoedown_extensions {
+ /* block-level extensions */
+ HOEDOWN_EXT_TABLES = (1 << 0),
+ HOEDOWN_EXT_FENCED_CODE = (1 << 1),
+ HOEDOWN_EXT_FOOTNOTES = (1 << 2),
+
+ /* span-level extensions */
+ HOEDOWN_EXT_AUTOLINK = (1 << 3),
+ HOEDOWN_EXT_STRIKETHROUGH = (1 << 4),
+ HOEDOWN_EXT_UNDERLINE = (1 << 5),
+ HOEDOWN_EXT_HIGHLIGHT = (1 << 6),
+ HOEDOWN_EXT_QUOTE = (1 << 7),
+ HOEDOWN_EXT_SUPERSCRIPT = (1 << 8),
+ HOEDOWN_EXT_MATH = (1 << 9),
+
+ /* other flags */
+ HOEDOWN_EXT_NO_INTRA_EMPHASIS = (1 << 11),
+ HOEDOWN_EXT_SPACE_HEADERS = (1 << 12),
+ HOEDOWN_EXT_MATH_EXPLICIT = (1 << 13),
+
+ /* negative flags */
+ HOEDOWN_EXT_DISABLE_INDENTED_CODE = (1 << 14)
+} hoedown_extensions;
+
+#define HOEDOWN_EXT_BLOCK (\
+ HOEDOWN_EXT_TABLES |\
+ HOEDOWN_EXT_FENCED_CODE |\
+ HOEDOWN_EXT_FOOTNOTES )
+
+#define HOEDOWN_EXT_SPAN (\
+ HOEDOWN_EXT_AUTOLINK |\
+ HOEDOWN_EXT_STRIKETHROUGH |\
+ HOEDOWN_EXT_UNDERLINE |\
+ HOEDOWN_EXT_HIGHLIGHT |\
+ HOEDOWN_EXT_QUOTE |\
+ HOEDOWN_EXT_SUPERSCRIPT |\
+ HOEDOWN_EXT_MATH )
+
+#define HOEDOWN_EXT_FLAGS (\
+ HOEDOWN_EXT_NO_INTRA_EMPHASIS |\
+ HOEDOWN_EXT_SPACE_HEADERS |\
+ HOEDOWN_EXT_MATH_EXPLICIT )
+
+#define HOEDOWN_EXT_NEGATIVE (\
+ HOEDOWN_EXT_DISABLE_INDENTED_CODE )
+
+typedef enum hoedown_list_flags {
+ HOEDOWN_LIST_ORDERED = (1 << 0),
+ HOEDOWN_LI_BLOCK = (1 << 1) /* <li> containing block data */
+} hoedown_list_flags;
+
+typedef enum hoedown_table_flags {
+ HOEDOWN_TABLE_ALIGN_LEFT = 1,
+ HOEDOWN_TABLE_ALIGN_RIGHT = 2,
+ HOEDOWN_TABLE_ALIGN_CENTER = 3,
+ HOEDOWN_TABLE_ALIGNMASK = 3,
+ HOEDOWN_TABLE_HEADER = 4
+} hoedown_table_flags;
+
+typedef enum hoedown_autolink_type {
+ HOEDOWN_AUTOLINK_NONE, /* used internally when it is not an autolink*/
+ HOEDOWN_AUTOLINK_NORMAL, /* normal http/http/ftp/mailto/etc link */
+ HOEDOWN_AUTOLINK_EMAIL /* e-mail link without explit mailto: */
+} hoedown_autolink_type;
+
+
+/*********
+ * TYPES *
+ *********/
+
+struct hoedown_document;
+typedef struct hoedown_document hoedown_document;
+
+struct hoedown_renderer_data {
+ void *opaque;
+};
+typedef struct hoedown_renderer_data hoedown_renderer_data;
+
+/* hoedown_renderer - functions for rendering parsed data */
+struct hoedown_renderer {
+ /* state object */
+ void *opaque;
+
+ /* block level callbacks - NULL skips the block */
+ void (*blockcode)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data);
+ void (*blockquote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*header)(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data);
+ void (*hrule)(hoedown_buffer *ob, const hoedown_renderer_data *data);
+ void (*list)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
+ void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
+ void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table_header)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table_body)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data);
+ void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data);
+ void (*blockhtml)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+ /* span level callbacks - NULL or return 0 prints the span verbatim */
+ int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data);
+ int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+ int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*underline)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*highlight)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*quote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*image)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data);
+ int (*linebreak)(hoedown_buffer *ob, const hoedown_renderer_data *data);
+ int (*link)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data);
+ int (*triple_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
+ int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data);
+ int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data);
+ int (*raw_html)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+ /* low level callbacks - NULL copies input directly into the output */
+ void (*entity)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+ void (*normal_text)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
+
+ /* miscellaneous callbacks */
+ void (*doc_header)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
+ void (*doc_footer)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
+};
+typedef struct hoedown_renderer hoedown_renderer;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_document_new: allocate a new document processor instance */
+hoedown_document *hoedown_document_new(
+ const hoedown_renderer *renderer,
+ hoedown_extensions extensions,
+ size_t max_nesting
+) __attribute__ ((malloc));
+
+/* hoedown_document_render: render regular Markdown using the document processor */
+void hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size);
+
+/* hoedown_document_render_inline: render inline Markdown using the document processor */
+void hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const uint8_t *data, size_t size);
+
+/* hoedown_document_free: deallocate a document processor instance */
+void hoedown_document_free(hoedown_document *doc);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_DOCUMENT_H **/
diff --git a/libraries/hoedown/include/hoedown/escape.h b/libraries/hoedown/include/hoedown/escape.h
new file mode 100644
index 00000000..d7659c27
--- /dev/null
+++ b/libraries/hoedown/include/hoedown/escape.h
@@ -0,0 +1,28 @@
+/* escape.h - escape utilities */
+
+#ifndef HOEDOWN_ESCAPE_H
+#define HOEDOWN_ESCAPE_H
+
+#include "buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_escape_href: escape (part of) a URL inside HTML */
+void hoedown_escape_href(hoedown_buffer *ob, const uint8_t *data, size_t size);
+
+/* hoedown_escape_html: escape HTML */
+void hoedown_escape_html(hoedown_buffer *ob, const uint8_t *data, size_t size, int secure);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_ESCAPE_H **/
diff --git a/libraries/hoedown/include/hoedown/html.h b/libraries/hoedown/include/hoedown/html.h
new file mode 100644
index 00000000..e46e7fd6
--- /dev/null
+++ b/libraries/hoedown/include/hoedown/html.h
@@ -0,0 +1,84 @@
+/* html.h - HTML renderer and utilities */
+
+#ifndef HOEDOWN_HTML_H
+#define HOEDOWN_HTML_H
+
+#include "document.h"
+#include "buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * CONSTANTS *
+ *************/
+
+typedef enum hoedown_html_flags {
+ HOEDOWN_HTML_SKIP_HTML = (1 << 0),
+ HOEDOWN_HTML_ESCAPE = (1 << 1),
+ HOEDOWN_HTML_HARD_WRAP = (1 << 2),
+ HOEDOWN_HTML_USE_XHTML = (1 << 3)
+} hoedown_html_flags;
+
+typedef enum hoedown_html_tag {
+ HOEDOWN_HTML_TAG_NONE = 0,
+ HOEDOWN_HTML_TAG_OPEN,
+ HOEDOWN_HTML_TAG_CLOSE
+} hoedown_html_tag;
+
+
+/*********
+ * TYPES *
+ *********/
+
+struct hoedown_html_renderer_state {
+ void *opaque;
+
+ struct {
+ int header_count;
+ int current_level;
+ int level_offset;
+ int nesting_level;
+ } toc_data;
+
+ hoedown_html_flags flags;
+
+ /* extra callbacks */
+ void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, const hoedown_renderer_data *data);
+};
+typedef struct hoedown_html_renderer_state hoedown_html_renderer_state;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_html_smartypants: process an HTML snippet using SmartyPants for smart punctuation */
+void hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *data, size_t size);
+
+/* hoedown_html_is_tag: checks if data starts with a specific tag, returns the tag type or NONE */
+hoedown_html_tag hoedown_html_is_tag(const uint8_t *data, size_t size, const char *tagname);
+
+
+/* hoedown_html_renderer_new: allocates a regular HTML renderer */
+hoedown_renderer *hoedown_html_renderer_new(
+ hoedown_html_flags render_flags,
+ int nesting_level
+) __attribute__ ((malloc));
+
+/* hoedown_html_toc_renderer_new: like hoedown_html_renderer_new, but the returned renderer produces the Table of Contents */
+hoedown_renderer *hoedown_html_toc_renderer_new(
+ int nesting_level
+) __attribute__ ((malloc));
+
+/* hoedown_html_renderer_free: deallocate an HTML renderer */
+void hoedown_html_renderer_free(hoedown_renderer *renderer);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_HTML_H **/
diff --git a/libraries/hoedown/include/hoedown/stack.h b/libraries/hoedown/include/hoedown/stack.h
new file mode 100644
index 00000000..bf9b439b
--- /dev/null
+++ b/libraries/hoedown/include/hoedown/stack.h
@@ -0,0 +1,52 @@
+/* stack.h - simple stacking */
+
+#ifndef HOEDOWN_STACK_H
+#define HOEDOWN_STACK_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*********
+ * TYPES *
+ *********/
+
+struct hoedown_stack {
+ void **item;
+ size_t size;
+ size_t asize;
+};
+typedef struct hoedown_stack hoedown_stack;
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_stack_init: initialize a stack */
+void hoedown_stack_init(hoedown_stack *st, size_t initial_size);
+
+/* hoedown_stack_uninit: free internal data of the stack */
+void hoedown_stack_uninit(hoedown_stack *st);
+
+/* hoedown_stack_grow: increase the allocated size to the given value */
+void hoedown_stack_grow(hoedown_stack *st, size_t neosz);
+
+/* hoedown_stack_push: push an item to the top of the stack */
+void hoedown_stack_push(hoedown_stack *st, void *item);
+
+/* hoedown_stack_pop: retrieve and remove the item at the top of the stack */
+void *hoedown_stack_pop(hoedown_stack *st);
+
+/* hoedown_stack_top: retrieve the item at the top of the stack */
+void *hoedown_stack_top(const hoedown_stack *st);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_STACK_H **/
diff --git a/libraries/hoedown/include/hoedown/version.h b/libraries/hoedown/include/hoedown/version.h
new file mode 100644
index 00000000..4938cae5
--- /dev/null
+++ b/libraries/hoedown/include/hoedown/version.h
@@ -0,0 +1,33 @@
+/* version.h - holds Hoedown's version */
+
+#ifndef HOEDOWN_VERSION_H
+#define HOEDOWN_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************
+ * CONSTANTS *
+ *************/
+
+#define HOEDOWN_VERSION "3.0.2"
+#define HOEDOWN_VERSION_MAJOR 3
+#define HOEDOWN_VERSION_MINOR 0
+#define HOEDOWN_VERSION_REVISION 2
+
+
+/*************
+ * FUNCTIONS *
+ *************/
+
+/* hoedown_version: retrieve Hoedown's version numbers */
+void hoedown_version(int *major, int *minor, int *revision);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** HOEDOWN_VERSION_H **/
diff --git a/libraries/hoedown/src/autolink.c b/libraries/hoedown/src/autolink.c
new file mode 100644
index 00000000..9bc7fad5
--- /dev/null
+++ b/libraries/hoedown/src/autolink.c
@@ -0,0 +1,281 @@
+#include "hoedown/autolink.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifndef _MSC_VER
+#include <strings.h>
+#else
+#define strncasecmp _strnicmp
+#endif
+
+int
+hoedown_autolink_is_safe(const uint8_t *data, size_t size)
+{
+ static const size_t valid_uris_count = 6;
+ static const char *valid_uris[] = {
+ "http://", "https://", "/", "#", "ftp://", "mailto:"
+ };
+ static const size_t valid_uris_size[] = { 7, 8, 1, 1, 6, 7 };
+ size_t i;
+
+ for (i = 0; i < valid_uris_count; ++i) {
+ size_t len = valid_uris_size[i];
+
+ if (size > len &&
+ strncasecmp((char *)data, valid_uris[i], len) == 0 &&
+ isalnum(data[len]))
+ return 1;
+ }
+
+ return 0;
+}
+
+static size_t
+autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
+{
+ uint8_t cclose, copen = 0;
+ size_t i;
+
+ for (i = 0; i < link_end; ++i)
+ if (data[i] == '<') {
+ link_end = i;
+ break;
+ }
+
+ while (link_end > 0) {
+ if (strchr("?!.,:", data[link_end - 1]) != NULL)
+ link_end--;
+
+ else if (data[link_end - 1] == ';') {
+ size_t new_end = link_end - 2;
+
+ while (new_end > 0 && isalpha(data[new_end]))
+ new_end--;
+
+ if (new_end < link_end - 2 && data[new_end] == '&')
+ link_end = new_end;
+ else
+ link_end--;
+ }
+ else break;
+ }
+
+ if (link_end == 0)
+ return 0;
+
+ cclose = data[link_end - 1];
+
+ switch (cclose) {
+ case '"': copen = '"'; break;
+ case '\'': copen = '\''; break;
+ case ')': copen = '('; break;
+ case ']': copen = '['; break;
+ case '}': copen = '{'; break;
+ }
+
+ if (copen != 0) {
+ size_t closing = 0;
+ size_t opening = 0;
+ size_t i = 0;
+
+ /* Try to close the final punctuation sign in this same line;
+ * if we managed to close it outside of the URL, that means that it's
+ * not part of the URL. If it closes inside the URL, that means it
+ * is part of the URL.
+ *
+ * Examples:
+ *
+ * foo http://www.pokemon.com/Pikachu_(Electric) bar
+ * => http://www.pokemon.com/Pikachu_(Electric)
+ *
+ * foo (http://www.pokemon.com/Pikachu_(Electric)) bar
+ * => http://www.pokemon.com/Pikachu_(Electric)
+ *
+ * foo http://www.pokemon.com/Pikachu_(Electric)) bar
+ * => http://www.pokemon.com/Pikachu_(Electric))
+ *
+ * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
+ * => foo http://www.pokemon.com/Pikachu_(Electric)
+ */
+
+ while (i < link_end) {
+ if (data[i] == copen)
+ opening++;
+ else if (data[i] == cclose)
+ closing++;
+
+ i++;
+ }
+
+ if (closing != opening)
+ link_end--;
+ }
+
+ return link_end;
+}
+
+static size_t
+check_domain(uint8_t *data, size_t size, int allow_short)
+{
+ size_t i, np = 0;
+
+ if (!isalnum(data[0]))
+ return 0;
+
+ for (i = 1; i < size - 1; ++i) {
+ if (strchr(".:", data[i]) != NULL) np++;
+ else if (!isalnum(data[i]) && data[i] != '-') break;
+ }
+
+ if (allow_short) {
+ /* We don't need a valid domain in the strict sense (with
+ * least one dot; so just make sure it's composed of valid
+ * domain characters and return the length of the the valid
+ * sequence. */
+ return i;
+ } else {
+ /* a valid domain needs to have at least a dot.
+ * that's as far as we get */
+ return np ? i : 0;
+ }
+}
+
+size_t
+hoedown_autolink__www(
+ size_t *rewind_p,
+ hoedown_buffer *link,
+ uint8_t *data,
+ size_t max_rewind,
+ size_t size,
+ unsigned int flags)
+{
+ size_t link_end;
+
+ if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
+ return 0;
+
+ if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
+ return 0;
+
+ link_end = check_domain(data, size, 0);
+
+ if (link_end == 0)
+ return 0;
+
+ while (link_end < size && !isspace(data[link_end]))
+ link_end++;
+
+ link_end = autolink_delim(data, link_end, max_rewind, size);
+
+ if (link_end == 0)
+ return 0;
+
+ hoedown_buffer_put(link, data, link_end);
+ *rewind_p = 0;
+
+ return (int)link_end;
+}
+
+size_t
+hoedown_autolink__email(
+ size_t *rewind_p,
+ hoedown_buffer *link,
+ uint8_t *data,
+ size_t max_rewind,
+ size_t size,
+ unsigned int flags)
+{
+ size_t link_end, rewind;
+ int nb = 0, np = 0;
+
+ for (rewind = 0; rewind < max_rewind; ++rewind) {
+ uint8_t c = data[-1 - rewind];
+
+ if (isalnum(c))
+ continue;
+
+ if (strchr(".+-_", c) != NULL)
+ continue;
+
+ break;
+ }
+
+ if (rewind == 0)
+ return 0;
+
+ for (link_end = 0; link_end < size; ++link_end) {
+ uint8_t c = data[link_end];
+
+ if (isalnum(c))
+ continue;
+
+ if (c == '@')
+ nb++;
+ else if (c == '.' && link_end < size - 1)
+ np++;
+ else if (c != '-' && c != '_')
+ break;
+ }
+
+ if (link_end < 2 || nb != 1 || np == 0 ||
+ !isalpha(data[link_end - 1]))
+ return 0;
+
+ link_end = autolink_delim(data, link_end, max_rewind, size);
+
+ if (link_end == 0)
+ return 0;
+
+ hoedown_buffer_put(link, data - rewind, link_end + rewind);
+ *rewind_p = rewind;
+
+ return link_end;
+}
+
+size_t
+hoedown_autolink__url(
+ size_t *rewind_p,
+ hoedown_buffer *link,
+ uint8_t *data,
+ size_t max_rewind,
+ size_t size,
+ unsigned int flags)
+{
+ size_t link_end, rewind = 0, domain_len;
+
+ if (size < 4 || data[1] != '/' || data[2] != '/')
+ return 0;
+
+ while (rewind < max_rewind && isalpha(data[-1 - rewind]))
+ rewind++;
+
+ if (!hoedown_autolink_is_safe(data - rewind, size + rewind))
+ return 0;
+
+ link_end = strlen("://");
+
+ domain_len = check_domain(
+ data + link_end,
+ size - link_end,
+ flags & HOEDOWN_AUTOLINK_SHORT_DOMAINS);
+
+ if (domain_len == 0)
+ return 0;
+
+ link_end += domain_len;
+ while (link_end < size && !isspace(data[link_end]))
+ link_end++;
+
+ link_end = autolink_delim(data, link_end, max_rewind, size);
+
+ if (link_end == 0)
+ return 0;
+
+ hoedown_buffer_put(link, data - rewind, link_end + rewind);
+ *rewind_p = rewind;
+
+ return link_end;
+}
diff --git a/libraries/hoedown/src/buffer.c b/libraries/hoedown/src/buffer.c
new file mode 100644
index 00000000..1c7ba55a
--- /dev/null
+++ b/libraries/hoedown/src/buffer.c
@@ -0,0 +1,308 @@
+#include "hoedown/buffer.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+void *
+hoedown_malloc(size_t size)
+{
+ void *ret = malloc(size);
+
+ if (!ret) {
+ fprintf(stderr, "Allocation failed.\n");
+ abort();
+ }
+
+ return ret;
+}
+
+void *
+hoedown_calloc(size_t nmemb, size_t size)
+{
+ void *ret = calloc(nmemb, size);
+
+ if (!ret) {
+ fprintf(stderr, "Allocation failed.\n");
+ abort();
+ }
+
+ return ret;
+}
+
+void *
+hoedown_realloc(void *ptr, size_t size)
+{
+ void *ret = realloc(ptr, size);
+
+ if (!ret) {
+ fprintf(stderr, "Allocation failed.\n");
+ abort();
+ }
+
+ return ret;
+}
+
+void
+hoedown_buffer_init(
+ hoedown_buffer *buf,
+ size_t unit,
+ hoedown_realloc_callback data_realloc,
+ hoedown_free_callback data_free,
+ hoedown_free_callback buffer_free)
+{
+ assert(buf);
+
+ buf->data = NULL;
+ buf->size = buf->asize = 0;
+ buf->unit = unit;
+ buf->data_realloc = data_realloc;