redcarpet 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of redcarpet might be problematic. Click here for more details.

data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ redcarpet (2.1.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ nokogiri (1.5.5)
10
+ rake (0.9.2.2)
11
+ rake-compiler (0.8.1)
12
+ rake
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ nokogiri
19
+ rake-compiler
20
+ redcarpet!
data/README.markdown CHANGED
@@ -9,14 +9,14 @@ case since version 2 -- it now has its own API, but retains the old name. Yes,
9
9
  that does mean that Redcarpet 2 is not backwards-compatible with the 1.X
10
10
  versions.
11
11
 
12
- Redcarpet is powered by the [Sundown](https://www.github.com/tanoku/sundown)
12
+ Redcarpet is powered by the [Sundown](https://www.github.com/vmg/sundown)
13
13
  library. You might want to find out more about Sundown to see what makes this
14
14
  Ruby library so awesome.
15
15
 
16
16
  This library is written by people
17
17
  -------------------------------------------------------
18
18
 
19
- Redcarpet 2 has been rewritten from scratch by Vicent Martí (@tanoku). Why
19
+ Redcarpet 2 has been rewritten from scratch by Vicent Martí (@vmg). Why
20
20
  are you not following me on Twitter?
21
21
 
22
22
  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.
32
32
 
33
33
  The Redcarpet source (including Sundown as a submodule) is available at GitHub:
34
34
 
35
- $ git clone git://github.com/tanoku/redcarpet.git
35
+ $ git clone git://github.com/vmg/redcarpet.git
36
36
 
37
37
  And it's like *really* simple to use
38
38
  ------------------------------------
@@ -78,7 +78,7 @@ settings, and reused between parses.
78
78
  Two `~` characters mark the start of a strikethrough,
79
79
  e.g. `this is ~~good~~ bad`
80
80
 
81
- :lax_html_blocks - HTML blocks do not require to be surrounded
81
+ :lax_spacing - HTML blocks do not require to be surrounded
82
82
  by an empty line as in the Markdown standard.
83
83
 
84
84
  :space_after_headers - A space is always required between the
@@ -126,32 +126,33 @@ instantiating the renderer:
126
126
 
127
127
  Render::HTML.new(render_options={})
128
128
 
129
- Initializes an HTML renderer. The following flags are available:
129
+ Initializes an HTML renderer. The following flags are available:
130
130
 
131
- :filter_html - do not allow any user-inputted HTML in the output
131
+ :filter_html - do not allow any user-inputted HTML in the output
132
132
 
133
- :no_images - do not generate any `<img>` tags
133
+ :no_images - do not generate any `<img>` tags
134
134
 
135
- :no_links - do not generate any `<a>` tags
135
+ :no_links - do not generate any `<a>` tags
136
136
 
137
- :no_styles - do not generate any `<style>` tags
137
+ :no_styles - do not generate any `<style>` tags
138
138
 
139
- :safe_links_only - only generate links for protocols which are considered safe
139
+ :safe_links_only - only generate links for protocols which are considered safe
140
140
 
141
- :with_toc_data - add HTML anchors to each header in the output HTML,
142
- to allow linking to each section.
141
+ :with_toc_data - add HTML anchors to each header in the output HTML,
142
+ to allow linking to each section.
143
143
 
144
- :hard_wrap - insert HTML `<br>` tags inside on paragraphs where the origin
145
- Markdown document had newlines (by default, Markdown ignores these
146
- newlines).
144
+ :hard_wrap - insert HTML `<br>` tags inside on paragraphs where the origin
145
+ Markdown document had newlines (by default, Markdown ignores these
146
+ newlines).
147
147
 
148
- :xhtml - output XHTML-conformant tags. This option is always enabled in the
149
- `Render::XHTML` renderer.
148
+ :xhtml - output XHTML-conformant tags. This option is always enabled in the
149
+ `Render::XHTML` renderer.
150
150
 
151
+ :link_attributes - hash of extra attributes to add to links
151
152
 
152
- Example:
153
+ Example:
153
154
 
154
- rndr = Redcarpet::Render::HTML.new(:no_links => true, :hard_wrap => true)
155
+ rndr = Redcarpet::Render::HTML.new(:no_links => true, :hard_wrap => true)
155
156
 
156
157
 
157
158
  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
295
296
  only way to have reliable and predictable Markdown output on your program.
296
297
 
297
298
  Still, if major forces (let's say, tornadoes or other natural disasters) force you
298
- to keep a Markdown-compatibility later, Redcarpet also supports this:
299
+ to keep a Markdown-compatibility layer, Redcarpet also supports this:
299
300
 
300
301
  require 'redcarpet/compat'
301
302
 
@@ -311,6 +312,10 @@ that's a maintance nightmare and won't work.
311
312
  On a related topic: if your Markdown gem has a `lib/markdown.rb` file that
312
313
  monkeypatches the Markdown class, you're a terrible human being. Just saying.
313
314
 
315
+ Testing
316
+ -------
317
+ Tests run a lot faster without `bundle exec` :)
318
+
314
319
  Boring legal stuff
315
320
  ------------------
316
321
 
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'rake/clean'
3
3
  require 'rake/extensiontask'
4
4
  require 'digest/md5'
5
5
 
6
- task :default => :test
6
+ task :default => [:checkout, :test]
7
7
 
8
8
  # ==========================================================
9
9
  # Ruby Extension
@@ -11,6 +11,13 @@ task :default => :test
11
11
 
12
12
  Rake::ExtensionTask.new('redcarpet')
13
13
 
14
+ task :checkout do |t|
15
+ unless File.exists?('sundown/src/markdown.h')
16
+ sh 'git submodule init'
17
+ sh 'git submodule update'
18
+ end
19
+ end
20
+
14
21
  # ==========================================================
15
22
  # Testing
16
23
  # ==========================================================
@@ -109,22 +116,3 @@ task :update_gem do
109
116
  puts "updated #{GEMFILE}"
110
117
  end
111
118
 
112
- desc 'Gather required Sundown sources into extension directory'
113
- task :gather => 'sundown/src/markdown.h' do |t|
114
- files =
115
- FileList[
116
- 'sundown/src/{markdown,buffer,stack,autolink,html_blocks}.h',
117
- 'sundown/src/{markdown,buffer,stack,autolink}.c',
118
- 'sundown/html/{html,html_smartypants,houdini_html_e,houdini_href_e}.c',
119
- 'sundown/html/{html,houdini}.h',
120
- ]
121
- cp files, 'ext/redcarpet/',
122
- :preserve => true,
123
- :verbose => true
124
- end
125
-
126
- file 'sundown/src/markdown.h' do |t|
127
- abort "The Sundown submodule is required."
128
- end
129
-
130
-
@@ -15,12 +15,17 @@
15
15
  */
16
16
 
17
17
  #include "buffer.h"
18
+ #include "autolink.h"
18
19
 
19
20
  #include <string.h>
20
21
  #include <stdlib.h>
21
22
  #include <stdio.h>
22
23
  #include <ctype.h>
23
24
 
25
+ #if defined(_WIN32)
26
+ #define strncasecmp _strnicmp
27
+ #endif
28
+
24
29
  int
25
30
  sd_autolink_issafe(const uint8_t *link, size_t link_len)
26
31
  {
@@ -44,7 +49,7 @@ sd_autolink_issafe(const uint8_t *link, size_t link_len)
44
49
  }
45
50
 
46
51
  static size_t
47
- autolink_delim(uint8_t *data, size_t link_end, size_t offset, size_t size)
52
+ autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
48
53
  {
49
54
  uint8_t cclose, copen = 0;
50
55
  size_t i;
@@ -128,7 +133,7 @@ autolink_delim(uint8_t *data, size_t link_end, size_t offset, size_t size)
128
133
  }
129
134
 
130
135
  static size_t
131
- check_domain(uint8_t *data, size_t size)
136
+ check_domain(uint8_t *data, size_t size, int allow_short)
132
137
  {
133
138
  size_t i, np = 0;
134
139
 
@@ -140,23 +145,37 @@ check_domain(uint8_t *data, size_t size)
140
145
  else if (!isalnum(data[i]) && data[i] != '-') break;
141
146
  }
142
147
 
143
- /* a valid domain needs to have at least a dot.
144
- * that's as far as we get */
145
- return np ? i : 0;
148
+ if (allow_short) {
149
+ /* We don't need a valid domain in the strict sense (with
150
+ * least one dot; so just make sure it's composed of valid
151
+ * domain characters and return the length of the the valid
152
+ * sequence. */
153
+ return i;
154
+ } else {
155
+ /* a valid domain needs to have at least a dot.
156
+ * that's as far as we get */
157
+ return np ? i : 0;
158
+ }
146
159
  }
147
160
 
148
161
  size_t
149
- sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
162
+ sd_autolink__www(
163
+ size_t *rewind_p,
164
+ struct buf *link,
165
+ uint8_t *data,
166
+ size_t max_rewind,
167
+ size_t size,
168
+ unsigned int flags)
150
169
  {
151
170
  size_t link_end;
152
171
 
153
- if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
172
+ if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
154
173
  return 0;
155
174
 
156
175
  if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
157
176
  return 0;
158
177
 
159
- link_end = check_domain(data, size);
178
+ link_end = check_domain(data, size, 0);
160
179
 
161
180
  if (link_end == 0)
162
181
  return 0;
@@ -164,7 +183,7 @@ sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offse
164
183
  while (link_end < size && !isspace(data[link_end]))
165
184
  link_end++;
166
185
 
167
- link_end = autolink_delim(data, link_end, offset, size);
186
+ link_end = autolink_delim(data, link_end, max_rewind, size);
168
187
 
169
188
  if (link_end == 0)
170
189
  return 0;
@@ -176,12 +195,18 @@ sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offse
176
195
  }
177
196
 
178
197
  size_t
179
- sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
198
+ sd_autolink__email(
199
+ size_t *rewind_p,
200
+ struct buf *link,
201
+ uint8_t *data,
202
+ size_t max_rewind,
203
+ size_t size,
204
+ unsigned int flags)
180
205
  {
181
206
  size_t link_end, rewind;
182
207
  int nb = 0, np = 0;
183
208
 
184
- for (rewind = 0; rewind < offset; ++rewind) {
209
+ for (rewind = 0; rewind < max_rewind; ++rewind) {
185
210
  uint8_t c = data[-rewind - 1];
186
211
 
187
212
  if (isalnum(c))
@@ -213,7 +238,7 @@ sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t off
213
238
  if (link_end < 2 || nb != 1 || np == 0)
214
239
  return 0;
215
240
 
216
- link_end = autolink_delim(data, link_end, offset, size);
241
+ link_end = autolink_delim(data, link_end, max_rewind, size);
217
242
 
218
243
  if (link_end == 0)
219
244
  return 0;
@@ -225,21 +250,32 @@ sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t off
225
250
  }
226
251
 
227
252
  size_t
228
- sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size)
253
+ sd_autolink__url(
254
+ size_t *rewind_p,
255
+ struct buf *link,
256
+ uint8_t *data,
257
+ size_t max_rewind,
258
+ size_t size,
259
+ unsigned int flags)
229
260
  {
230
261
  size_t link_end, rewind = 0, domain_len;
231
262
 
232
263
  if (size < 4 || data[1] != '/' || data[2] != '/')
233
264
  return 0;
234
265
 
235
- while (rewind < offset && isalpha(data[-rewind - 1]))
266
+ while (rewind < max_rewind && isalpha(data[-rewind - 1]))
236
267
  rewind++;
237
268
 
238
269
  if (!sd_autolink_issafe(data - rewind, size + rewind))
239
270
  return 0;
271
+
240
272
  link_end = strlen("://");
241
273
 
242
- domain_len = check_domain(data + link_end, size - link_end);
274
+ domain_len = check_domain(
275
+ data + link_end,
276
+ size - link_end,
277
+ flags & SD_AUTOLINK_SHORT_DOMAINS);
278
+
243
279
  if (domain_len == 0)
244
280
  return 0;
245
281
 
@@ -247,7 +283,7 @@ sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offse
247
283
  while (link_end < size && !isspace(data[link_end]))
248
284
  link_end++;
249
285
 
250
- link_end = autolink_delim(data, link_end, offset, size);
286
+ link_end = autolink_delim(data, link_end, max_rewind, size);
251
287
 
252
288
  if (link_end == 0)
253
289
  return 0;
@@ -19,17 +19,32 @@
19
19
 
20
20
  #include "buffer.h"
21
21
 
22
- extern int
22
+ #ifdef __cplusplus
23
+ extern "C" {
24
+ #endif
25
+
26
+ enum {
27
+ SD_AUTOLINK_SHORT_DOMAINS = (1 << 0),
28
+ };
29
+
30
+ int
23
31
  sd_autolink_issafe(const uint8_t *link, size_t link_len);
24
32
 
25
- extern size_t
26
- sd_autolink__www(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
33
+ size_t
34
+ sd_autolink__www(size_t *rewind_p, struct buf *link,
35
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
27
36
 
28
- extern size_t
29
- sd_autolink__email(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
37
+ size_t
38
+ sd_autolink__email(size_t *rewind_p, struct buf *link,
39
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
30
40
 
31
- extern size_t
32
- sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size);
41
+ size_t
42
+ sd_autolink__url(size_t *rewind_p, struct buf *link,
43
+ uint8_t *data, size_t offset, size_t size, unsigned int flags);
44
+
45
+ #ifdef __cplusplus
46
+ }
47
+ #endif
33
48
 
34
49
  #endif
35
50
 
@@ -127,7 +127,9 @@ bufprintf(struct buf *buf, const char *fmt, ...)
127
127
 
128
128
  if (n < 0) {
129
129
  #ifdef _MSC_VER
130
+ va_start(ap, fmt);
130
131
  n = _vscprintf(fmt, ap);
132
+ va_end(ap);
131
133
  #else
132
134
  return;
133
135
  #endif
@@ -22,6 +22,10 @@
22
22
  #include <stdarg.h>
23
23
  #include <stdint.h>
24
24
 
25
+ #ifdef __cplusplus
26
+ extern "C" {
27
+ #endif
28
+
25
29
  #if defined(_MSC_VER)
26
30
  #define __attribute__(x)
27
31
  #define inline
@@ -85,4 +89,8 @@ void bufslurp(struct buf *, size_t);
85
89
  /* bufprintf: formatted printing to a buffer */
86
90
  void bufprintf(struct buf *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
87
91
 
92
+ #ifdef __cplusplus
93
+ }
94
+ #endif
95
+
88
96
  #endif
data/ext/redcarpet/html.c CHANGED
@@ -491,6 +491,13 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
491
491
  {
492
492
  struct html_renderopt *options = opaque;
493
493
 
494
+ /* set the level offset if this is the first header
495
+ * we're parsing for the document */
496
+ if (options->toc_data.current_level == 0) {
497
+ options->toc_data.level_offset = level - 1;
498
+ }
499
+ level -= options->toc_data.level_offset;
500
+
494
501
  if (level > options->toc_data.current_level) {
495
502
  while (level > options->toc_data.current_level) {
496
503
  BUFPUTSL(ob, "<ul>\n<li>\n");
@@ -516,7 +523,7 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
516
523
  static int
517
524
  toc_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque)
518
525
  {
519
- if (content && content->size)
526
+ if (content && content->size)
520
527
  bufput(ob, content->data, content->size);
521
528
  return 1;
522
529
  }
data/ext/redcarpet/html.h CHANGED
@@ -25,6 +25,7 @@ struct html_renderopt {
25
25
  struct {
26
26
  int header_count;
27
27
  int current_level;
28
+ int level_offset;
28
29
  } toc_data;
29
30
 
30
31
  unsigned int flags;
@@ -22,6 +22,10 @@
22
22
  #include <stdio.h>
23
23
  #include <ctype.h>
24
24
 
25
+ #if defined(_WIN32)
26
+ #define snprintf _snprintf
27
+ #endif
28
+
25
29
  struct smartypants_data {
26
30
  int in_squote;
27
31
  int in_dquote;
@@ -25,6 +25,10 @@
25
25
  #include <ctype.h>
26
26
  #include <stdio.h>
27
27
 
28
+ #if defined(_WIN32)
29
+ #define strncasecmp _strnicmp
30
+ #endif
31
+
28
32
  #define REF_TABLE_SIZE 8
29
33
 
30
34
  #define BUFFER_BLOCK 0
@@ -497,7 +501,7 @@ parse_emph1(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size
497
501
  if (data[i] == c && !_isspace(data[i - 1])) {
498
502
 
499
503
  if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
500
- if (!(i + 1 == size || _isspace(data[i + 1]) || ispunct(data[i + 1])))
504
+ if (i + i < size && isalnum(data[i + 1]))
501
505
  continue;
502
506
  }
503
507
 
@@ -592,6 +596,11 @@ char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t of
592
596
  uint8_t c = data[0];
593
597
  size_t ret;
594
598
 
599
+ if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
600
+ if (offset > 0 && !_isspace(data[-1]) && data[-1] != '>')
601
+ return 0;
602
+ }
603
+
595
604
  if (size > 2 && data[1] != c) {
596
605
  /* whitespace cannot follow an opening emphasis;
597
606
  * strikethrough only takes two characters '~~' */
@@ -767,7 +776,7 @@ char_autolink_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_
767
776
 
768
777
  link = rndr_newbuf(rndr, BUFFER_SPAN);
769
778
 
770
- if ((link_len = sd_autolink__www(&rewind, link, data, offset, size)) > 0) {
779
+ if ((link_len = sd_autolink__www(&rewind, link, data, offset, size, 0)) > 0) {
771
780
  link_url = rndr_newbuf(rndr, BUFFER_SPAN);
772
781
  BUFPUTSL(link_url, "http://");
773
782
  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
799
808
 
800
809
  link = rndr_newbuf(rndr, BUFFER_SPAN);
801
810
 
802
- if ((link_len = sd_autolink__email(&rewind, link, data, offset, size)) > 0) {
811
+ if ((link_len = sd_autolink__email(&rewind, link, data, offset, size, 0)) > 0) {
803
812
  ob->size -= rewind;
804
813
  rndr->cb.autolink(ob, link, MKDA_EMAIL, rndr->opaque);
805
814
  }
@@ -819,7 +828,7 @@ char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_
819
828
 
820
829
  link = rndr_newbuf(rndr, BUFFER_SPAN);
821
830
 
822
- if ((link_len = sd_autolink__url(&rewind, link, data, offset, size)) > 0) {
831
+ if ((link_len = sd_autolink__url(&rewind, link, data, offset, size, 0)) > 0) {
823
832
  ob->size -= rewind;
824
833
  rndr->cb.autolink(ob, link, MKDA_NORMAL, rndr->opaque);
825
834
  }
@@ -1150,9 +1159,10 @@ is_hrule(uint8_t *data, size_t size)
1150
1159
  return n >= 3;
1151
1160
  }
1152
1161
 
1153
- /* check if a line is a code fence; return its size if it is */
1162
+ /* check if a line begins with a code fence; return the
1163
+ * width of the code fence */
1154
1164
  static size_t
1155
- is_codefence(uint8_t *data, size_t size, struct buf *syntax)
1165
+ prefix_codefence(uint8_t *data, size_t size)
1156
1166
  {
1157
1167
  size_t i = 0, n = 0;
1158
1168
  uint8_t c;
@@ -1177,41 +1187,54 @@ is_codefence(uint8_t *data, size_t size, struct buf *syntax)
1177
1187
  if (n < 3)
1178
1188
  return 0;
1179
1189
 
1180
- if (syntax != NULL) {
1181
- size_t syn = 0;
1190
+ return i;
1191
+ }
1182
1192
 
1183
- while (i < size && data[i] == ' ')
1184
- i++;
1193
+ /* check if a line is a code fence; return its size if it is */
1194
+ static size_t
1195
+ is_codefence(uint8_t *data, size_t size, struct buf *syntax)
1196
+ {
1197
+ size_t i = 0, syn_len = 0;
1198
+ uint8_t *syn_start;
1185
1199
 
1186
- syntax->data = data + i;
1200
+ i = prefix_codefence(data, size);
1201
+ if (i == 0)
1202
+ return 0;
1187
1203
 
1188
- if (i < size && data[i] == '{') {
1189
- i++; syntax->data++;
1204
+ while (i < size && data[i] == ' ')
1205
+ i++;
1190
1206
 
1191
- while (i < size && data[i] != '}' && data[i] != '\n') {
1192
- syn++; i++;
1193
- }
1207
+ syn_start = data + i;
1194
1208
 
1195
- if (i == size || data[i] != '}')
1196
- return 0;
1209
+ if (i < size && data[i] == '{') {
1210
+ i++; syn_start++;
1197
1211
 
1198
- /* strip all whitespace at the beginning and the end
1199
- * of the {} block */
1200
- while (syn > 0 && _isspace(syntax->data[0])) {
1201
- syntax->data++; syn--;
1202
- }
1212
+ while (i < size && data[i] != '}' && data[i] != '\n') {
1213
+ syn_len++; i++;
1214
+ }
1203
1215
 
1204
- while (syn > 0 && _isspace(syntax->data[syn - 1]))
1205
- syn--;
1216
+ if (i == size || data[i] != '}')
1217
+ return 0;
1206
1218
 
1207
- i++;
1208
- } else {
1209
- while (i < size && !_isspace(data[i])) {
1210
- syn++; i++;
1211
- }
1219
+ /* strip all whitespace at the beginning and the end
1220
+ * of the {} block */
1221
+ while (syn_len > 0 && _isspace(syn_start[0])) {
1222
+ syn_start++; syn_len--;
1212
1223
  }
1213
1224
 
1214
- syntax->size = syn;
1225
+ while (syn_len > 0 && _isspace(syn_start[syn_len - 1]))
1226
+ syn_len--;
1227
+
1228
+ i++;
1229
+ } else {
1230
+ while (i < size && !_isspace(data[i])) {
1231
+ syn_len++; i++;
1232
+ }
1233
+ }
1234
+
1235
+ if (syntax) {
1236
+ syntax->data = syn_start;
1237
+ syntax->size = syn_len;
1215
1238
  }
1216
1239
 
1217
1240
  while (i < size && data[i] != '\n') {
@@ -1416,19 +1439,48 @@ parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
1416
1439
  while (i < size) {
1417
1440
  for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;
1418
1441
 
1419
- if (is_empty(data + i, size - i) || (level = is_headerline(data + i, size - i)) != 0)
1442
+ if (is_empty(data + i, size - i))
1443
+ break;
1444
+
1445
+ if ((level = is_headerline(data + i, size - i)) != 0)
1446
+ break;
1447
+
1448
+ if (is_atxheader(rndr, data + i, size - i) ||
1449
+ is_hrule(data + i, size - i) ||
1450
+ prefix_quote(data + i, size - i)) {
1451
+ end = i;
1420
1452
  break;
1453
+ }
1421
1454
 
1422
- if (rndr->ext_flags & MKDEXT_LAX_HTML_BLOCKS) {
1423
- if (data[i] == '<' && rndr->cb.blockhtml && parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
1455
+ /*
1456
+ * Early termination of a paragraph with the same logic
1457
+ * as Markdown 1.0.0. If this logic is applied, the
1458
+ * Markdown 1.0.3 test suite won't pass cleanly
1459
+ *
1460
+ * :: If the first character in a new line is not a letter,
1461
+ * let's check to see if there's some kind of block starting
1462
+ * here
1463
+ */
1464
+ if ((rndr->ext_flags & MKDEXT_LAX_SPACING) && !isalnum(data[i])) {
1465
+ if (prefix_oli(data + i, size - i) ||
1466
+ prefix_uli(data + i, size - i)) {
1424
1467
  end = i;
1425
1468
  break;
1426
1469
  }
1427
- }
1428
1470
 
1429
- if (is_atxheader(rndr, data + i, size - i) || is_hrule(data + i, size - i)) {
1430
- end = i;
1431
- break;
1471
+ /* see if an html block starts here */
1472
+ if (data[i] == '<' && rndr->cb.blockhtml &&
1473
+ parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
1474
+ end = i;
1475
+ break;
1476
+ }
1477
+
1478
+ /* see if a code fence starts here */
1479
+ if ((rndr->ext_flags & MKDEXT_FENCED_CODE) != 0 &&
1480
+ is_codefence(data + i, size - i, NULL) != 0) {
1481
+ end = i;
1482
+ break;
1483
+ }
1432
1484
  }
1433
1485
 
1434
1486
  i = end;
@@ -1500,9 +1552,10 @@ parse_fencedcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
1500
1552
 
1501
1553
  while (beg < size) {
1502
1554
  size_t fence_end;
1555
+ struct buf fence_trail = { 0, 0, 0, 0 };
1503
1556
 
1504
- fence_end = is_codefence(data + beg, size - beg, NULL);
1505
- if (fence_end != 0) {
1557
+ fence_end = is_codefence(data + beg, size - beg, &fence_trail);
1558
+ if (fence_end != 0 && fence_trail.size == 0) {
1506
1559
  beg += fence_end;
1507
1560
  break;
1508
1561
  }
@@ -1577,8 +1630,7 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
1577
1630
  {
1578
1631
  struct buf *work = 0, *inter = 0;
1579
1632
  size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
1580
- int in_empty = 0, has_inside_empty = 0;
1581
- size_t has_next_uli, has_next_oli;
1633
+ int in_empty = 0, has_inside_empty = 0, in_fence = 0;
1582
1634
 
1583
1635
  /* keeping track of the first indentation prefix */
1584
1636
  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
1606
1658
 
1607
1659
  /* process the following lines */
1608
1660
  while (beg < size) {
1661
+ size_t has_next_uli = 0, has_next_oli = 0;
1662
+
1609
1663
  end++;
1610
1664
 
1611
1665
  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
1625
1679
 
1626
1680
  pre = i;
1627
1681
 
1628
- has_next_uli = prefix_uli(data + beg + i, end - beg - i);
1629
- has_next_oli = prefix_oli(data + beg + i, end - beg - i);
1682
+ if (rndr->ext_flags & MKDEXT_FENCED_CODE) {
1683
+ if (is_codefence(data + beg + i, end - beg - i, NULL) != 0)
1684
+ in_fence = !in_fence;
1685
+ }
1686
+
1687
+ /* Only check for new list items if we are **not** inside
1688
+ * a fenced code block */
1689
+ if (!in_fence) {
1690
+ has_next_uli = prefix_uli(data + beg + i, end - beg - i);
1691
+ has_next_oli = prefix_oli(data + beg + i, end - beg - i);
1692
+ }
1630
1693
 
1631
1694
  /* checking for ul/ol switch */
1632
1695
  if (in_empty && (
@@ -1647,10 +1710,12 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
1647
1710
  if (!sublist)
1648
1711
  sublist = work->size;
1649
1712
  }
1650
- /* joining only indented stuff after empty lines */
1651
- else if (in_empty && i < 4) {
1652
- *flags |= MKD_LI_END;
1653
- break;
1713
+ /* joining only indented stuff after empty lines;
1714
+ * note that now we only require 1 space of indentation
1715
+ * to continue a list */
1716
+ else if (in_empty && pre == 0) {
1717
+ *flags |= MKD_LI_END;
1718
+ break;
1654
1719
  }
1655
1720
  else if (in_empty) {
1656
1721
  bufputc(work, '\n');
@@ -1758,7 +1823,12 @@ parse_atxheader(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
1758
1823
  /* htmlblock_end • checking end of HTML block : </tag>[ \t]*\n[ \t*]\n */
1759
1824
  /* returns the length on match, 0 otherwise */
1760
1825
  static size_t
1761
- htmlblock_end(const char *tag, size_t tag_len, struct sd_markdown *rndr, uint8_t *data, size_t size)
1826
+ htmlblock_end_tag(
1827
+ const char *tag,
1828
+ size_t tag_len,
1829
+ struct sd_markdown *rndr,
1830
+ uint8_t *data,
1831
+ size_t size)
1762
1832
  {
1763
1833
  size_t i, w;
1764
1834
 
@@ -1776,25 +1846,60 @@ htmlblock_end(const char *tag, size_t tag_len, struct sd_markdown *rndr, uint8_t
1776
1846
  i += w;
1777
1847
  w = 0;
1778
1848
 
1779
- if (rndr->ext_flags & MKDEXT_LAX_HTML_BLOCKS) {
1780
- if (i < size)
1781
- w = is_empty(data + i, size - i);
1782
- } else {
1783
- if (i < size && (w = is_empty(data + i, size - i)) == 0)
1784
- return 0; /* non-blank line after tag line */
1785
- }
1849
+ if (i < size)
1850
+ w = is_empty(data + i, size - i);
1786
1851
 
1787
1852
  return i + w;
1788
1853
  }
1789
1854
 
1855
+ static size_t
1856
+ htmlblock_end(const char *curtag,
1857
+ struct sd_markdown *rndr,
1858
+ uint8_t *data,
1859
+ size_t size,
1860
+ int start_of_line)
1861
+ {
1862
+ size_t tag_size = strlen(curtag);
1863
+ size_t i = 1, end_tag;
1864
+ int block_lines = 0;
1865
+
1866
+ while (i < size) {
1867
+ i++;
1868
+ while (i < size && !(data[i - 1] == '<' && data[i] == '/')) {
1869
+ if (data[i] == '\n')
1870
+ block_lines++;
1871
+
1872
+ i++;
1873
+ }
1874
+
1875
+ /* If we are only looking for unindented tags, skip the tag
1876
+ * if it doesn't follow a newline.
1877
+ *
1878
+ * The only exception to this is if the tag is still on the
1879
+ * initial line; in that case it still counts as a closing
1880
+ * tag
1881
+ */
1882
+ if (start_of_line && block_lines > 0 && data[i - 2] != '\n')
1883
+ continue;
1884
+
1885
+ if (i + 2 + tag_size >= size)
1886
+ break;
1887
+
1888
+ end_tag = htmlblock_end_tag(curtag, tag_size, rndr, data + i - 1, size - i + 1);
1889
+ if (end_tag)
1890
+ return i + end_tag - 1;
1891
+ }
1892
+
1893
+ return 0;
1894
+ }
1895
+
1790
1896
 
1791
1897
  /* parse_htmlblock • parsing of inline HTML block */
1792
1898
  static size_t
1793
1899
  parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render)
1794
1900
  {
1795
- size_t i, j = 0;
1901
+ size_t i, j = 0, tag_end;
1796
1902
  const char *curtag = NULL;
1797
- int found;
1798
1903
  struct buf work = { data, 0, 0, 0 };
1799
1904
 
1800
1905
  /* identification of the opening tag */
@@ -1855,40 +1960,23 @@ parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
1855
1960
 
1856
1961
  /* looking for an unindented matching closing tag */
1857
1962
  /* followed by a blank line */
1858
- i = 1;
1859
- found = 0;
1963
+ tag_end = htmlblock_end(curtag, rndr, data, size, 1);
1860
1964
 
1861
1965
  /* if not found, trying a second pass looking for indented match */
1862
1966
  /* but not if tag is "ins" or "del" (following original Markdown.pl) */
1863
- if (strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0) {
1864
- size_t tag_size = strlen(curtag);
1865
- i = 1;
1866
- while (i < size) {
1867
- i++;
1868
- while (i < size && !(data[i - 1] == '<' && data[i] == '/'))
1869
- i++;
1870
-
1871
- if (i + 2 + tag_size >= size)
1872
- break;
1873
-
1874
- j = htmlblock_end(curtag, tag_size, rndr, data + i - 1, size - i + 1);
1875
-
1876
- if (j) {
1877
- i += j - 1;
1878
- found = 1;
1879
- break;
1880
- }
1881
- }
1967
+ if (!tag_end && strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0) {
1968
+ tag_end = htmlblock_end(curtag, rndr, data, size, 0);
1882
1969
  }
1883
1970
 
1884
- if (!found) return 0;
1971
+ if (!tag_end)
1972
+ return 0;
1885
1973
 
1886
1974
  /* the end of the block has been found */
1887
- work.size = i;
1975
+ work.size = tag_end;
1888
1976
  if (do_render && rndr->cb.blockhtml)
1889
1977
  rndr->cb.blockhtml(ob, &work, rndr->opaque);
1890
1978
 
1891
- return i;
1979
+ return tag_end;
1892
1980
  }
1893
1981
 
1894
1982
  static void
@@ -2460,9 +2548,9 @@ sd_markdown_free(struct sd_markdown *md)
2460
2548
  void
2461
2549
  sd_version(int *ver_major, int *ver_minor, int *ver_revision)
2462
2550
  {
2463
- *ver_major = UPSKIRT_VER_MAJOR;
2464
- *ver_minor = UPSKIRT_VER_MINOR;
2465
- *ver_revision = UPSKIRT_VER_REVISION;
2551
+ *ver_major = SUNDOWN_VER_MAJOR;
2552
+ *ver_minor = SUNDOWN_VER_MINOR;
2553
+ *ver_revision = SUNDOWN_VER_REVISION;
2466
2554
  }
2467
2555
 
2468
2556
  /* vim: set filetype=c: */
@@ -22,10 +22,14 @@
22
22
  #include "buffer.h"
23
23
  #include "autolink.h"
24
24
 
25
- #define UPSKIRT_VERSION "1.15.2"
26
- #define UPSKIRT_VER_MAJOR 1
27
- #define UPSKIRT_VER_MINOR 15
28
- #define UPSKIRT_VER_REVISION 2
25
+ #ifdef __cplusplus
26
+ extern "C" {
27
+ #endif
28
+
29
+ #define SUNDOWN_VERSION "1.16.0"
30
+ #define SUNDOWN_VER_MAJOR 1
31
+ #define SUNDOWN_VER_MINOR 16
32
+ #define SUNDOWN_VER_REVISION 0
29
33
 
30
34
  /********************
31
35
  * TYPE DEFINITIONS *
@@ -52,9 +56,9 @@ enum mkd_extensions {
52
56
  MKDEXT_FENCED_CODE = (1 << 2),
53
57
  MKDEXT_AUTOLINK = (1 << 3),
54
58
  MKDEXT_STRIKETHROUGH = (1 << 4),
55
- MKDEXT_LAX_HTML_BLOCKS = (1 << 5),
56
59
  MKDEXT_SPACE_HEADERS = (1 << 6),
57
60
  MKDEXT_SUPERSCRIPT = (1 << 7),
61
+ MKDEXT_LAX_SPACING = (1 << 8),
58
62
  };
59
63
 
60
64
  /* sd_callbacks - functions for rendering parsed data */
@@ -125,6 +129,10 @@ sd_markdown_free(struct sd_markdown *md);
125
129
  extern void
126
130
  sd_version(int *major, int *minor, int *revision);
127
131
 
132
+ #ifdef __cplusplus
133
+ }
134
+ #endif
135
+
128
136
  #endif
129
137
 
130
138
  /* vim: set filetype=c: */
@@ -44,8 +44,8 @@ static void rb_redcarpet_md_flags(VALUE hash, unsigned int *enabled_extensions_p
44
44
  if (rb_hash_lookup(hash, CSTR2SYM("strikethrough")) == Qtrue)
45
45
  extensions |= MKDEXT_STRIKETHROUGH;
46
46
 
47
- if (rb_hash_lookup(hash, CSTR2SYM("lax_html_blocks")) == Qtrue)
48
- extensions |= MKDEXT_LAX_HTML_BLOCKS;
47
+ if (rb_hash_lookup(hash, CSTR2SYM("lax_spacing")) == Qtrue)
48
+ extensions |= MKDEXT_LAX_SPACING;
49
49
 
50
50
  if (rb_hash_lookup(hash, CSTR2SYM("space_after_headers")) == Qtrue)
51
51
  extensions |= MKDEXT_SPACE_HEADERS;
@@ -234,6 +234,27 @@ rndr_doc_footer(struct buf *ob, void *opaque)
234
234
  BLOCK_CALLBACK("doc_footer", 0);
235
235
  }
236
236
 
237
+ static int
238
+ cb_link_attribute(VALUE key, VALUE val, VALUE payload)
239
+ {
240
+ struct buf *ob = (struct buf *)payload;
241
+ key = rb_obj_as_string(key);
242
+ val = rb_obj_as_string(val);
243
+ bufprintf(ob, " %s=\"%s\"", StringValueCStr(key), StringValueCStr(val));
244
+ return ST_CONTINUE;
245
+ }
246
+
247
+ static void
248
+ rndr_link_attributes(struct buf *ob, const struct buf *url, void *opaque)
249
+ {
250
+ struct redcarpet_renderopt *opt = opaque;
251
+ struct rb_redcarpet_rndr *rndr;
252
+
253
+ Data_Get_Struct(opt->self, struct rb_redcarpet_rndr, rndr);
254
+ Check_Type(opt->link_attributes, T_HASH);
255
+ rb_hash_foreach(opt->link_attributes, &cb_link_attribute, (VALUE)ob);
256
+ }
257
+
237
258
  static struct sd_callbacks rb_redcarpet_callbacks = {
238
259
  rndr_blockcode,
239
260
  rndr_blockquote,
@@ -342,12 +363,11 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
342
363
  {
343
364
  struct rb_redcarpet_rndr *rndr;
344
365
  unsigned int render_flags = 0;
345
- VALUE hash;
366
+ VALUE hash, link_attr = Qnil;
346
367
 
347
368
  Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
348
369
 
349
- if (rb_scan_args(argc, argv, "01", &hash) == 1)
350
- {
370
+ if (rb_scan_args(argc, argv, "01", &hash) == 1) {
351
371
  Check_Type(hash, T_HASH);
352
372
 
353
373
  /* escape_html */
@@ -382,11 +402,18 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
382
402
 
383
403
  if (rb_hash_aref(hash, CSTR2SYM("xhtml")) == Qtrue)
384
404
  render_flags |= HTML_USE_XHTML;
405
+
406
+ link_attr = rb_hash_aref(hash, CSTR2SYM("link_attributes"));
385
407
  }
386
408
 
387
409
  sdhtml_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, render_flags);
388
410
  rb_redcarpet__overload(self, rb_cRenderHTML);
389
411
 
412
+ if (!NIL_P(link_attr)) {
413
+ rndr->options.link_attributes = link_attr;
414
+ rndr->options.html.link_attributes = &rndr_link_attributes;
415
+ }
416
+
390
417
  return Qnil;
391
418
  }
392
419
 
@@ -3,6 +3,7 @@
3
3
 
4
4
  #define RSTRING_NOT_MODIFIED
5
5
  #include "ruby.h"
6
+ #include "st.h"
6
7
  #include <stdio.h>
7
8
 
8
9
  #ifdef HAVE_RUBY_ENCODING_H
@@ -21,6 +22,7 @@ extern void Init_redcarpet_rndr();
21
22
 
22
23
  struct redcarpet_renderopt {
23
24
  struct html_renderopt html;
25
+ VALUE link_attributes;
24
26
  VALUE self;
25
27
  VALUE base_class;
26
28
  #ifdef HAVE_RUBY_ENCODING_H
@@ -3,6 +3,10 @@
3
3
 
4
4
  #include <stdlib.h>
5
5
 
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
6
10
  struct stack {
7
11
  void **item;
8
12
  size_t size;
@@ -18,4 +22,8 @@ int stack_push(struct stack *, void *);
18
22
  void *stack_pop(struct stack *);
19
23
  void *stack_top(struct stack *);
20
24
 
25
+ #ifdef __cplusplus
26
+ }
27
+ #endif
28
+
21
29
  #endif
data/lib/redcarpet.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'redcarpet.so'
2
2
 
3
3
  module Redcarpet
4
- VERSION = '2.1.1'
4
+ VERSION = '2.2.0'
5
5
 
6
6
  class Markdown
7
7
  attr_reader :renderer
@@ -77,7 +77,7 @@ class RedcarpetCompat
77
77
  :fenced_code => :fenced_code_blocks,
78
78
  :filter_html => :filter_html,
79
79
  :hard_wrap => :hard_wrap,
80
- :lax_htmlblock => :lax_html_blocks,
80
+ :lax_htmlblock => :lax_spacing,
81
81
  :no_image => :no_images,
82
82
  :no_intraemphasis => :no_intra_emphasis,
83
83
  :no_links => :no_links,
data/redcarpet.gemspec CHANGED
@@ -1,16 +1,18 @@
1
1
  # encoding: utf-8
2
2
  Gem::Specification.new do |s|
3
3
  s.name = 'redcarpet'
4
- s.version = '2.1.1'
4
+ s.version = '2.2.0'
5
5
  s.summary = "Markdown that smells nice"
6
6
  s.description = 'A fast, safe and extensible Markdown to (X)HTML parser'
7
- s.date = '2011-09-14'
7
+ s.date = '2012-10-11'
8
8
  s.email = 'vicent@github.com'
9
- s.homepage = 'http://github.com/tanoku/redcarpet'
9
+ s.homepage = 'http://github.com/vmg/redcarpet'
10
10
  s.authors = ["Natacha Porté", "Vicent Martí"]
11
11
  # = MANIFEST =
12
12
  s.files = %w[
13
13
  COPYING
14
+ Gemfile
15
+ Gemfile.lock
14
16
  README.markdown
15
17
  Rakefile
16
18
  bin/redcarpet
@@ -47,5 +49,6 @@ Gem::Specification.new do |s|
47
49
  s.extensions = ["ext/redcarpet/extconf.rb"]
48
50
  s.executables = ["redcarpet"]
49
51
  s.require_paths = ["lib"]
52
+ s.add_development_dependency "nokogiri"
50
53
  s.add_development_dependency "rake-compiler"
51
54
  end
@@ -127,6 +127,12 @@ EOE
127
127
 
128
128
  assert rd =~ /<br>/
129
129
  end
130
+
131
+ def test_that_link_attributes_work
132
+ rndr = Redcarpet::Render::HTML.new(:link_attributes => {:rel => 'blank'})
133
+ md = Redcarpet::Markdown.new(rndr)
134
+ assert md.render('This is a [simple](http://test.com) test.').include?('rel="blank"')
135
+ end
130
136
  end
131
137
 
132
138
  class MarkdownTest < Test::Unit::TestCase
@@ -187,7 +193,7 @@ class MarkdownTest < Test::Unit::TestCase
187
193
  end
188
194
 
189
195
  def test_para_before_block_html_should_not_wrap_in_p_tag
190
- markdown = render_with({:lax_html_blocks => true},
196
+ markdown = render_with({:lax_spacing => true},
191
197
  "Things to watch out for\n" +
192
198
  "<ul>\n<li>Blah</li>\n</ul>\n")
193
199
 
@@ -311,6 +317,15 @@ fenced
311
317
  assert render_with({:fenced_code_blocks => true}, text) =~ /<code/
312
318
  end
313
319
 
320
+ def test_that_fenced_flag_works_without_space
321
+ text = "foo\nbar\n```\nsome\ncode\n```\nbaz"
322
+ out = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true, :lax_spacing => true).render(text)
323
+ assert out.include?("<pre><code>")
324
+
325
+ out = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true).render(text)
326
+ assert !out.include?("<pre><code>")
327
+ end
328
+
314
329
  def test_that_headers_are_linkable
315
330
  markdown = @markdown.render('### Hello [GitHub](http://github.com)')
316
331
  html_equal "<h3>Hello <a href=\"http://github.com\">GitHub</a></h3>", markdown
@@ -327,6 +342,14 @@ text
327
342
  rd = render_with({:space_after_headers => true}, "#123 a header yes\n")
328
343
  assert rd !~ /<h1>/
329
344
  end
345
+
346
+ def test_proper_intra_emphasis
347
+ md = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :no_intra_emphasis => true)
348
+ assert render_with({:no_intra_emphasis => true}, "http://en.wikipedia.org/wiki/Dave_Allen_(comedian)") !~ /<em>/
349
+ assert render_with({:no_intra_emphasis => true}, "this fails: hello_world_") !~ /<em>/
350
+ assert render_with({:no_intra_emphasis => true}, "this also fails: hello_world_#bye") !~ /<em>/
351
+ assert render_with({:no_intra_emphasis => true}, "this works: hello_my_world") !~ /<em>/
352
+ end
330
353
  end
331
354
 
332
355
  class CustomRenderTest < Test::Unit::TestCase
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redcarpet
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
- - 1
9
- - 1
10
- version: 2.1.1
8
+ - 2
9
+ - 0
10
+ version: 2.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Natacha Port\xC3\xA9"
@@ -16,10 +16,11 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-09-14 00:00:00 Z
19
+ date: 2012-10-11 00:00:00 +02:00
20
+ default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
22
- name: rake-compiler
23
+ name: nokogiri
23
24
  prerelease: false
24
25
  requirement: &id001 !ruby/object:Gem::Requirement
25
26
  none: false
@@ -32,6 +33,20 @@ dependencies:
32
33
  version: "0"
33
34
  type: :development
34
35
  version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake-compiler
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :development
49
+ version_requirements: *id002
35
50
  description: A fast, safe and extensible Markdown to (X)HTML parser
36
51
  email: vicent@github.com
37
52
  executables:
@@ -42,6 +57,8 @@ extra_rdoc_files:
42
57
  - COPYING
43
58
  files:
44
59
  - COPYING
60
+ - Gemfile
61
+ - Gemfile.lock
45
62
  - README.markdown
46
63
  - Rakefile
47
64
  - bin/redcarpet
@@ -70,7 +87,8 @@ files:
70
87
  - lib/redcarpet/render_strip.rb
71
88
  - redcarpet.gemspec
72
89
  - test/redcarpet_test.rb
73
- homepage: http://github.com/tanoku/redcarpet
90
+ has_rdoc: true
91
+ homepage: http://github.com/vmg/redcarpet
74
92
  licenses: []
75
93
 
76
94
  post_install_message:
@@ -99,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
117
  requirements: []
100
118
 
101
119
  rubyforge_project:
102
- rubygems_version: 1.8.15
120
+ rubygems_version: 1.6.2
103
121
  signing_key:
104
122
  specification_version: 3
105
123
  summary: Markdown that smells nice