[DRE-commits] [SCM] ruby-redcarpet.git branch, master, updated. debian/2.1.1-3-2-gaa2cd63
Youhei SASAKI
uwabami at gfd-dennou.org
Thu Jan 17 12:55:05 UTC 2013
The following commit has been merged in the master branch:
commit 3fea53c6d94bdc6607bf2616fae9c7a17e9e7138
Author: Youhei SASAKI <uwabami at gfd-dennou.org>
Date: Thu Jan 17 21:45:01 2013 +0900
Imported Upstream version 2.2.2
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..e45e65f
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,2 @@
+source :rubygems
+gemspec
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..3605ca0
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,20 @@
+PATH
+ remote: .
+ specs:
+ redcarpet (2.1.1)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ nokogiri (1.5.5)
+ rake (0.9.2.2)
+ rake-compiler (0.8.1)
+ rake
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ nokogiri
+ rake-compiler
+ redcarpet!
diff --git a/README.markdown b/README.markdown
index 5bca6a9..0b68c9f 100644
--- a/README.markdown
+++ b/README.markdown
@@ -9,14 +9,14 @@ case since version 2 -- it now has its own API, but retains the old name. Yes,
that does mean that Redcarpet 2 is not backwards-compatible with the 1.X
versions.
-Redcarpet is powered by the [Sundown](https://www.github.com/tanoku/sundown)
+Redcarpet is powered by the [Sundown](https://www.github.com/vmg/sundown)
library. You might want to find out more about Sundown to see what makes this
Ruby library so awesome.
This library is written by people
-------------------------------------------------------
-Redcarpet 2 has been rewritten from scratch by Vicent Martí (@tanoku). Why
+Redcarpet 2 has been rewritten from scratch by Vicent Martí (@vmg). Why
are you not following me on Twitter?
Redcarpet would not be possible without the Sundown library and its authors
@@ -32,7 +32,7 @@ extensions, but the parser is standalone and requires no installed libraries.
The Redcarpet source (including Sundown as a submodule) is available at GitHub:
- $ git clone git://github.com/tanoku/redcarpet.git
+ $ git clone git://github.com/vmg/redcarpet.git
And it's like *really* simple to use
------------------------------------
@@ -78,7 +78,7 @@ settings, and reused between parses.
Two `~` characters mark the start of a strikethrough,
e.g. `this is ~~good~~ bad`
- :lax_html_blocks - HTML blocks do not require to be surrounded
+ :lax_spacing - HTML blocks do not require to be surrounded
by an empty line as in the Markdown standard.
:space_after_headers - A space is always required between the
@@ -126,32 +126,33 @@ instantiating the renderer:
Render::HTML.new(render_options={})
- Initializes an HTML renderer. The following flags are available:
+Initializes an HTML renderer. The following flags are available:
- :filter_html - do not allow any user-inputted HTML in the output
+ :filter_html - do not allow any user-inputted HTML in the output
- :no_images - do not generate any `<img>` tags
+ :no_images - do not generate any `<img>` tags
- :no_links - do not generate any `<a>` tags
+ :no_links - do not generate any `<a>` tags
- :no_styles - do not generate any `<style>` tags
+ :no_styles - do not generate any `<style>` tags
- :safe_links_only - only generate links for protocols which are considered safe
+ :safe_links_only - only generate links for protocols which are considered safe
- :with_toc_data - add HTML anchors to each header in the output HTML,
- to allow linking to each section.
+ :with_toc_data - add HTML anchors to each header in the output HTML,
+ to allow linking to each section.
- :hard_wrap - insert HTML `<br>` tags inside on paragraphs where the origin
- Markdown document had newlines (by default, Markdown ignores these
- newlines).
+ :hard_wrap - insert HTML `<br>` tags inside on paragraphs where the origin
+ Markdown document had newlines (by default, Markdown ignores these
+ newlines).
- :xhtml - output XHTML-conformant tags. This option is always enabled in the
- `Render::XHTML` renderer.
+ :xhtml - output XHTML-conformant tags. This option is always enabled in the
+ `Render::XHTML` renderer.
+ :link_attributes - hash of extra attributes to add to links
- Example:
+Example:
- rndr = Redcarpet::Render::HTML.new(:no_links => true, :hard_wrap => true)
+ rndr = Redcarpet::Render::HTML.new(:no_links => true, :hard_wrap => true)
The `HTML` renderer has an alternate version, `Redcarpet::Render::HTML_TOC`,
@@ -295,7 +296,7 @@ software accordingly, and force your users to install it. That's the
only way to have reliable and predictable Markdown output on your program.
Still, if major forces (let's say, tornadoes or other natural disasters) force you
-to keep a Markdown-compatibility later, Redcarpet also supports this:
+to keep a Markdown-compatibility layer, Redcarpet also supports this:
require 'redcarpet/compat'
@@ -311,6 +312,10 @@ that's a maintance nightmare and won't work.
On a related topic: if your Markdown gem has a `lib/markdown.rb` file that
monkeypatches the Markdown class, you're a terrible human being. Just saying.
+Testing
+-------
+Tests run a lot faster without `bundle exec` :)
+
Boring legal stuff
------------------
diff --git a/Rakefile b/Rakefile
index 3936a10..7c63124 100644
--- a/Rakefile
+++ b/Rakefile
@@ -3,7 +3,7 @@ require 'rake/clean'
require 'rake/extensiontask'
require 'digest/md5'
-task :default => :test
+task :default => [:test]
# ==========================================================
# Ruby Extension
@@ -110,7 +110,7 @@ task :update_gem do
end
desc 'Gather required Sundown sources into extension directory'
-task :gather => 'sundown/src/markdown.h' do |t|
+task :gather => 'sundown:checkout' do |t|
files =
FileList[
'sundown/src/{markdown,buffer,stack,autolink,html_blocks}.h',
@@ -123,8 +123,9 @@ task :gather => 'sundown/src/markdown.h' do |t|
:verbose => true
end
-file 'sundown/src/markdown.h' do |t|
- abort "The Sundown submodule is required."
+task 'sundown:checkout' do |t|
+ unless File.exists?('sundown/src/markdown.h')
+ sh 'git submodule init'
+ sh 'git submodule update'
+ end
end
-
-
diff --git a/ext/redcarpet/autolink.c b/ext/redcarpet/autolink.c
index 1c3a070..b0d2616 100644
--- a/ext/redcarpet/autolink.c
+++ b/ext/redcarpet/autolink.c
@@ -15,12 +15,17 @@
*/
#include "buffer.h"
+#include "autolink.h"
#include <string.h>
#include <stdlib.h>
#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)
{
@@ -44,7 +49,7 @@ sd_autolink_issafe(const uint8_t *link, size_t link_len)
}
static size_t
-autolink_delim(uint8_t *data, size_t link_end, size_t offset, size_t size)
+autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
{
uint8_t cclose, copen = 0;
size_t i;
@@ -128,7 +133,7 @@ autolink_delim(uint8_t *data, size_t link_end, size_t offset, size_t size)
}
static size_t
-check_domain(uint8_t *data, size_t size)
+check_domain(uint8_t *data, size_t size, int allow_short)
{
size_t i, np = 0;
@@ -140,23 +145,37 @@ check_domain(uint8_t *data, size_t size)
else if (!isalnum(data[i]) && data[i] != '-') break;
}
- /* a valid domain needs to have at least a dot.
- * that's as far as we get */
- return np ? i : 0;
+ 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
-sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
+sd_autolink__www(
+ size_t *rewind_p,
+ struct buf *link,
+ uint8_t *data,
+ size_t max_rewind,
+ size_t size,
+ unsigned int flags)
{
size_t link_end;
- if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
+ 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);
+ link_end = check_domain(data, size, 0);
if (link_end == 0)
return 0;
@@ -164,7 +183,7 @@ sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offse
while (link_end < size && !isspace(data[link_end]))
link_end++;
- link_end = autolink_delim(data, link_end, offset, size);
+ link_end = autolink_delim(data, link_end, max_rewind, size);
if (link_end == 0)
return 0;
@@ -176,12 +195,18 @@ sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offse
}
size_t
-sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
+sd_autolink__email(
+ size_t *rewind_p,
+ struct buf *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 < offset; ++rewind) {
+ for (rewind = 0; rewind < max_rewind; ++rewind) {
uint8_t c = data[-rewind - 1];
if (isalnum(c))
@@ -213,7 +238,7 @@ sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t off
if (link_end < 2 || nb != 1 || np == 0)
return 0;
- link_end = autolink_delim(data, link_end, offset, size);
+ link_end = autolink_delim(data, link_end, max_rewind, size);
if (link_end == 0)
return 0;
@@ -225,21 +250,32 @@ sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t off
}
size_t
-sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
+sd_autolink__url(
+ size_t *rewind_p,
+ struct buf *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 < offset && isalpha(data[-rewind - 1]))
+ while (rewind < max_rewind && 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);
+ domain_len = check_domain(
+ data + link_end,
+ size - link_end,
+ flags & SD_AUTOLINK_SHORT_DOMAINS);
+
if (domain_len == 0)
return 0;
@@ -247,7 +283,7 @@ sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offse
while (link_end < size && !isspace(data[link_end]))
link_end++;
- link_end = autolink_delim(data, link_end, offset, size);
+ link_end = autolink_delim(data, link_end, max_rewind, size);
if (link_end == 0)
return 0;
diff --git a/ext/redcarpet/autolink.h b/ext/redcarpet/autolink.h
index df9fd9c..65e0fe6 100644
--- a/ext/redcarpet/autolink.h
+++ b/ext/redcarpet/autolink.h
@@ -19,17 +19,32 @@
#include "buffer.h"
-extern int
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ SD_AUTOLINK_SHORT_DOMAINS = (1 << 0),
+};
+
+int
sd_autolink_issafe(const uint8_t *link, size_t link_len);
-extern size_t
-sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
+size_t
+sd_autolink__www(size_t *rewind_p, struct buf *link,
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
-extern size_t
-sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
+size_t
+sd_autolink__email(size_t *rewind_p, struct buf *link,
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
-extern size_t
-sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
+size_t
+sd_autolink__url(size_t *rewind_p, struct buf *link,
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
+
+#ifdef __cplusplus
+}
+#endif
#endif
diff --git a/ext/redcarpet/buffer.c b/ext/redcarpet/buffer.c
index 3807fb9..47b40ce 100644
--- a/ext/redcarpet/buffer.c
+++ b/ext/redcarpet/buffer.c
@@ -127,7 +127,9 @@ bufprintf(struct buf *buf, const char *fmt, ...)
if (n < 0) {
#ifdef _MSC_VER
+ va_start(ap, fmt);
n = _vscprintf(fmt, ap);
+ va_end(ap);
#else
return;
#endif
diff --git a/ext/redcarpet/buffer.h b/ext/redcarpet/buffer.h
index 8a1eb25..221d142 100644
--- a/ext/redcarpet/buffer.h
+++ b/ext/redcarpet/buffer.h
@@ -22,6 +22,10 @@
#include <stdarg.h>
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#if defined(_MSC_VER)
#define __attribute__(x)
#define inline
@@ -85,4 +89,8 @@ void bufslurp(struct buf *, size_t);
/* bufprintf: formatted printing to a buffer */
void bufprintf(struct buf *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/ext/redcarpet/houdini.h b/ext/redcarpet/houdini.h
index d14147c..b4954c0 100644
--- a/ext/redcarpet/houdini.h
+++ b/ext/redcarpet/houdini.h
@@ -3,6 +3,10 @@
#include "buffer.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ifdef HOUDINI_USE_LOCALE
# define _isxdigit(c) isxdigit(c)
# define _isdigit(c) isdigit(c)
@@ -26,4 +30,8 @@ extern void houdini_unescape_url(struct buf *ob, const uint8_t *src, size_t size
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
diff --git a/ext/redcarpet/html.c b/ext/redcarpet/html.c
index 8c0d468..7f08ee8 100755
--- a/ext/redcarpet/html.c
+++ b/ext/redcarpet/html.c
@@ -491,6 +491,13 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
{
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");
@@ -516,7 +523,7 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
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)
+ if (content && content->size)
bufput(ob, content->data, content->size);
return 1;
}
diff --git a/ext/redcarpet/html.h b/ext/redcarpet/html.h
index 4fbf3f4..4c8810d 100644
--- a/ext/redcarpet/html.h
+++ b/ext/redcarpet/html.h
@@ -21,10 +21,15 @@
#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;
@@ -64,5 +69,9 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *optio
extern void
sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/ext/redcarpet/html_smartypants.c b/ext/redcarpet/html_smartypants.c
index bb4089d..367c26a 100644
--- a/ext/redcarpet/html_smartypants.c
+++ b/ext/redcarpet/html_smartypants.c
@@ -22,6 +22,10 @@
#include <stdio.h>
#include <ctype.h>
+#if defined(_WIN32)
+#define snprintf _snprintf
+#endif
+
struct smartypants_data {
int in_squote;
int in_dquote;
diff --git a/ext/redcarpet/markdown.c b/ext/redcarpet/markdown.c
index 18b1cfb..3253b0f 100644
--- a/ext/redcarpet/markdown.c
+++ b/ext/redcarpet/markdown.c
@@ -25,6 +25,10 @@
#include <ctype.h>
#include <stdio.h>
+#if defined(_WIN32)
+#define strncasecmp _strnicmp
+#endif
+
#define REF_TABLE_SIZE 8
#define BUFFER_BLOCK 0
@@ -497,7 +501,7 @@ parse_emph1(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size
if (data[i] == c && !_isspace(data[i - 1])) {
if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
- if (!(i + 1 == size || _isspace(data[i + 1]) || ispunct(data[i + 1])))
+ if (i + i < size && isalnum(data[i + 1]))
continue;
}
@@ -592,6 +596,11 @@ char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t of
uint8_t c = data[0];
size_t ret;
+ if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
+ if (offset > 0 && !_isspace(data[-1]) && data[-1] != '>')
+ return 0;
+ }
+
if (size > 2 && data[1] != c) {
/* whitespace cannot follow an opening emphasis;
* strikethrough only takes two characters '~~' */
@@ -767,7 +776,7 @@ char_autolink_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_
link = rndr_newbuf(rndr, BUFFER_SPAN);
- if ((link_len = sd_autolink__www(&rewind, link, data, offset, size)) > 0) {
+ if ((link_len = sd_autolink__www(&rewind, link, data, offset, size, 0)) > 0) {
link_url = rndr_newbuf(rndr, BUFFER_SPAN);
BUFPUTSL(link_url, "http://");
bufput(link_url, link->data, link->size);
@@ -799,7 +808,7 @@ char_autolink_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, siz
link = rndr_newbuf(rndr, BUFFER_SPAN);
- if ((link_len = sd_autolink__email(&rewind, link, data, offset, size)) > 0) {
+ if ((link_len = sd_autolink__email(&rewind, link, data, offset, size, 0)) > 0) {
ob->size -= rewind;
rndr->cb.autolink(ob, link, MKDA_EMAIL, rndr->opaque);
}
@@ -819,7 +828,7 @@ char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_
link = rndr_newbuf(rndr, BUFFER_SPAN);
- if ((link_len = sd_autolink__url(&rewind, link, data, offset, size)) > 0) {
+ if ((link_len = sd_autolink__url(&rewind, link, data, offset, size, 0)) > 0) {
ob->size -= rewind;
rndr->cb.autolink(ob, link, MKDA_NORMAL, rndr->opaque);
}
@@ -1150,9 +1159,10 @@ is_hrule(uint8_t *data, size_t size)
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;
@@ -1177,41 +1187,54 @@ is_codefence(uint8_t *data, size_t size, struct buf *syntax)
if (n < 3)
return 0;
- if (syntax != NULL) {
- size_t syn = 0;
+ return i;
+}
- while (i < size && data[i] == ' ')
- 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_len = 0;
+ uint8_t *syn_start;
- syntax->data = data + i;
+ i = prefix_codefence(data, size);
+ if (i == 0)
+ return 0;
- if (i < size && data[i] == '{') {
- i++; syntax->data++;
+ while (i < size && data[i] == ' ')
+ i++;
- while (i < size && data[i] != '}' && data[i] != '\n') {
- syn++; i++;
- }
+ syn_start = data + i;
- if (i == size || data[i] != '}')
- return 0;
+ if (i < size && data[i] == '{') {
+ i++; syn_start++;
- /* strip all whitespace at the beginning and the end
- * of the {} block */
- while (syn > 0 && _isspace(syntax->data[0])) {
- syntax->data++; syn--;
- }
+ while (i < size && data[i] != '}' && data[i] != '\n') {
+ syn_len++; i++;
+ }
- while (syn > 0 && _isspace(syntax->data[syn - 1]))
- syn--;
+ if (i == size || data[i] != '}')
+ return 0;
- i++;
- } else {
- while (i < size && !_isspace(data[i])) {
- syn++; i++;
- }
+ /* strip all whitespace at the beginning and the end
+ * of the {} block */
+ while (syn_len > 0 && _isspace(syn_start[0])) {
+ syn_start++; syn_len--;
}
- syntax->size = syn;
+ while (syn_len > 0 && _isspace(syn_start[syn_len - 1]))
+ syn_len--;
+
+ i++;
+ } else {
+ while (i < size && !_isspace(data[i])) {
+ syn_len++; i++;
+ }
+ }
+
+ if (syntax) {
+ syntax->data = syn_start;
+ syntax->size = syn_len;
}
while (i < size && data[i] != '\n') {
@@ -1416,19 +1439,48 @@ parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
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 ((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;
+ }
- if (rndr->ext_flags & MKDEXT_LAX_HTML_BLOCKS) {
- if (data[i] == '<' && rndr->cb.blockhtml && parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
+ /*
+ * 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;
@@ -1500,9 +1552,10 @@ parse_fencedcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
while (beg < size) {
size_t fence_end;
+ struct buf fence_trail = { 0, 0, 0, 0 };
- fence_end = is_codefence(data + beg, size - beg, NULL);
- if (fence_end != 0) {
+ fence_end = is_codefence(data + beg, size - beg, &fence_trail);
+ if (fence_end != 0 && fence_trail.size == 0) {
beg += fence_end;
break;
}
@@ -1577,8 +1630,7 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
{
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] == ' ')
@@ -1606,6 +1658,8 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
/* 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')
@@ -1625,8 +1679,17 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
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 && (
@@ -1647,10 +1710,12 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
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');
@@ -1758,7 +1823,12 @@ parse_atxheader(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
/* 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;
@@ -1776,25 +1846,60 @@ htmlblock_end(const char *tag, size_t tag_len, struct sd_markdown *rndr, uint8_t
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 0;
+}
+
/* parse_htmlblock • parsing of inline HTML block */
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 */
@@ -1855,40 +1960,23 @@ parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
/* 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
@@ -2460,9 +2548,9 @@ sd_markdown_free(struct sd_markdown *md)
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: */
diff --git a/ext/redcarpet/markdown.h b/ext/redcarpet/markdown.h
index f8a47c6..6f6553e 100644
--- a/ext/redcarpet/markdown.h
+++ b/ext/redcarpet/markdown.h
@@ -22,10 +22,14 @@
#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 *
@@ -52,9 +56,9 @@ enum mkd_extensions {
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 */
@@ -125,6 +129,10 @@ sd_markdown_free(struct sd_markdown *md);
extern void
sd_version(int *major, int *minor, int *revision);
+#ifdef __cplusplus
+}
+#endif
+
#endif
/* vim: set filetype=c: */
diff --git a/ext/redcarpet/rc_markdown.c b/ext/redcarpet/rc_markdown.c
index 4b42e5c..da1abcc 100644
--- a/ext/redcarpet/rc_markdown.c
+++ b/ext/redcarpet/rc_markdown.c
@@ -44,8 +44,8 @@ static void rb_redcarpet_md_flags(VALUE hash, unsigned int *enabled_extensions_p
if (rb_hash_lookup(hash, CSTR2SYM("strikethrough")) == Qtrue)
extensions |= MKDEXT_STRIKETHROUGH;
- if (rb_hash_lookup(hash, CSTR2SYM("lax_html_blocks")) == Qtrue)
- extensions |= MKDEXT_LAX_HTML_BLOCKS;
+ if (rb_hash_lookup(hash, CSTR2SYM("lax_spacing")) == Qtrue)
+ extensions |= MKDEXT_LAX_SPACING;
if (rb_hash_lookup(hash, CSTR2SYM("space_after_headers")) == Qtrue)
extensions |= MKDEXT_SPACE_HEADERS;
diff --git a/ext/redcarpet/rc_render.c b/ext/redcarpet/rc_render.c
index 8e1c564..63cc558 100644
--- a/ext/redcarpet/rc_render.c
+++ b/ext/redcarpet/rc_render.c
@@ -234,6 +234,27 @@ rndr_doc_footer(struct buf *ob, void *opaque)
BLOCK_CALLBACK("doc_footer", 0);
}
+static int
+cb_link_attribute(VALUE key, VALUE val, VALUE payload)
+{
+ struct buf *ob = (struct buf *)payload;
+ key = rb_obj_as_string(key);
+ val = rb_obj_as_string(val);
+ bufprintf(ob, " %s=\"%s\"", StringValueCStr(key), StringValueCStr(val));
+ return 0;
+}
+
+static void
+rndr_link_attributes(struct buf *ob, const struct buf *url, void *opaque)
+{
+ struct redcarpet_renderopt *opt = opaque;
+ struct rb_redcarpet_rndr *rndr;
+
+ Data_Get_Struct(opt->self, struct rb_redcarpet_rndr, rndr);
+ Check_Type(opt->link_attributes, T_HASH);
+ rb_hash_foreach(opt->link_attributes, &cb_link_attribute, (VALUE)ob);
+}
+
static struct sd_callbacks rb_redcarpet_callbacks = {
rndr_blockcode,
rndr_blockquote,
@@ -342,12 +363,11 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
{
struct rb_redcarpet_rndr *rndr;
unsigned int render_flags = 0;
- VALUE hash;
+ VALUE hash, link_attr = Qnil;
Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
- if (rb_scan_args(argc, argv, "01", &hash) == 1)
- {
+ if (rb_scan_args(argc, argv, "01", &hash) == 1) {
Check_Type(hash, T_HASH);
/* escape_html */
@@ -382,11 +402,18 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
if (rb_hash_aref(hash, CSTR2SYM("xhtml")) == Qtrue)
render_flags |= HTML_USE_XHTML;
+
+ link_attr = rb_hash_aref(hash, CSTR2SYM("link_attributes"));
}
sdhtml_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, render_flags);
rb_redcarpet__overload(self, rb_cRenderHTML);
+ if (!NIL_P(link_attr)) {
+ rndr->options.link_attributes = link_attr;
+ rndr->options.html.link_attributes = &rndr_link_attributes;
+ }
+
return Qnil;
}
diff --git a/ext/redcarpet/redcarpet.h b/ext/redcarpet/redcarpet.h
index 1c4133f..e2f6b97 100644
--- a/ext/redcarpet/redcarpet.h
+++ b/ext/redcarpet/redcarpet.h
@@ -21,6 +21,7 @@ extern void Init_redcarpet_rndr();
struct redcarpet_renderopt {
struct html_renderopt html;
+ VALUE link_attributes;
VALUE self;
VALUE base_class;
#ifdef HAVE_RUBY_ENCODING_H
diff --git a/ext/redcarpet/stack.h b/ext/redcarpet/stack.h
index e3b79d9..08ff030 100644
--- a/ext/redcarpet/stack.h
+++ b/ext/redcarpet/stack.h
@@ -3,6 +3,10 @@
#include <stdlib.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct stack {
void **item;
size_t size;
@@ -18,4 +22,8 @@ int stack_push(struct stack *, void *);
void *stack_pop(struct stack *);
void *stack_top(struct stack *);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/lib/redcarpet.rb b/lib/redcarpet.rb
index edd6ad0..2dc4ba5 100644
--- a/lib/redcarpet.rb
+++ b/lib/redcarpet.rb
@@ -1,7 +1,7 @@
require 'redcarpet.so'
module Redcarpet
- VERSION = '2.1.1'
+ VERSION = '2.2.2'
class Markdown
attr_reader :renderer
@@ -77,7 +77,7 @@ class RedcarpetCompat
:fenced_code => :fenced_code_blocks,
:filter_html => :filter_html,
:hard_wrap => :hard_wrap,
- :lax_htmlblock => :lax_html_blocks,
+ :lax_htmlblock => :lax_spacing,
:no_image => :no_images,
:no_intraemphasis => :no_intra_emphasis,
:no_links => :no_links,
diff --git a/metadata.yml b/metadata.yml
index a64a872..4f687a7 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,13 +1,13 @@
--- !ruby/object:Gem::Specification
name: redcarpet
version: !ruby/object:Gem::Version
- hash: 9
+ hash: 3
prerelease:
segments:
- 2
- - 1
- - 1
- version: 2.1.1
+ - 2
+ - 2
+ version: 2.2.2
platform: ruby
authors:
- "Natacha Port\xC3\xA9"
@@ -16,10 +16,11 @@ autorequire:
bindir: bin
cert_chain: []
-date: 2011-09-14 00:00:00 Z
+date: 2012-10-19 00:00:00 +02:00
+default_executable:
dependencies:
- !ruby/object:Gem::Dependency
- name: rake-compiler
+ name: nokogiri
prerelease: false
requirement: &id001 !ruby/object:Gem::Requirement
none: false
@@ -32,6 +33,20 @@ dependencies:
version: "0"
type: :development
version_requirements: *id001
+- !ruby/object:Gem::Dependency
+ name: rake-compiler
+ prerelease: false
+ requirement: &id002 !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ">="
+ - !ruby/object:Gem::Version
+ hash: 3
+ segments:
+ - 0
+ version: "0"
+ type: :development
+ version_requirements: *id002
description: A fast, safe and extensible Markdown to (X)HTML parser
email: vicent at github.com
executables:
@@ -42,6 +57,8 @@ extra_rdoc_files:
- COPYING
files:
- COPYING
+- Gemfile
+- Gemfile.lock
- README.markdown
- Rakefile
- bin/redcarpet
@@ -70,7 +87,8 @@ files:
- lib/redcarpet/render_strip.rb
- redcarpet.gemspec
- test/redcarpet_test.rb
-homepage: http://github.com/tanoku/redcarpet
+has_rdoc: true
+homepage: http://github.com/vmg/redcarpet
licenses: []
post_install_message:
@@ -99,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project:
-rubygems_version: 1.8.15
+rubygems_version: 1.6.2
signing_key:
specification_version: 3
summary: Markdown that smells nice
diff --git a/redcarpet.gemspec b/redcarpet.gemspec
index ce9fc15..bf268e0 100644
--- a/redcarpet.gemspec
+++ b/redcarpet.gemspec
@@ -1,16 +1,18 @@
# encoding: utf-8
Gem::Specification.new do |s|
s.name = 'redcarpet'
- s.version = '2.1.1'
+ s.version = '2.2.2'
s.summary = "Markdown that smells nice"
s.description = 'A fast, safe and extensible Markdown to (X)HTML parser'
- s.date = '2011-09-14'
+ s.date = '2012-10-19'
s.email = 'vicent at github.com'
- s.homepage = 'http://github.com/tanoku/redcarpet'
+ s.homepage = 'http://github.com/vmg/redcarpet'
s.authors = ["Natacha Porté", "Vicent Martí"]
# = MANIFEST =
s.files = %w[
COPYING
+ Gemfile
+ Gemfile.lock
README.markdown
Rakefile
bin/redcarpet
@@ -47,5 +49,6 @@ Gem::Specification.new do |s|
s.extensions = ["ext/redcarpet/extconf.rb"]
s.executables = ["redcarpet"]
s.require_paths = ["lib"]
+ s.add_development_dependency "nokogiri"
s.add_development_dependency "rake-compiler"
end
diff --git a/test/redcarpet_test.rb b/test/redcarpet_test.rb
index 70e40ea..00ff013 100644
--- a/test/redcarpet_test.rb
+++ b/test/redcarpet_test.rb
@@ -127,6 +127,12 @@ EOE
assert rd =~ /<br>/
end
+
+ def test_that_link_attributes_work
+ rndr = Redcarpet::Render::HTML.new(:link_attributes => {:rel => 'blank'})
+ md = Redcarpet::Markdown.new(rndr)
+ assert md.render('This is a [simple](http://test.com) test.').include?('rel="blank"')
+ end
end
class MarkdownTest < Test::Unit::TestCase
@@ -187,7 +193,7 @@ class MarkdownTest < Test::Unit::TestCase
end
def test_para_before_block_html_should_not_wrap_in_p_tag
- markdown = render_with({:lax_html_blocks => true},
+ markdown = render_with({:lax_spacing => true},
"Things to watch out for\n" +
"<ul>\n<li>Blah</li>\n</ul>\n")
@@ -311,6 +317,15 @@ fenced
assert render_with({:fenced_code_blocks => true}, text) =~ /<code/
end
+ def test_that_fenced_flag_works_without_space
+ text = "foo\nbar\n```\nsome\ncode\n```\nbaz"
+ out = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true, :lax_spacing => true).render(text)
+ assert out.include?("<pre><code>")
+
+ out = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true).render(text)
+ assert !out.include?("<pre><code>")
+ end
+
def test_that_headers_are_linkable
markdown = @markdown.render('### Hello [GitHub](http://github.com)')
html_equal "<h3>Hello <a href=\"http://github.com\">GitHub</a></h3>", markdown
@@ -327,6 +342,14 @@ text
rd = render_with({:space_after_headers => true}, "#123 a header yes\n")
assert rd !~ /<h1>/
end
+
+ def test_proper_intra_emphasis
+ md = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :no_intra_emphasis => true)
+ assert render_with({:no_intra_emphasis => true}, "http://en.wikipedia.org/wiki/Dave_Allen_(comedian)") !~ /<em>/
+ assert render_with({:no_intra_emphasis => true}, "this fails: hello_world_") !~ /<em>/
+ assert render_with({:no_intra_emphasis => true}, "this also fails: hello_world_#bye") !~ /<em>/
+ assert render_with({:no_intra_emphasis => true}, "this works: hello_my_world") !~ /<em>/
+ end
end
class CustomRenderTest < Test::Unit::TestCase
--
ruby-redcarpet.git
More information about the Pkg-ruby-extras-commits
mailing list