Commits

murarth committed 91fd6ea

Updated sundown

  • Participants
  • Parent commits ad79499

Comments (0)

Files changed (13)

reddish/lib/sundown/README.markdown

 - [RobotSkirt](https://github.com/benmills/robotskirt) (Node.js)
 - [Misaka](https://github.com/FSX/misaka) (Python)
 - [ffi-sundown](https://github.com/postmodern/ffi-sundown) (Ruby FFI)
-- [Sundown HS](https://github.com/rostayob/sundown) (Haskell)
+- [Sundown HS](https://github.com/bitonic/sundown) (Haskell)
 - [Goskirt](https://github.com/madari/goskirt) (Go)
 - [Upskirt.go](https://github.com/buu700/upskirt.go) (Go)
 - [MoonShine](https://github.com/brandonc/moonshine) (.NET)

reddish/lib/sundown/VERSION

-1.15.2 3361ebcd22089fe64860f96a7b6acaf18a55746e
+1.16.0 3027e7ab3fc7c9cf4942d6ed13aaaf14e1598cfb

reddish/lib/sundown/html/houdini.h

 
 #include "buffer.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef HOUDINI_USE_LOCALE
 #	define _isxdigit(c) isxdigit(c)
 #	define _isdigit(c) isdigit(c)
 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);
 
+#ifdef __cplusplus
+}
 #endif
+
+#endif

reddish/lib/sundown/html/html.c

 {
 	struct html_renderopt *options = opaque;
 
+	/* set the level offset if this is the first header
+	 * we're parsing for the document */
+	if (options->toc_data.current_level == 0) {
+		options->toc_data.level_offset = level - 1;
+	}
+	level -= options->toc_data.level_offset;
+
 	if (level > options->toc_data.current_level) {
 		while (level > options->toc_data.current_level) {
 			BUFPUTSL(ob, "<ul>\n<li>\n");
 	BUFPUTSL(ob, "</a>\n");
 }
 
+static int
+toc_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque)
+{
+	if (content && content->size)
+		bufput(ob, content->data, content->size);
+	return 1;
+}
+
 static void
 toc_finalize(struct buf *ob, void *opaque)
 {
 		rndr_emphasis,
 		NULL,
 		NULL,
-		NULL,
+		toc_link,
 		NULL,
 		rndr_triple_emphasis,
 		rndr_strikethrough,

reddish/lib/sundown/html/html.h

 #include "buffer.h"
 #include <stdlib.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct html_renderopt {
 	struct {
 		int header_count;
 		int current_level;
+		int level_offset;
 	} toc_data;
 
 	unsigned int flags;
 extern void
 sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size);
 
+#ifdef __cplusplus
+}
 #endif
 
+#endif
+

reddish/lib/sundown/html/html_smartypants.c

 #include <stdio.h>
 #include <ctype.h>
 
+#if defined(_WIN32)
+#define snprintf	_snprintf		
+#endif
+
 struct smartypants_data {
 	int in_squote;
 	int in_dquote;

reddish/lib/sundown/src/autolink.c

 #include <stdio.h>
 #include <ctype.h>
 
+#if defined(_WIN32)
+#define strncasecmp	_strnicmp
+#endif
+
 int
 sd_autolink_issafe(const uint8_t *link, size_t link_len)
 {

reddish/lib/sundown/src/autolink.h

 
 #include "buffer.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 extern int
 sd_autolink_issafe(const uint8_t *link, size_t link_len);
 
 extern size_t
 sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
 
 /* vim: set filetype=c: */

reddish/lib/sundown/src/buffer.h

 #include <stdarg.h>
 #include <stdint.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #if defined(_MSC_VER)
 #define __attribute__(x)
 #define inline
 /* bufprintf: formatted printing to a buffer */
 void bufprintf(struct buf *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
 
+#ifdef __cplusplus
+}
 #endif
+
+#endif

reddish/lib/sundown/src/markdown.c

 #include <ctype.h>
 #include <stdio.h>
 
+#if defined(_WIN32)
+#define strncasecmp	_strnicmp
+#endif
+
 #define BUFFER_BLOCK 0
 #define BUFFER_SPAN 1
 
 	return n >= 3;
 }
 
-/* check if a line is a code fence; return its size if it is */
+/* check if a line begins with a code fence; return the
+ * width of the code fence */
 static size_t
-is_codefence(uint8_t *data, size_t size, struct buf *syntax)
+prefix_codefence(uint8_t *data, size_t size)
 {
 	size_t i = 0, n = 0;
 	uint8_t c;
 	if (n < 3)
 		return 0;
 
-	if (syntax != NULL) {
-		size_t syn = 0;
-
-		while (i < size && data[i] == ' ')
-			i++;
-
+	return i;
+}
+
+/* check if a line is a code fence; return its size if it is */
+static size_t
+is_codefence(uint8_t *data, size_t size, struct buf *syntax)
+{
+	size_t i = 0, syn = 0;
+
+	i = prefix_codefence(data, size);
+	if (i == 0)
+		return 0;
+
+	while (i < size && data[i] == ' ')
+		i++;
+
+	if (syntax)
 		syntax->data = data + i;
 
-		if (i < size && data[i] == '{') {
-			i++; syntax->data++;
-
-			while (i < size && data[i] != '}' && data[i] != '\n') {
-				syn++; i++;
-			}
-
-			if (i == size || data[i] != '}')
-				return 0;
-
-			/* strip all whitespace at the beginning and the end
-			 * of the {} block */
-			while (syn > 0 && _isspace(syntax->data[0])) {
-				syntax->data++; syn--;
-			}
-
-			while (syn > 0 && _isspace(syntax->data[syn - 1]))
-				syn--;
-
-			i++;
-		} else {
-			while (i < size && !_isspace(data[i])) {
-				syn++; i++;
-			}
+	if (i < size && data[i] == '{') {
+		i++; syntax->data++;
+
+		while (i < size && data[i] != '}' && data[i] != '\n') {
+			syn++; i++;
 		}
 
+		if (i == size || data[i] != '}')
+			return 0;
+
+		/* strip all whitespace at the beginning and the end
+		 * of the {} block */
+		while (syn > 0 && _isspace(syntax->data[0])) {
+			syntax->data++; syn--;
+		}
+
+		while (syn > 0 && _isspace(syntax->data[syn - 1]))
+			syn--;
+
+		i++;
+	} else {
+		while (i < size && !_isspace(data[i])) {
+			syn++; i++;
+		}
+	}
+
+	if (syntax)
 		syntax->size = syn;
-	}
 
 	while (i < size && data[i] != '\n') {
 		if (!_isspace(data[i]))
 	while (i < size) {
 		for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;
 
-		if (is_empty(data + i, size - i) || (level = is_headerline(data + i, size - i)) != 0)
+		if (is_empty(data + i, size - i))
 			break;
 
-		if (rndr->ext_flags & MKDEXT_LAX_HTML_BLOCKS) {
-			if (data[i] == '<' && rndr->cb.blockhtml && parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
+		if ((level = is_headerline(data + i, size - i)) != 0)
+			break;
+
+		if (is_atxheader(rndr, data + i, size - i) ||
+			is_hrule(data + i, size - i) ||
+			prefix_quote(data + i, size - i)) {
+			end = i;
+			break;
+		}
+
+		/*
+		 * Early termination of a paragraph with the same logic
+		 * as Markdown 1.0.0. If this logic is applied, the
+		 * Markdown 1.0.3 test suite won't pass cleanly
+		 *
+		 * :: If the first character in a new line is not a letter,
+		 * let's check to see if there's some kind of block starting
+		 * here
+		 */
+		if ((rndr->ext_flags & MKDEXT_LAX_SPACING) && !isalnum(data[i])) {
+			if (prefix_oli(data + i, size - i) ||
+				prefix_uli(data + i, size - i)) {
 				end = i;
 				break;
 			}
-		}
-
-		if (is_atxheader(rndr, data + i, size - i) || is_hrule(data + i, size - i)) {
-			end = i;
-			break;
+
+			/* see if an html block starts here */
+			if (data[i] == '<' && rndr->cb.blockhtml &&
+				parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
+				end = i;
+				break;
+			}
+
+			/* see if a code fence starts here */
+			if ((rndr->ext_flags & MKDEXT_FENCED_CODE) != 0 &&
+				is_codefence(data + i, size - i, NULL) != 0) {
+				end = i;
+				break;
+			}
 		}
 
 		i = end;
 
 	while (beg < size) {
 		size_t fence_end;
-
-		fence_end = is_codefence(data + beg, size - beg, NULL);
-		if (fence_end != 0) {
+		struct buf fence_trail = { 0, 0, 0, 0 };
+
+		fence_end = is_codefence(data + beg, size - beg, &fence_trail);
+		if (fence_end != 0 && fence_trail.size == 0) {
 			beg += fence_end;
 			break;
 		}
 {
 	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;
+	int in_empty = 0, has_inside_empty = 0, in_fence = 0;
 
 	/* keeping track of the first indentation prefix */
 	while (orgpre < 3 && orgpre < size && data[orgpre] == ' ')
 
 	/* process the following lines */
 	while (beg < size) {
+		size_t has_next_uli = 0, has_next_oli = 0;
+
 		end++;
 
 		while (end < size && data[end - 1] != '\n')
 
 		pre = i;
 
-		has_next_uli = prefix_uli(data + beg + i, end - beg - i);
-		has_next_oli = prefix_oli(data + beg + i, end - beg - i);
+		if (rndr->ext_flags & MKDEXT_FENCED_CODE) {
+			if (is_codefence(data + beg + i, end - beg - i, NULL) != 0)
+				in_fence = !in_fence;
+		}
+
+		/* Only check for new list items if we are **not** inside
+		 * a fenced code block */
+		if (!in_fence) {
+			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 && (
 			if (!sublist)
 				sublist = work->size;
 		}
-		/* joining only indented stuff after empty lines */
-		else if (in_empty && i < 4) {
-				*flags |= MKD_LI_END;
-				break;
+		/* joining only indented stuff after empty lines;
+		 * note that now we only require 1 space of indentation
+		 * to continue a list */
+		else if (in_empty && pre == 0) {
+			*flags |= MKD_LI_END;
+			break;
 		}
 		else if (in_empty) {
 			bufputc(work, '\n');
 /* 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, uint8_t *data, size_t size)
+htmlblock_end_tag(
+	const char *tag,
+	size_t tag_len,
+	struct sd_markdown *rndr,
+	uint8_t *data,
+	size_t size)
 {
 	size_t i, w;
 
 	i += w;
 	w = 0;
 
-	if (rndr->ext_flags & MKDEXT_LAX_HTML_BLOCKS) {
-		if (i < size)
-			w = is_empty(data + i, size - i);
-	} else  {
-		if (i < size && (w = is_empty(data + i, size - i)) == 0)
-			return 0; /* non-blank line after tag line */
+	if (i < size)
+		w = is_empty(data + i, size - i);
+
+	return i + w;
+}
+
+static size_t
+htmlblock_end(const char *curtag,
+	struct sd_markdown *rndr,
+	uint8_t *data,
+	size_t size,
+	int start_of_line)
+{
+	size_t tag_size = strlen(curtag);
+	size_t i = 1, end_tag;
+	int block_lines = 0;
+
+	while (i < size) {
+		i++;
+		while (i < size && !(data[i - 1] == '<' && data[i] == '/')) {
+			if (data[i] == '\n')
+				block_lines++;
+
+			i++;
+		}
+
+		/* If we are only looking for unindented tags, skip the tag
+		 * if it doesn't follow a newline.
+		 *
+		 * The only exception to this is if the tag is still on the
+		 * initial line; in that case it still counts as a closing
+		 * tag
+		 */
+		if (start_of_line && block_lines > 0 && data[i - 2] != '\n')
+			continue;
+
+		if (i + 2 + tag_size >= size)
+			break;
+
+		end_tag = htmlblock_end_tag(curtag, tag_size, rndr, data + i - 1, size - i + 1);
+		if (end_tag)
+			return i + end_tag - 1;
 	}
 
-	return i + w;
+	return 0;
 }
 
 
 static size_t
 parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render)
 {
-	size_t i, j = 0;
+	size_t i, j = 0, tag_end;
 	const char *curtag = NULL;
-	int found;
 	struct buf work = { data, 0, 0, 0 };
 
 	/* identification of the opening tag */
 
 	/* looking for an unindented matching closing tag */
 	/*	followed by a blank line */
-	i = 1;
-	found = 0;
+	tag_end = htmlblock_end(curtag, rndr, data, size, 1);
 
 	/* if not found, trying a second pass looking for indented match */
 	/* but not if tag is "ins" or "del" (following original Markdown.pl) */
-	if (strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0) {
-		size_t tag_size = strlen(curtag);
-		i = 1;
-		while (i < size) {
-			i++;
-			while (i < size && !(data[i - 1] == '<' && data[i] == '/'))
-				i++;
-
-			if (i + 2 + tag_size >= size)
-				break;
-
-			j = htmlblock_end(curtag, tag_size, rndr, data + i - 1, size - i + 1);
-
-			if (j) {
-				i += j - 1;
-				found = 1;
-				break;
-			}
-		}
+	if (!tag_end && strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0) {
+		tag_end = htmlblock_end(curtag, rndr, data, size, 0);
 	}
 
-	if (!found) return 0;
+	if (!tag_end)
+		return 0;
 
 	/* the end of the block has been found */
-	work.size = i;
+	work.size = tag_end;
 	if (do_render && rndr->cb.blockhtml)
 		rndr->cb.blockhtml(ob, &work, rndr->opaque);
 
-	return i;
+	return tag_end;
 }
 
 static void
 void
 sd_version(int *ver_major, int *ver_minor, int *ver_revision)
 {
-	*ver_major = UPSKIRT_VER_MAJOR;
-	*ver_minor = UPSKIRT_VER_MINOR;
-	*ver_revision = UPSKIRT_VER_REVISION;
+	*ver_major = SUNDOWN_VER_MAJOR;
+	*ver_minor = SUNDOWN_VER_MINOR;
+	*ver_revision = SUNDOWN_VER_REVISION;
 }
 
 /* vim: set filetype=c: */

reddish/lib/sundown/src/markdown.h

 #include "buffer.h"
 #include "autolink.h"
 
-#define UPSKIRT_VERSION "1.15.2"
-#define UPSKIRT_VER_MAJOR 1
-#define UPSKIRT_VER_MINOR 15
-#define UPSKIRT_VER_REVISION 2
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SUNDOWN_VERSION "1.16.0"
+#define SUNDOWN_VER_MAJOR 1
+#define SUNDOWN_VER_MINOR 16
+#define SUNDOWN_VER_REVISION 0
 
 /********************
  * TYPE DEFINITIONS *
 	MKDEXT_FENCED_CODE = (1 << 2),
 	MKDEXT_AUTOLINK = (1 << 3),
 	MKDEXT_STRIKETHROUGH = (1 << 4),
-	MKDEXT_LAX_HTML_BLOCKS = (1 << 5),
 	MKDEXT_SPACE_HEADERS = (1 << 6),
 	MKDEXT_SUPERSCRIPT = (1 << 7),
+	MKDEXT_LAX_SPACING = (1 << 8),
 };
 
 /* sd_callbacks - functions for rendering parsed data */
 extern void
 sd_version(int *major, int *minor, int *revision);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
 
 /* vim: set filetype=c: */

reddish/lib/sundown/src/stack.h

 
 #include <stdlib.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct stack {
 	void **item;
 	size_t size;
 void *stack_pop(struct stack *);
 void *stack_top(struct stack *);
 
+#ifdef __cplusplus
+}
 #endif
+
+#endif

reddish/lib/sundown/sundown.c

 	if (mod == NULL)
 		return;
 
-	int major, minor, revision;
-
-	sd_version(&major, &minor, &revision);
-
-	PyObject *version_str = PyString_FromFormat("%d.%d.%d", major, minor, revision);
-
-	if (version_str)
-		PyModule_AddObject(mod, "__version__", version_str);
+	PyModule_AddStringConstant(mod, "__version__", SUNDOWN_VERSION);
 }