Skip to content
Browse files

rename to Sundown.

  • Loading branch information...
1 parent dcbe8c1 commit 19b8b2d63246f03ad8171d284a102749c0f43780 @chobie committed Jul 24, 2011
View
3 .gitmodules
@@ -0,0 +1,3 @@
+[submodule "sundown"]
+ path = sundown
+ url = https://github.com/tanoku/sundown.git
View
18 README.md
@@ -1,7 +1,7 @@
-PHP + Upskirt
+PHP + Sundown
===========================
-phpskirt is just simple wrapper of <https://github.com/tanoku/upskirt>.
+php-sundown is just simple wrapper of <https://github.com/tanoku/sundown>.
License
-------
@@ -23,20 +23,20 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Install
-------
- git clone https://github.com/chobie/phpskirt.git && cd phpskirt
- git submodule init
+ git clone https://github.com/chobie/php-sundown.git && cd php-sundown
cd src
phpize && ./configure
make
sudo make install
- # extension=phpskirt.so
+ # please add following line to your php.ini
+ # extension=sundown.so
Example
-------
- $markdown = new Upskirt(string $string [, array $extensions]);
- echo $markdown->to_html();
- echo $markdown->to_toc();
+ $sundown = new Sundown(string $string [, array $extensions]);
+ echo $sundown->to_html();
+ echo $sundownn->to_toc();
Supported Extensions
--------------------
@@ -46,7 +46,7 @@ Supported Extensions
// default: disable all.
// maybe this array will be integer (bit flags).
-new Upskirt('something',array(
+new Sundown('something',array(
"filter_html"=>true,
"no_image"=>true,
"no_links"=>true,
View
261 src/autolink.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2011, Vicent Marti
+ *
+ * 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.
+ */
+
+#include "buffer.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+int
+sd_autolink_issafe(const char *link, size_t link_len)
+{
+ static const size_t valid_uris_count = 4;
+ static const char *valid_uris[] = {
+ "http://", "https://", "ftp://", "mailto://"
+ };
+
+ size_t i;
+
+ for (i = 0; i < valid_uris_count; ++i) {
+ size_t len = strlen(valid_uris[i]);
+
+ if (link_len > len &&
+ strncasecmp(link, valid_uris[i], len) == 0 &&
+ isalnum(link[len]))
+ return 1;
+ }
+
+ return 0;
+}
+
+static size_t
+autolink_delim(char *data, size_t link_end, size_t offset, size_t size)
+{
+ char 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(char *data, size_t size)
+{
+ size_t i, np = 0;
+
+ if (!isalnum(data[0]))
+ return 0;
+
+ for (i = 1; i < size - 1; ++i) {
+ if (data[i] == '.') np++;
+ else if (!isalnum(data[i]) && data[i] != '-') break;
+ }
+
+ if (!isalnum(data[i - 1]) || np == 0)
+ return 0;
+
+ return i;
+}
+
+size_t
+sd_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)
+{
+ size_t link_end;
+
+ if (offset > 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);
+
+ if (link_end == 0)
+ return 0;
+
+ while (link_end < size && !isspace(data[link_end]))
+ link_end++;
+
+ link_end = autolink_delim(data, link_end, offset, size);
+
+ if (link_end == 0)
+ return 0;
+
+ bufput(link, data, link_end);
+ *rewind_p = 0;
+
+ return (int)link_end;
+}
+
+size_t
+sd_autolink__email(size_t *rewind_p, struct buf *link, char *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];
+
+ if (isalnum(c))
+ continue;
+
+ if (strchr(".+-_", c) != NULL)
+ continue;
+
+ break;
+ }
+
+ if (rewind == 0)
+ return 0;
+
+ for (link_end = 0; link_end < size; ++link_end) {
+ char 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)
+ return 0;
+
+ link_end = autolink_delim(data, link_end, offset, size);
+
+ if (link_end == 0)
+ return 0;
+
+ bufput(link, data - rewind, link_end + rewind);
+ *rewind_p = rewind;
+
+ return link_end;
+}
+
+size_t
+sd_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)
+{
+ size_t link_end, rewind = 0, domain_len;
+
+ if (size < 4 || data[1] != '/' || data[2] != '/')
+ return 0;
+
+ while (rewind < offset && isalpha(data[-rewind - 1]))
+ rewind++;
+
+ if (!sd_autolink_issafe(data - rewind, size + rewind))
+ return 0;
+ link_end = STRLEN("://");
+
+ domain_len = check_domain(data + link_end, size - link_end);
+ 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, offset, size);
+
+ if (link_end == 0)
+ return 0;
+
+ bufput(link, data - rewind, link_end + rewind);
+ *rewind_p = rewind;
+
+ return link_end;
+}
+
View
36 src/autolink.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011, Vicent Marti
+ *
+ * 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.
+ */
+
+#ifndef UPSKIRT_AUTOLINK_H
+#define UPSKIRT_AUTOLINK_H
+
+#include "buffer.h"
+
+extern int
+sd_autolink_issafe(const char *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);
+
+extern size_t
+sd_autolink__email(size_t *rewind_p, struct buf *link, char *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);
+
+#endif
+
+/* vim: set filetype=c: */
View
8 src/config.m4
@@ -1,6 +1,6 @@
-PHP_ARG_ENABLE(phpskirt,Whether to enable the "phpskirt" extension,
- [ --enable-phpskirt Enable "phpskirt" extension support])
+PHP_ARG_ENABLE(sundown,Whether to enable the "sundown" extension,
+ [ --enable-sundown Enable "sundown" extension support])
-if test $PHP_PHPSKIRT != "no"; then
- PHP_NEW_EXTENSION(phpskirt,phpskirt.c array.c buffer.c markdown.c html.c html_smartypants.c, $ext_shared)
+if test $PHP_SUNDOWN != "no"; then
+ PHP_NEW_EXTENSION(sundown,php_sundown.c array.c buffer.c markdown.c html.c html_smartypants.c autolink.c, $ext_shared)
fi
View
6 src/config.w32
@@ -1,6 +1,6 @@
-ARG_WITH('phpskirt', 'phpskirt extension', 'no');
+ARG_WITH('sundown', 'sundown extension', 'no');
-if (PHP_PHPSKIRT != "no") {
+if (SUNDOWN != "no") {
- EXTENSION("phpskirt", "phpskirt.c array.c buffer.c markdown.c html.c html_smartypants.c");
+ EXTENSION("sundown", "sundown.c array.c buffer.c markdown.c html.c html_smartypants.c autolink.c");
}
View
90 src/html.c
@@ -24,6 +24,8 @@
#include <ctype.h>
struct html_renderopt {
+ void *extra;
+
struct {
int header_count;
int current_level;
@@ -45,9 +47,9 @@ put_scaped_char(struct buf *ob, char c)
}
}
-/* attr_escape • copy the buffer entity-escaping '<', '>', '&' and '"' */
-static void
-attr_escape(struct buf *ob, const char *src, size_t size)
+/* 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) {
@@ -66,37 +68,37 @@ attr_escape(struct buf *ob, const char *src, size_t size)
}
}
-static int
-is_html_tag(struct buf *tag, const char *tagname)
+int
+sdhtml_tag(const char *tag_data, size_t tag_size, const char *tagname)
{
- size_t i = 0;
+ size_t i;
+ int closed = 0;
- if (i < tag->size && tag->data[0] != '<')
- return 0;
+ if (tag_size < 3 || tag_data[0] != '<')
+ return HTML_TAG_NONE;
- i++;
+ i = 1;
- while (i < tag->size && isspace(tag->data[i]))
- i++;
-
- if (i < tag->size && tag->data[i] == '/')
- i++;
-
- while (i < tag->size && isspace(tag->data[i]))
+ if (tag_data[i] == '/') {
+ closed = 1;
i++;
+ }
- for (; i < tag->size; ++i, ++tagname) {
+ for (; i < tag_size; ++i, ++tagname) {
if (*tagname == 0)
break;
- if (tag->data[i] != *tagname)
- return 0;
+ if (tag_data[i] != *tagname)
+ return HTML_TAG_NONE;
}
- if (i == tag->size)
- return 0;
+ if (i == tag_size)
+ return HTML_TAG_NONE;
+
+ if (isspace(tag_data[i]) || tag_data[i] == '>')
+ return closed ? HTML_TAG_CLOSE : HTML_TAG_OPEN;
- return (isspace(tag->data[i]) || tag->data[i] == '>');
+ return HTML_TAG_NONE;
}
/********************
@@ -111,7 +113,7 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *op
return 0;
if ((options->flags & HTML_SAFELINK) != 0 &&
- !is_safe_link(link->data, link->size) &&
+ !sd_autolink_issafe(link->data, link->size) &&
type != MKDA_EMAIL)
return 0;
@@ -127,9 +129,9 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *op
* want to print the `mailto:` prefix
*/
if (bufprefix(link, "mailto:") == 0) {
- attr_escape(ob, link->data + 7, link->size - 7);
+ sdhtml_escape(ob, link->data + 7, link->size - 7);
} else {
- attr_escape(ob, link->data, link->size);
+ sdhtml_escape(ob, link->data, link->size);
}
BUFPUTSL(ob, "</a>");
@@ -159,7 +161,7 @@ rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
org++;
if (cls) bufputc(ob, ' ');
- attr_escape(ob, lang->data + org, i - org);
+ sdhtml_escape(ob, lang->data + org, i - org);
}
}
@@ -168,7 +170,7 @@ rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
BUFPUTSL(ob, "<pre><code>");
if (text)
- attr_escape(ob, text->data, text->size);
+ sdhtml_escape(ob, text->data, text->size);
BUFPUTSL(ob, "</code></pre>\n");
}
@@ -204,16 +206,16 @@ rndr_blockcode_github(struct buf *ob, struct buf *text, struct buf *lang, void *
i++;
if (lang->data[0] == '.')
- attr_escape(ob, lang->data + 1, i - 1);
+ sdhtml_escape(ob, lang->data + 1, i - 1);
else
- attr_escape(ob, lang->data, i);
+ sdhtml_escape(ob, lang->data, i);
BUFPUTSL(ob, "\"><code>");
} else
BUFPUTSL(ob, "<pre><code>");
if (text)
- attr_escape(ob, text->data, text->size);
+ sdhtml_escape(ob, text->data, text->size);
BUFPUTSL(ob, "</code></pre>\n");
}
@@ -230,7 +232,7 @@ static int
rndr_codespan(struct buf *ob, struct buf *text, void *opaque)
{
BUFPUTSL(ob, "<code>");
- if (text) attr_escape(ob, text->data, text->size);
+ if (text) sdhtml_escape(ob, text->data, text->size);
BUFPUTSL(ob, "</code>");
return 1;
}
@@ -292,14 +294,14 @@ rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *conte
{
struct html_renderopt *options = opaque;
- if ((options->flags & HTML_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
+ if ((options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size))
return 0;
BUFPUTSL(ob, "<a href=\"");
if (link && link->size) bufput(ob, link->data, link->size);
if (title && title->size) {
BUFPUTSL(ob, "\" title=\"");
- attr_escape(ob, title->data, title->size); }
+ sdhtml_escape(ob, title->data, title->size); }
BUFPUTSL(ob, "\">");
if (content && content->size) bufput(ob, content->data, content->size);
BUFPUTSL(ob, "</a>");
@@ -406,13 +408,13 @@ rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt,
struct html_renderopt *options = opaque;
if (!link || !link->size) return 0;
BUFPUTSL(ob, "<img src=\"");
- attr_escape(ob, link->data, link->size);
+ sdhtml_escape(ob, link->data, link->size);
BUFPUTSL(ob, "\" alt=\"");
if (alt && alt->size)
- attr_escape(ob, alt->data, alt->size);
+ sdhtml_escape(ob, alt->data, alt->size);
if (title && title->size) {
BUFPUTSL(ob, "\" title=\"");
- attr_escape(ob, title->data, title->size); }
+ sdhtml_escape(ob, title->data, title->size); }
bufputc(ob, '"');
bufputs(ob, options->close_tag);
@@ -436,13 +438,13 @@ rndr_raw_html(struct buf *ob, struct buf *text, void *opaque)
if ((options->flags & HTML_SKIP_HTML) != 0)
return 1;
- if ((options->flags & HTML_SKIP_STYLE) != 0 && is_html_tag(text, "style"))
+ if ((options->flags & HTML_SKIP_STYLE) != 0 && sdhtml_tag(text->data, text->size, "style"))
return 1;
- if ((options->flags & HTML_SKIP_LINKS) != 0 && is_html_tag(text, "a"))
+ if ((options->flags & HTML_SKIP_LINKS) != 0 && sdhtml_tag(text->data, text->size, "a"))
return 1;
- if ((options->flags & HTML_SKIP_IMAGES) != 0 && is_html_tag(text, "img"))
+ if ((options->flags & HTML_SKIP_IMAGES) != 0 && sdhtml_tag(text->data, text->size, "img"))
return 1;
bufput(ob, text->data, text->size);
@@ -503,7 +505,7 @@ static void
rndr_normal_text(struct buf *ob, struct buf *text, void *opaque)
{
if (text)
- attr_escape(ob, text->data, text->size);
+ sdhtml_escape(ob, text->data, text->size);
}
static void
@@ -546,7 +548,7 @@ toc_finalize(struct buf *ob, void *opaque)
}
void
-upshtml_toc_renderer(struct mkd_renderer *renderer)
+sdhtml_toc_renderer(struct mkd_renderer *renderer, void *extra)
{
static const struct mkd_renderer toc_render = {
NULL,
@@ -584,13 +586,14 @@ upshtml_toc_renderer(struct mkd_renderer *renderer)
struct html_renderopt *options;
options = calloc(1, sizeof(struct html_renderopt));
options->flags = HTML_TOC;
+ options->extra = extra;
memcpy(renderer, &toc_render, sizeof(struct mkd_renderer));
renderer->opaque = options;
}
void
-upshtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags)
+sdhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags, void *extra)
{
static const char *xhtml_close = "/>\n";
static const char *html_close = ">\n";
@@ -632,6 +635,7 @@ upshtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags)
options = calloc(1, sizeof(struct html_renderopt));
options->flags = render_flags;
options->close_tag = (render_flags & HTML_USE_XHTML) ? xhtml_close : html_close;
+ options->extra = extra;
memcpy(renderer, &renderer_default, sizeof(struct mkd_renderer));
renderer->opaque = options;
@@ -652,7 +656,7 @@ upshtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags)
}
void
-upshtml_free_renderer(struct mkd_renderer *renderer)
+sdhtml_free_renderer(struct mkd_renderer *renderer)
{
free(renderer->opaque);
}
View
22 src/html.h
@@ -18,6 +18,8 @@
#define UPSKIRT_HTML_H
#include "markdown.h"
+#include "buffer.h"
+#include <stdlib.h>
typedef enum {
HTML_SKIP_HTML = (1 << 0),
@@ -32,17 +34,29 @@ typedef enum {
HTML_USE_XHTML = (1 << 11),
} render_mode;
+typedef enum {
+ HTML_TAG_NONE = 0,
+ HTML_TAG_OPEN,
+ 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);
+
extern void
-upshtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags);
+sdhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags, void *extra);
extern void
-upshtml_toc_renderer(struct mkd_renderer *renderer);
+sdhtml_toc_renderer(struct mkd_renderer *renderer, void *extra);
extern void
-upshtml_free_renderer(struct mkd_renderer *renderer);
+sdhtml_free_renderer(struct mkd_renderer *renderer);
extern void
-upshtml_smartypants(struct buf *ob, struct buf *text);
+sdhtml_smartypants(struct buf *ob, struct buf *text);
#endif
View
46 src/html_smartypants.c
@@ -161,16 +161,14 @@ smartypants_cb__parens(struct buf *ob, struct smartypants_data *smrt, char previ
static size_t
smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)
{
- if (size >= 2) {
- if (text[1] == '-') {
- BUFPUTSL(ob, "&mdash;");
- return 1;
- }
+ if (size >= 3 && text[1] == '-' && text[2] == '-') {
+ BUFPUTSL(ob, "&mdash;");
+ return 2;
+ }
- if (word_boundary(previous_char) && word_boundary(text[1])) {
- BUFPUTSL(ob, "&ndash;");
- return 0;
- }
+ if (size >= 2 && text[1] == '-') {
+ BUFPUTSL(ob, "&ndash;");
+ return 1;
}
bufputc(ob, text[0]);
@@ -264,11 +262,37 @@ smartypants_cb__dquote(struct buf *ob, struct smartypants_data *smrt, char previ
static size_t
smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)
{
- size_t i = 0;
+ static const char *skip_tags[] = {"pre", "code", "kbd", "script"};
+ static const size_t skip_tags_count = 4;
+
+ size_t tag, i = 0;
while (i < size && text[i] != '>')
i++;
+ for (tag = 0; tag < skip_tags_count; ++tag) {
+ if (sdhtml_tag(text, size, skip_tags[tag]) == HTML_TAG_OPEN)
+ break;
+ }
+
+ if (tag < skip_tags_count) {
+ for (;;) {
+ while (i < size && text[i] != '<')
+ i++;
+
+ if (i == size)
+ break;
+
+ if (sdhtml_tag(text + i, size - i, skip_tags[tag]) == HTML_TAG_CLOSE)
+ break;
+
+ i++;
+ }
+
+ while (i < size && text[i] != '>')
+ i++;
+ }
+
bufput(ob, text, i + 1);
return i;
}
@@ -304,7 +328,7 @@ static struct {
#endif
void
-upshtml_smartypants(struct buf *ob, struct buf *text)
+sdhtml_smartypants(struct buf *ob, struct buf *text)
{
size_t i;
struct smartypants_data smrt = {0, 0};
View
436 src/markdown.c
@@ -145,13 +145,14 @@ static struct html_tag block_tags[] = {
{ "h6", 2 },
{ "ol", 2 },
{ "ul", 2 },
-/*10*/ { "del", 3 },
+ { "del", 3 }, /* 10 */
{ "div", 3 },
-/*12*/ { "ins", 3 },
+ { "ins", 3 }, /* 12 */
{ "pre", 3 },
{ "form", 4 },
{ "math", 4 },
{ "table", 5 },
+ { "figure", 6 },
{ "iframe", 6 },
{ "script", 6 },
{ "fieldset", 8 },
@@ -165,28 +166,6 @@ static struct html_tag block_tags[] = {
/***************************
* HELPER FUNCTIONS *
***************************/
-int
-is_safe_link(const char *link, size_t link_len)
-{
- static const size_t valid_uris_count = 4;
- static const char *valid_uris[] = {
- "http://", "https://", "ftp://", "mailto://"
- };
-
- size_t i;
-
- for (i = 0; i < valid_uris_count; ++i) {
- size_t len = strlen(valid_uris[i]);
-
- if (link_len > len &&
- strncasecmp(link, valid_uris[i], len) == 0 &&
- isalnum(link[len]))
- return 1;
- }
-
- return 0;
-}
-
static void
unscape_text(struct buf *ob, struct buf *src)
{
@@ -246,7 +225,7 @@ find_block_tag(char *data, size_t size)
while (i < size && ((data[i] >= '0' && data[i] <= '9')
|| (data[i] >= 'A' && data[i] <= 'Z')
|| (data[i] >= 'a' && data[i] <= 'z')))
- i += 1;
+ i++;
if (i >= size) return 0;
/* binary search of the tag */
@@ -339,7 +318,7 @@ tag_length(char *data, size_t size, enum mkd_autolink *autolink)
if (data[i] == '\\') i += 2;
else if (data[i] == '>' || data[i] == '\'' ||
data[i] == '"' || isspace(data[i])) break;
- else i += 1;
+ else i++;
}
if (i >= size) return 0;
@@ -349,7 +328,7 @@ tag_length(char *data, size_t size, enum mkd_autolink *autolink)
}
/* looking for sometinhg looking like a tag end */
- while (i < size && data[i] != '>') i += 1;
+ while (i < size && data[i] != '>') i++;
if (i >= size) return 0;
return i + 1;
}
@@ -401,47 +380,72 @@ find_emph_char(char *data, size_t size, char c)
size_t i = 1;
while (i < size) {
- while (i < size && data[i] != c
- && data[i] != '`' && data[i] != '[')
- i += 1;
- if (data[i] == c) return i;
+ while (i < size && data[i] != c && data[i] != '`' && data[i] != '[')
+ i++;
+
+ if (i == size)
+ return 0;
+
+ if (data[i] == c)
+ return i;
/* not counting escaped chars */
- if (i && data[i - 1] == '\\') { i += 1; continue; }
+ if (i && data[i - 1] == '\\') {
+ i++; continue;
+ }
/* skipping a code span */
if (data[i] == '`') {
size_t tmp_i = 0;
- i += 1;
+
+ i++;
while (i < size && data[i] != '`') {
if (!tmp_i && data[i] == c) tmp_i = i;
- i += 1; }
- if (i >= size) return tmp_i;
- i += 1; }
+ i++;
+ }
+
+ if (i >= size)
+ return tmp_i;
+ i++;
+ }
/* skipping a link */
else if (data[i] == '[') {
size_t tmp_i = 0;
char cc;
- i += 1;
+
+ i++;
while (i < size && data[i] != ']') {
if (!tmp_i && data[i] == c) tmp_i = i;
- i += 1; }
- i += 1;
- while (i < size && (data[i] == ' '
- || data[i] == '\t' || data[i] == '\n'))
- i += 1;
- if (i >= size) return tmp_i;
+ i++;
+ }
+
+ i++;
+ while (i < size && (data[i] == ' ' || data[i] == '\t' || data[i] == '\n'))
+ i++;
+
+ if (i >= size)
+ return tmp_i;
+
if (data[i] != '[' && data[i] != '(') { /* not a link*/
if (tmp_i) return tmp_i;
- else continue; }
+ else continue;
+ }
+
cc = data[i];
- i += 1;
+ i++;
while (i < size && data[i] != cc) {
if (!tmp_i && data[i] == c) tmp_i = i;
- i += 1; }
- if (i >= size) return tmp_i;
- i += 1; } }
+ i++;
+ }
+
+ if (i >= size)
+ return tmp_i;
+
+ i++;
+ }
+ }
+
return 0;
}
@@ -466,7 +470,7 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c
if (i >= size) return 0;
if (i + 1 < size && data[i + 1] == c) {
- i += 1;
+ i++;
continue;
}
@@ -690,7 +694,7 @@ char_entity(struct buf *ob, struct render *rndr, char *data, size_t offset, size
end++;
if (end < size && data[end] == ';')
- end += 1; /* real entity */
+ end++; /* real entity */
else
return 0; /* lone '&' */
@@ -731,236 +735,68 @@ char_langle_tag(struct buf *ob, struct render *rndr, char *data, size_t offset,
}
static size_t
-autolink_delim(char *data, size_t link_end, size_t offset, size_t size)
-{
- char cclose, copen = 0;
-
- /* See if the link finishes with a punctuation sign that can be skipped. */
- switch (data[link_end - 1]) {
- case '?':
- case '!':
- case '.':
- case ',':
- link_end--;
- break;
-
- case ';':
- {
- 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--;
-
- break;
- }
-
- case '>':
- while (link_end > 0 && data[link_end] != '<')
- link_end--;
-
- if (link_end == 0)
- return 0;
-
- break;
- }
-
- 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
char_autolink_www(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
{
- struct buf work = { 0, 0, 0, 0, 0 };
- size_t link_end;
- int np = 0;
-
- if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
- return 0;
-
- if (size < 4 || memcmp(data, "www.", STRLEN("www.")) != 0)
- return 0;
-
- link_end = 0;
- while (link_end < size && !isspace(data[link_end])) {
- if (data[link_end] == '.')
- np++;
-
- link_end++;
- }
-
- if (np < 2)
- return 0;
-
- link_end = autolink_delim(data, link_end, offset, size);
+ struct buf *link, *link_url;
+ size_t link_len, rewind;
- if (link_end == 0)
+ if (!rndr->make.link)
return 0;
- work.size = link_end;
- work.data = data;
+ link = rndr_newbuf(rndr, BUFFER_SPAN);
- if (rndr->make.link) {
- struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
- BUFPUTSL(u_link, "http://");
- unscape_text(u_link, &work);
+ if ((link_len = sd_autolink__www(&rewind, link, data, offset, size)) > 0) {
+ link_url = rndr_newbuf(rndr, BUFFER_SPAN);
+ BUFPUTSL(link_url, "http://");
+ bufput(link_url, link->data, link->size);
- rndr->make.link(ob, u_link, NULL, &work, rndr->make.opaque);
+ ob->size -= rewind;
+ rndr->make.link(ob, link_url, NULL, link, rndr->make.opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
}
- return link_end;
+ rndr_popbuf(rndr, BUFFER_SPAN);
+ return link_len;
}
static size_t
char_autolink_email(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
{
- struct buf work = { 0, 0, 0, 0, 0 };
- size_t link_end, rewind;
- int nb = 0, np = 0;
-
- for (rewind = 0; rewind < offset; ++rewind) {
- char c = data[-rewind - 1];
-
- if (isalnum(c))
- continue;
-
- if (strchr(".+-_", c) != NULL)
- continue;
-
- break;
- }
-
- if (rewind == 0)
- return 0;
-
- for (link_end = 0; link_end < size; ++link_end) {
- char 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)
- return 0;
-
- link_end = autolink_delim(data, link_end, offset, size);
+ struct buf *link;
+ size_t link_len, rewind;
- if (link_end == 0)
+ if (!rndr->make.autolink)
return 0;
- work.size = link_end + rewind;
- work.data = data - rewind;
-
- if (rndr->make.autolink) {
- struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
- unscape_text(u_link, &work);
+ link = rndr_newbuf(rndr, BUFFER_SPAN);
+ if ((link_len = sd_autolink__email(&rewind, link, data, offset, size)) > 0) {
ob->size -= rewind;
- rndr->make.autolink(ob, u_link, MKDA_EMAIL, rndr->make.opaque);
- rndr_popbuf(rndr, BUFFER_SPAN);
- }
+ rndr->make.autolink(ob, link, MKDA_EMAIL, rndr->make.opaque);
+ }
- return link_end;
+ rndr_popbuf(rndr, BUFFER_SPAN);
+ return link_len;
}
static size_t
char_autolink_url(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
{
- struct buf work = { 0, 0, 0, 0, 0 };
- size_t link_end, rewind = 0;
-
- if (size < 4 || data[1] != '/' || data[2] != '/')
- return 0;
-
- while (rewind < offset && isalpha(data[-rewind - 1]))
- rewind++;
-
- if (!is_safe_link(data - rewind, size + rewind))
- return 0;
-
- link_end = 0;
- while (link_end < size && !isspace(data[link_end]))
- link_end++;
-
- link_end = autolink_delim(data, link_end, offset, size);
+ struct buf *link;
+ size_t link_len, rewind;
- if (link_end == 0)
+ if (!rndr->make.autolink)
return 0;
- work.size = link_end + rewind;
- work.data = data - rewind;
-
- if (rndr->make.autolink) {
- struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
- unscape_text(u_link, &work);
+ link = rndr_newbuf(rndr, BUFFER_SPAN);
+ if ((link_len = sd_autolink__url(&rewind, link, data, offset, size)) > 0) {
ob->size -= rewind;
- rndr->make.autolink(ob, u_link, MKDA_NORMAL, rndr->make.opaque);
- rndr_popbuf(rndr, BUFFER_SPAN);
+ rndr->make.autolink(ob, link, MKDA_NORMAL, rndr->make.opaque);
}
- return link_end;
+ rndr_popbuf(rndr, BUFFER_SPAN);
+ return link_len;
}
/* char_link • '[': parsing a link or an image */
@@ -981,7 +817,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
goto cleanup;
/* looking for the matching closing bracket */
- for (level = 1; i < size; i += 1) {
+ for (level = 1; i < size; i++) {
if (data[i] == '\n')
text_has_nl = 1;
@@ -1002,7 +838,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
goto cleanup;
txt_e = i;
- i += 1;
+ i++;
/* skip any amount of whitespace or newline */
/* (this is much more laxist than original markdown syntax) */
@@ -1012,7 +848,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
/* inline style link */
if (i < size && data[i] == '(') {
/* skipping initial whitespace */
- i += 1;
+ i++;
while (i < size && isspace(data[i]))
i++;
@@ -1023,7 +859,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
while (i < size) {
if (data[i] == '\\') i += 2;
else if (data[i] == ')' || data[i] == '\'' || data[i] == '"') break;
- else i += 1;
+ else i++;
}
if (i >= size) goto cleanup;
@@ -1037,7 +873,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
while (i < size) {
if (data[i] == '\\') i += 2;
else if (data[i] == ')') break;
- else i += 1;
+ else i++;
}
if (i >= size) goto cleanup;
@@ -1082,7 +918,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
struct link_ref *lr;
/* looking for the id */
- i += 1;
+ i++;
link_b = i;
while (i < size && data[i] != ']') i++;
if (i >= size) goto cleanup;
@@ -1118,7 +954,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
/* keeping link and title from link_ref */
link = lr->link;
title = lr->title;
- i += 1;
+ i++;
}
/* shortcut reference style link */
@@ -1196,7 +1032,7 @@ static size_t
is_empty(char *data, size_t size)
{
size_t i;
- for (i = 0; i < size && data[i] != '\n'; i += 1)
+ for (i = 0; i < size && data[i] != '\n'; i++)
if (data[i] != ' ' && data[i] != '\t') return 0;
return i + 1;
}
@@ -1210,9 +1046,9 @@ is_hrule(char *data, size_t size)
/* skipping initial spaces */
if (size < 3) return 0;
- if (data[0] == ' ') { i += 1;
- if (data[1] == ' ') { i += 1;
- if (data[2] == ' ') { i += 1; } } }
+ if (data[0] == ' ') { i++;
+ if (data[1] == ' ') { i++;
+ if (data[2] == ' ') { i++; } } }
/* looking at the hrule char */
if (i + 2 >= size
@@ -1222,10 +1058,10 @@ is_hrule(char *data, size_t size)
/* the whole line must be the char or whitespace */
while (i < size && data[i] != '\n') {
- if (data[i] == c) n += 1;
+ if (data[i] == c) n++;
else if (data[i] != ' ' && data[i] != '\t')
return 0;
- i += 1; }
+ i++; }
return n >= 3;
}
@@ -1239,9 +1075,9 @@ is_codefence(char *data, size_t size, struct buf *syntax)
/* skipping initial spaces */
if (size < 3) return 0;
- if (data[0] == ' ') { i += 1;
- if (data[1] == ' ') { i += 1;
- if (data[2] == ' ') { i += 1; } } }
+ if (data[0] == ' ') { i++;
+ if (data[1] == ' ') { i++;
+ if (data[2] == ' ') { i++; } } }
/* looking at the hrule char */
if (i + 2 >= size || !(data[i] == '~' || data[i] == '`'))
@@ -1332,14 +1168,14 @@ is_headerline(char *data, size_t size)
/* test of level 1 header */
if (data[i] == '=') {
- for (i = 1; i < size && data[i] == '='; i += 1);
- while (i < size && (data[i] == ' ' || data[i] == '\t')) i += 1;
+ for (i = 1; i < size && data[i] == '='; i++);
+ while (i < size && (data[i] == ' ' || data[i] == '\t')) 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 += 1);
- while (i < size && (data[i] == ' ' || data[i] == '\t')) i += 1;
+ for (i = 1; i < size && data[i] == '-'; i++);
+ while (i < size && (data[i] == ' ' || data[i] == '\t')) i++;
return (i >= size || data[i] == '\n') ? 2 : 0; }
return 0;
@@ -1350,9 +1186,9 @@ static size_t
prefix_quote(char *data, size_t size)
{
size_t i = 0;
- if (i < size && data[i] == ' ') i += 1;
- if (i < size && data[i] == ' ') i += 1;
- if (i < size && data[i] == ' ') i += 1;
+ 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'))
return i + 2;
@@ -1375,11 +1211,11 @@ static size_t
prefix_oli(char *data, size_t size)
{
size_t i = 0;
- if (i < size && data[i] == ' ') i += 1;
- if (i < size && data[i] == ' ') i += 1;
- if (i < size && data[i] == ' ') i += 1;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
if (i >= size || data[i] < '0' || data[i] > '9') return 0;
- while (i < size && data[i] >= '0' && data[i] <= '9') i += 1;
+ while (i < size && data[i] >= '0' && data[i] <= '9') i++;
if (i + 1 >= size || data[i] != '.'
|| (data[i + 1] != ' ' && data[i + 1] != '\t')) return 0;
return i + 2;
@@ -1390,9 +1226,9 @@ static size_t
prefix_uli(char *data, size_t size)
{
size_t i = 0;
- if (i < size && data[i] == ' ') i += 1;
- if (i < size && data[i] == ' ') i += 1;
- if (i < size && data[i] == ' ') i += 1;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
+ if (i < size && data[i] == ' ') i++;
if (i + 1 >= size
|| (data[i] != '*' && data[i] != '+' && data[i] != '-')
|| (data[i + 1] != ' ' && data[i + 1] != '\t'))
@@ -1553,7 +1389,7 @@ parse_fencedcode(struct buf *ob, struct render *rndr, char *data, size_t size)
break;
}
- for (end = beg + 1; end < size && data[end - 1] != '\n'; end += 1);
+ for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
if (beg < end) {
/* verbatim copy to the working buffer,
@@ -1867,10 +1703,10 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
if (size > 4 && (data[1] == 'h' || data[1] == 'H') && (data[2] == 'r' || data[2] == 'R')) {
i = 3;
while (i < size && data[i] != '>')
- i += 1;
+ i++;
if (i + 1 < size) {
- i += 1;
+ i++;
j = is_empty(data + i, size - i);
if (j) {
work.size = i + j;
@@ -2181,34 +2017,34 @@ is_ref(char *data, size_t beg, size_t end, size_t *last, struct array *refs)
/* id part: anything but a newline between brackets */
if (data[i] != '[') return 0;
- i += 1;
+ i++;
id_offset = i;
while (i < end && data[i] != '\n' && data[i] != '\r' && data[i] != ']')
- i += 1;
+ i++;
if (i >= end || data[i] != ']') return 0;
id_end = i;
/* spacer: colon (space | tab)* newline? (space | tab)* */
- i += 1;
+ i++;
if (i >= end || data[i] != ':') return 0;
- i += 1;
- while (i < end && (data[i] == ' ' || data[i] == '\t')) i += 1;
+ i++;
+ while (i < end && (data[i] == ' ' || data[i] == '\t')) i++;
if (i < end && (data[i] == '\n' || data[i] == '\r')) {
- i += 1;
- if (i < end && data[i] == '\r' && data[i - 1] == '\n') i += 1; }
- while (i < end && (data[i] == ' ' || data[i] == '\t')) i += 1;
+ i++;
+ if (i < end && data[i] == '\r' && data[i - 1] == '\n') i++; }
+ while (i < end && (data[i] == ' ' || data[i] == '\t')) i++;
if (i >= end) return 0;
/* link: whitespace-free sequence, optionally between angle brackets */
- if (data[i] == '<') i += 1;
+ if (data[i] == '<') i++;
link_offset = i;
while (i < end && data[i] != ' ' && data[i] != '\t'
- && data[i] != '\n' && data[i] != '\r') i += 1;
+ && 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 += 1;
+ while (i < end && (data[i] == ' ' || data[i] == '\t')) i++;
if (i < end && data[i] != '\n' && data[i] != '\r'
&& data[i] != '\'' && data[i] != '"' && data[i] != '(')
return 0;
@@ -2221,17 +2057,17 @@ is_ref(char *data, size_t beg, size_t end, size_t *last, struct array *refs)
/* optional (space|tab)* spacer after a newline */
if (line_end) {
i = line_end + 1;
- while (i < end && (data[i] == ' ' || data[i] == '\t')) i += 1; }
+ while (i < end && (data[i] == ' ' || data[i] == '\t')) i++; }
/* optional title: any non-newline sequence enclosed in '"()
alone on its line */
title_offset = title_end = 0;
if (i + 1 < end
&& (data[i] == '\'' || data[i] == '"' || data[i] == '(')) {
- i += 1;
+ i++;
title_offset = i;
/* looking for EOL */
- while (i < end && data[i] != '\n' && data[i] != '\r') i += 1;
+ while (i < end && data[i] != '\n' && data[i] != '\r') i++;
if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
title_end = i + 1;
else title_end = i;
@@ -2292,7 +2128,7 @@ static void expand_tabs(struct buf *ob, const char *line, size_t size)
/* markdown • parses the input buffer and renders it into the output buffer */
void
-ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, unsigned int extensions) {
+sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, unsigned int extensions) {
struct link_ref *lr;
struct buf *text;
size_t i, beg, end;
@@ -2314,7 +2150,7 @@ ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer,
parr_init(&rndr.work_bufs[BUFFER_BLOCK]);
parr_init(&rndr.work_bufs[BUFFER_SPAN]);
- for (i = 0; i < 256; i += 1)
+ for (i = 0; i < 256; i++)
rndr.active_char[i] = 0;
if (rndr.make.emphasis || rndr.make.double_emphasis || rndr.make.triple_emphasis) {
@@ -2355,7 +2191,7 @@ ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer,
else { /* skipping to the next line */
end = beg;
while (end < ib->size && ib->data[end] != '\n' && ib->data[end] != '\r')
- end += 1;
+ end++;
/* adding the line body if present */
if (end > beg)
@@ -2365,7 +2201,7 @@ ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer,
/* add one \n per newline */
if (ib->data[end] == '\n' || (end + 1 < ib->size && ib->data[end + 1] != '\n'))
bufputc(text, '\n');
- end += 1;
+ end++;
}
beg = end;
@@ -2393,7 +2229,7 @@ ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer,
/* clean-up */
bufrelease(text);
lr = rndr.refs.base;
- for (i = 0; i < (size_t)rndr.refs.size; i += 1) {
+ for (i = 0; i < (size_t)rndr.refs.size; i++) {
bufrelease(lr[i].id);
bufrelease(lr[i].link);
bufrelease(lr[i].title);
@@ -2415,7 +2251,7 @@ ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer,
}
void
-ups_version(int *ver_major, int *ver_minor, int *ver_revision)
+sd_version(int *ver_major, int *ver_minor, int *ver_revision)
{
*ver_major = UPSKIRT_VER_MAJOR;
*ver_minor = UPSKIRT_VER_MINOR;
View
15 src/markdown.h
@@ -20,6 +20,7 @@
#define UPSKIRT_MARKDOWN_H
#include "buffer.h"
+#include "autolink.h"
#define UPSKIRT_VERSION "1.15.2"
#define UPSKIRT_VER_MAJOR 1
@@ -99,23 +100,17 @@ struct mkd_renderer {
#define MKD_TABLE_ALIGN_R (1 << 1)
#define MKD_TABLE_ALIGN_CENTER (MKD_TABLE_ALIGN_L | MKD_TABLE_ALIGN_R)
-/*******************
- * Auxiliar methods
- *******************/
-int
-is_safe_link(const char *link, size_t link_len);
-
/**********************
* EXPORTED FUNCTIONS *
**********************/
-/* ups_markdown * parses the input buffer and renders it into the output buffer */
+/* sd_markdown * parses the input buffer and renders it into the output buffer */
extern void
-ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndr, unsigned int extensions);
+sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndr, unsigned int extensions);
-/* ups_version * returns the library version as major.minor.rev */
+/* sd_version * returns the library version as major.minor.rev */
extern void
-ups_version(int *major, int *minor, int *revision);
+sd_version(int *major, int *minor, int *revision);
#endif
View
24 src/php_phpskirt.h
@@ -1,24 +0,0 @@
-#ifndef PHP_PHPSKIRT_H
-
-#define PHP_PHPSKIRT_H
-
-#define PHP_PHPSKIRT_EXTNAME "phpskirt"
-#define PHP_PHPSKIRT_EXTVER "0.1"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "markdown.h"
-#include "html.h"
-
-/* Define the entry point symbol
- * Zend will use when loading this module
- */
-extern zend_module_entry phpskirt_module_entry;
-#define phpext_phpskirt_ptr &phpskirt_module_entry;
-
-extern zend_class_entry *phpskirt_class_entry;
-
-#endif /* PHP_PHPSKIRT_H */
View
142 src/phpskirt.c → src/php_sundown.c
@@ -22,118 +22,117 @@
* THE SOFTWARE.
*/
-#include "php_phpskirt.h"
+#include "php_sundown.h"
-zend_class_entry *phpskirt_class_entry;
+zend_class_entry *sundown_class_entry;
-void php_phpskirt_init(TSRMLS_D);
+void php_sundown_init(TSRMLS_D);
typedef enum
{
- PHPSKIRT_RENDER_HTML,
- PHPSKIRT_RENDER_TOC
-} PHPSkirtRendererType;
+ SUNDOWN_RENDER_HTML,
+ SUNDOWN_RENDER_TOC
+} SundownRendererType;
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_phpskirt__construct, 0, 0, 2)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sundown__construct, 0, 0, 2)
ZEND_ARG_INFO(0, data)
ZEND_ARG_ARRAY_INFO(0, extensions, 0)
ZEND_END_ARG_INFO()
-#define PHPSKIRT_HAS_EXTENSION(name) (table != NULL && zend_hash_exists(table, name,strlen(name)+1) == 1)
+#define SUNDOWN_HAS_EXTENSION(name) (table != NULL && zend_hash_exists(table, name,strlen(name)+1) == 1)
-static void php_phpskirt__get_flags(HashTable *table, unsigned int *enabled_extensions_p, unsigned int *render_flags_p)
+static void php_sundown__get_flags(HashTable *table, unsigned int *enabled_extensions_p, unsigned int *render_flags_p)
{
TSRMLS_FETCH();
unsigned int render_flags = HTML_EXPAND_TABS;
unsigned int extensions = 0;
/* filter_html */
- if (PHPSKIRT_HAS_EXTENSION("filter_html")) {
+ if (SUNDOWN_HAS_EXTENSION("filter_html")) {
render_flags |= HTML_SKIP_HTML;
}
/* no_image */
- if (PHPSKIRT_HAS_EXTENSION("no_image")) {
+ if (SUNDOWN_HAS_EXTENSION("no_image")) {
render_flags |= HTML_SKIP_IMAGES;
}
/* no_links */
- if (PHPSKIRT_HAS_EXTENSION("no_links")) {
+ if (SUNDOWN_HAS_EXTENSION("no_links")) {
render_flags |= HTML_SKIP_LINKS;
}
/* filter_style */
- if (PHPSKIRT_HAS_EXTENSION("filter_styles")) {
+ if (SUNDOWN_HAS_EXTENSION("filter_styles")) {
render_flags |= HTML_SKIP_STYLE;
}
/* safelink */
- if (PHPSKIRT_HAS_EXTENSION("safelink")) {
+ if (SUNDOWN_HAS_EXTENSION("safelink")) {
render_flags |= HTML_SAFELINK;
}
- if (PHPSKIRT_HAS_EXTENSION("generate_toc")) {
+ if (SUNDOWN_HAS_EXTENSION("generate_toc")) {
render_flags |= HTML_TOC;
}
- if (PHPSKIRT_HAS_EXTENSION("hard_wrap")) {
+ if (SUNDOWN_HAS_EXTENSION("hard_wrap")) {
render_flags |= HTML_HARD_WRAP;
}
- if (PHPSKIRT_HAS_EXTENSION("gh_blockcode")) {
+ if (SUNDOWN_HAS_EXTENSION("gh_blockcode")) {
render_flags |= HTML_GITHUB_BLOCKCODE;
}
- if (PHPSKIRT_HAS_EXTENSION("xhtml")) {
+ if (SUNDOWN_HAS_EXTENSION("xhtml")) {
render_flags |= HTML_USE_XHTML;
}
/**
* Markdown extensions -- all disabled by default
*/
- if (PHPSKIRT_HAS_EXTENSION("autolink")) {
+ if (SUNDOWN_HAS_EXTENSION("autolink")) {
extensions |= MKDEXT_AUTOLINK;
}
- if (PHPSKIRT_HAS_EXTENSION("no_intraemphasis")) {
+ if (SUNDOWN_HAS_EXTENSION("no_intraemphasis")) {
extensions |= MKDEXT_NO_INTRA_EMPHASIS;
}
- if (PHPSKIRT_HAS_EXTENSION("tables")) {
+ if (SUNDOWN_HAS_EXTENSION("tables")) {
extensions |= MKDEXT_TABLES;
}
- if (PHPSKIRT_HAS_EXTENSION("fenced_code")) {
+ if (SUNDOWN_HAS_EXTENSION("fenced_code")) {
extensions |= MKDEXT_FENCED_CODE;
}
- if (PHPSKIRT_HAS_EXTENSION("strikethrough")) {
+ if (SUNDOWN_HAS_EXTENSION("strikethrough")) {
extensions |= MKDEXT_STRIKETHROUGH;
}
- if (PHPSKIRT_HAS_EXTENSION("lax_htmlblock")) {
+ if (SUNDOWN_HAS_EXTENSION("lax_htmlblock")) {
extensions |= MKDEXT_LAX_HTML_BLOCKS;
}
- if (PHPSKIRT_HAS_EXTENSION("space_header")) {
+ if (SUNDOWN_HAS_EXTENSION("space_header")) {
extensions |= MKDEXT_SPACE_HEADERS;
}
*enabled_extensions_p = extensions;
*render_flags_p = render_flags;
}
-static void phpskirt__render(PHPSkirtRendererType render_type, INTERNAL_FUNCTION_PARAMETERS)
+static void sundown__render(SundownRendererType render_type, INTERNAL_FUNCTION_PARAMETERS)
{
struct buf input_buf, *output_buf;
- struct mkd_renderer phpskirt_render;
+ struct mkd_renderer sundown_render;
unsigned int enabled_extensions = 0, render_flags = 0;
char *buffer;
int buffer_len = 0;
HashTable *table;
- buffer = Z_STRVAL_P(zend_read_property(phpskirt_class_entry, getThis(),"data",sizeof("data")-1, 0 TSRMLS_CC));
+ buffer = Z_STRVAL_P(zend_read_property(sundown_class_entry, getThis(),"data",sizeof("data")-1, 0 TSRMLS_CC));
buffer_len = strlen(buffer);
memset(&input_buf, 0x0, sizeof(struct buf));
@@ -143,40 +142,40 @@ static void phpskirt__render(PHPSkirtRendererType render_type, INTERNAL_FUNCTION
output_buf = bufnew(128);
bufgrow(output_buf, strlen(buffer) * 1.2f);
- if(Z_TYPE_P(zend_read_property(phpskirt_class_entry, getThis(),"extensions",sizeof("extensions")-1, 0 TSRMLS_CC)) != IS_NULL) {
- table = Z_ARRVAL_P(zend_read_property(phpskirt_class_entry, getThis(),"extensions",sizeof("extensions")-1, 0 TSRMLS_CC));
+ if(Z_TYPE_P(zend_read_property(sundown_class_entry, getThis(),"extensions",sizeof("extensions")-1, 0 TSRMLS_CC)) != IS_NULL) {
+ table = Z_ARRVAL_P(zend_read_property(sundown_class_entry, getThis(),"extensions",sizeof("extensions")-1, 0 TSRMLS_CC));
}
- php_phpskirt__get_flags(table, &enabled_extensions, &render_flags);
+ php_sundown__get_flags(table, &enabled_extensions, &render_flags);
switch (render_type) {
- case PHPSKIRT_RENDER_HTML:
- upshtml_renderer(&phpskirt_render, render_flags);
+ case SUNDOWN_RENDER_HTML:
+ sdhtml_renderer(&sundown_render, render_flags,NULL);
break;
- case PHPSKIRT_RENDER_TOC:
- upshtml_toc_renderer(&phpskirt_render);
+ case SUNDOWN_RENDER_TOC:
+ sdhtml_toc_renderer(&sundown_render,NULL);
break;
default:
RETURN_FALSE;
}
- ups_markdown(output_buf, &input_buf, &phpskirt_render, enabled_extensions);
+ sd_markdown(output_buf, &input_buf, &sundown_render, enabled_extensions);
- if (Z_BVAL_P(zend_read_property(phpskirt_class_entry, getThis(),"enable_pants",sizeof("enable_pants")-1, 0 TSRMLS_CC))) {
+ if (Z_BVAL_P(zend_read_property(sundown_class_entry, getThis(),"enable_pants",sizeof("enable_pants")-1, 0 TSRMLS_CC))) {
struct buf *smart_buf = bufnew(128);
- upshtml_smartypants(smart_buf, output_buf);
+ sdhtml_smartypants(smart_buf, output_buf);
RETVAL_STRINGL(smart_buf->data, smart_buf->size,1);
bufrelease(smart_buf);
} else {
RETVAL_STRINGL(output_buf->data, output_buf->size,1);
}
bufrelease(output_buf);
- upshtml_free_renderer(&phpskirt_render);
+ sdhtml_free_renderer(&sundown_render);
}
/* {{{ proto string __construct(string $string [, array $extensions])
- setup Upskirt extension */
-PHP_METHOD(phpskirt, __construct)
+ setup Sundown extension */
+PHP_METHOD(sundown, __construct)
{
zval *extensions = NULL;
char *buffer;
@@ -198,11 +197,11 @@ PHP_METHOD(phpskirt, __construct)
/* {{{ proto void __destruct()
cleanup variables */
-PHP_METHOD(phpskirt, __destruct)
+PHP_METHOD(sundown, __destruct)
{
zval *extensions;
- extensions = zend_read_property(phpskirt_class_entry, getThis(),"extensions",sizeof("extensions")-1, 0 TSRMLS_CC);
+ extensions = zend_read_property(sundown_class_entry, getThis(),"extensions",sizeof("extensions")-1, 0 TSRMLS_CC);
if(extensions != NULL && Z_TYPE_P(extensions) != IS_NULL) {
zval_ptr_dtor(&extensions);
}
@@ -211,76 +210,75 @@ PHP_METHOD(phpskirt, __destruct)
/* {{{ proto string to_html()
Returns converted HTML string */
-PHP_METHOD(phpskirt, to_html)
+PHP_METHOD(sundown, to_html)
{
- phpskirt__render(PHPSKIRT_RENDER_HTML,INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ sundown__render(SUNDOWN_RENDER_HTML,INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto string __toString()
Returns converted HTML string */
-PHP_METHOD(phpskirt, __toString)
+PHP_METHOD(sundown, __toString)
{
- phpskirt__render(PHPSKIRT_RENDER_HTML,INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ sundown__render(SUNDOWN_RENDER_HTML,INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto string to_toc()
Returns table of contents*/
-PHP_METHOD(phpskirt, to_toc)
+PHP_METHOD(sundown, to_toc)
{
- phpskirt__render(PHPSKIRT_RENDER_TOC,INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ sundown__render(SUNDOWN_RENDER_TOC,INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
-static function_entry php_phpskirt_methods[] = {
- PHP_ME(phpskirt, __construct, arginfo_phpskirt__construct, ZEND_ACC_PUBLIC)
- PHP_ME(phpskirt, __destruct, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(phpskirt, to_html, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(phpskirt, to_toc, NULL, ZEND_ACC_PUBLIC)
- PHP_ME(phpskirt, __toString, NULL, ZEND_ACC_PUBLIC)
+static function_entry php_sundown_methods[] = {
+ PHP_ME(sundown, __construct, arginfo_sundown__construct, ZEND_ACC_PUBLIC)
+ PHP_ME(sundown, __destruct, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(sundown, to_html, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(sundown, to_toc, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(sundown, __toString, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
/* }}} */
-PHP_MINIT_FUNCTION(phpskirt) {
- php_phpskirt_init(TSRMLS_C);
+PHP_MINIT_FUNCTION(sundown) {
+ php_sundown_init(TSRMLS_C);
return SUCCESS;
}
-PHP_MINFO_FUNCTION(phpskirt)
+PHP_MINFO_FUNCTION(sundown)
{
- return SUCCESS;
}
-zend_module_entry phpskirt_module_entry = {
+zend_module_entry sundown_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
- "phpskirt",
+ "sundown",
NULL, /* Functions */
- PHP_MINIT(phpskirt), /* MINIT */
+ PHP_MINIT(sundown), /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
- PHP_MINFO(phpskirt), /* MINFO */
+ PHP_MINFO(sundown), /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901
- PHP_PHPSKIRT_EXTVER,
+ PHP_SUNDOWN_EXTVER,
#endif
STANDARD_MODULE_PROPERTIES
};
-void php_phpskirt_init(TSRMLS_D)
+void php_sundown_init(TSRMLS_D)
{
zend_class_entry ce;
- INIT_CLASS_ENTRY(ce, "Upskirt", php_phpskirt_methods);
- phpskirt_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
- zend_declare_property_null(phpskirt_class_entry, "extensions", sizeof("extensions")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
- zend_declare_property_null(phpskirt_class_entry, "enable_pants", sizeof("enable_pants")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
+ INIT_CLASS_ENTRY(ce, "Sundown", php_sundown_methods);
+ sundown_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
+ zend_declare_property_null(sundown_class_entry, "extensions", sizeof("extensions")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
+ zend_declare_property_null(sundown_class_entry, "enable_pants", sizeof("enable_pants")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
}
-#ifdef COMPILE_DL_PHPSKIRT
-ZEND_GET_MODULE(phpskirt)
+#ifdef COMPILE_DL_SUNDOWN
+ZEND_GET_MODULE(sundown)
#endif
View
24 src/php_sundown.h
@@ -0,0 +1,24 @@
+#ifndef PHP_SUNDOWN_H
+
+#define PHP_SUNDOWN_H
+
+#define PHP_SUNDOWN_EXTNAME "sundown"
+#define PHP_SUNDOWN_EXTVER "0.1"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "markdown.h"
+#include "html.h"
+
+/* Define the entry point symbol
+ * Zend will use when loading this module
+ */
+extern zend_module_entry sundown_module_entry;
+#define phpext_sundown_ptr &sundown_module_entry;
+
+extern zend_class_entry *sundown_class_entry;
+
+#endif /* PHP_SUNDOWN_H */
View
8 src/tests/001.phpt
@@ -1,9 +1,9 @@
--TEST--
-Check for phpskirt presence
+Check for sundown presence
--SKIPIF--
-<?php if (!extension_loaded("phpskirt")) print "skip"; ?>
+<?php if (!extension_loaded("sundown")) print "skip"; ?>
--FILE--
<?php
-echo "phpskirt extension is available";
+echo "sundown extension is available";
--EXPECT--
-phpskirt extension is available
+sundown extension is available
View
8 src/tests/002-constructor-arguments.phpt
@@ -1,14 +1,14 @@
--TEST--
-Check for Upskirt::__construct arguments
+Check for Sundown::__construct arguments
--SKIPIF--
-<?php if (!extension_loaded("phpskirt")) print "skip"; ?>
+<?php if (!extension_loaded("sundown")) print "skip"; ?>
--FILE--
<?php
-$a = new Upskirt('a');
+$a = new Sundown('a');
if (is_array($a->extensions) && is_null($a->enable_pants) && $a->data == 'a') {
echo "OK" .PHP_EOL;
}
-$a = new Upskirt('a',array('autolink'=>true));
+$a = new Sundown('a',array('autolink'=>true));
if (isset($a->extensions['autolink']) && is_null($a->enable_pants) && $a->data == 'a') {
echo "OK" .PHP_EOL;
}
View
6 src/tests/003-to_html.phpt
@@ -1,14 +1,14 @@
--TEST--
-Check for Upskirt::to_html() feature
+Check for Sundown::to_html() feature
--SKIPIF--
-<?php if (!extension_loaded("phpskirt")) print "skip"; ?>
+<?php if (!extension_loaded("sundown")) print "skip"; ?>
--FILE--
<?php
$data = <<<EOF
* Hello World
EOF;
-$a = new Upskirt($data);
+$a = new Sundown($data);
// list
echo $a->to_html();
--EXPECT--
1 sundown
@@ -0,0 +1 @@
+Subproject commit 170a164b716f782d71136b7e4c0a44972f395426

0 comments on commit 19b8b2d

Please sign in to comment.
Something went wrong with that request. Please try again.