redcarpet 3.2.3 → 3.3.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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 43a33037d69f1dd517faf8a01c848668c225418d
4
- data.tar.gz: 79ecfd87ac885f4c9a8af16dd9059927e8fe4c52
3
+ metadata.gz: f1ec4be4477178cfdbddb7bef23823f45b62fa49
4
+ data.tar.gz: 8d444aba2d98347c039435dadc795d642d92c7c1
5
5
  SHA512:
6
- metadata.gz: 976b1611046fb3dc9423d4100d67ba4539e54484ea25073f8503a5d1c4ebc483bec3d9ee704890ab7f9ffaf9ac515f39fd682d81cee132c3c243463423714eba
7
- data.tar.gz: 26a7e3d6bdaffc67c59f02b7935a2aea3a42d7cd1909854d16aa36a4135abcf882b13ed7d2e83321a4b8cd65c8aa83d0296c5b2aef221860ecf49fd406fa76d8
6
+ metadata.gz: 6f7de4add3ffb9325b0feb63d5353cc8d946704fbd9835a7e549d8adcab9509ac78c832089fce6fb869d40b836a6db79c7050a3f469946bb33d740104f4c3164
7
+ data.tar.gz: 8cf876f963adce44ba5513028e1a01b0a79beb649233f7e7f2355b26e4148d28991c9216d32c711caa96e344713ef51886a4e85e784ce8af95f1c34fc55b3bfc
data/COPYING CHANGED
File without changes
@@ -332,6 +332,43 @@ SmartyPants works on top of already-rendered HTML, and will ignore replacements
332
332
  inside the content of HTML tags and inside specific HTML blocks such as
333
333
  `<code>` or `<pre>`.
334
334
 
335
+ What? You really want to mix Markdown renderers?
336
+ ------------------------------------------------
337
+
338
+ Redcarpet used to be a drop-in replacement for Redcloth. This is no longer the
339
+ case since version 2 -- it now has its own API, but retains the old name. Yes,
340
+ that does mean that Redcarpet is not backwards-compatible with the 1.X
341
+ versions.
342
+
343
+ Each renderer has its own API and its own set of extensions: you should choose one
344
+ (it doesn't have to be Redcarpet, though that would be great!), write your
345
+ software accordingly, and force your users to install it. That's the
346
+ only way to have reliable and predictable Markdown output on your program.
347
+
348
+ Markdown is already ill-specified enough; if you create software that is
349
+ renderer-independent, the results will be completely unreliable!
350
+
351
+ Still, if major forces (let's say, tornadoes or other natural disasters) force you
352
+ to keep a Markdown-compatibility layer, Redcarpet also supports this:
353
+
354
+ ~~~~~ ruby
355
+ require 'redcarpet/compat'
356
+ ~~~~~
357
+
358
+ Requiring the compatibility library will declare a `Markdown` class with the
359
+ classical RedCloth API, e.g.
360
+
361
+ ~~~~~ ruby
362
+ Markdown.new('this is my text').to_html
363
+ ~~~~~
364
+
365
+ This class renders 100% standards compliant Markdown with 0 extensions. Nada.
366
+ Don't even try to enable extensions with a compatibility layer, because
367
+ that's a maintenance nightmare and won't work.
368
+
369
+ On a related topic: if your Markdown gem has a `lib/markdown.rb` file that
370
+ monkeypatches the Markdown class, you're a terrible human being. Just saying.
371
+
335
372
  Boring legal stuff
336
373
  ------------------
337
374
 
@@ -1,43 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- # Usage: redcarpet [--parse-<extension>...] [--render-<extension>...] [--smarty] [<file>...]
3
- # Convert one or more Markdown files to HTML and write to standard output. With
4
- # no <file> or when <file> is '-', read Markdown source text from standard input.
5
- # With <extension>s, perform additional Markdown processing before writing output.
6
- # With --smarty, use the SmartyHTML renderer
7
- if ARGV.include?('--help') or ARGV.include?('-h')
8
- File.read(__FILE__).split("\n").grep(/^# /).each do |line|
9
- puts line[2..-1]
10
- end
11
- exit 0
12
- end
2
+ lib_path = File.expand_path('../../lib', __FILE__)
3
+ $:.unshift(lib_path)
13
4
 
14
- require 'redcarpet'
5
+ require 'redcarpet/cli'
15
6
 
16
- if ARGV.include?('--version') or ARGV.include?('-v')
17
- puts "Redcarpet #{Redcarpet::VERSION}"
18
- exit 0
19
- end
20
-
21
- root = File.expand_path('../../', __FILE__)
22
- $:.unshift File.expand_path('lib', root)
23
-
24
- render_extensions = {}
25
- parse_extensions = {}
26
- renderer = Redcarpet::Render::HTML
27
-
28
- ARGV.delete_if do |arg|
29
- if arg =~ /^--render-([\w-]+)$/
30
- arg = $1.gsub('-', '_')
31
- render_extensions[arg.to_sym] = true
32
- elsif arg =~ /^--parse-([\w-]+)$/
33
- arg = $1.gsub('-', '_')
34
- parse_extensions[arg.to_sym] = true
35
- elsif arg == '--smarty'
36
- renderer = Redcarpet::Render::SmartyHTML
37
- else
38
- false
39
- end
40
- end
41
-
42
- render = renderer.new(render_extensions)
43
- STDOUT.write(Redcarpet::Markdown.new(render, parse_extensions).render(ARGF.read))
7
+ Redcarpet::CLI.process(ARGV)
@@ -94,14 +94,14 @@ bufnew(size_t unit)
94
94
 
95
95
  /* bufnullterm: NULL-termination of the string array */
96
96
  const char *
97
- bufcstr(struct buf *buf)
97
+ bufcstr(const struct buf *buf)
98
98
  {
99
99
  assert(buf && buf->unit);
100
100
 
101
101
  if (buf->size < buf->asize && buf->data[buf->size] == 0)
102
102
  return (char *)buf->data;
103
103
 
104
- if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1) == 0) {
104
+ if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1) == BUF_OK) {
105
105
  buf->data[buf->size] = 0;
106
106
  return (char *)buf->data;
107
107
  }
@@ -118,7 +118,7 @@ bufprintf(struct buf *buf, const char *fmt, ...)
118
118
 
119
119
  assert(buf && buf->unit);
120
120
 
121
- if (buf->size >= buf->asize && bufgrow(buf, buf->size + 1) < 0)
121
+ if (buf->size >= buf->asize && bufgrow(buf, buf->size + 1) < BUF_OK)
122
122
  return;
123
123
 
124
124
  va_start(ap, fmt);
@@ -136,7 +136,7 @@ bufprintf(struct buf *buf, const char *fmt, ...)
136
136
  }
137
137
 
138
138
  if ((size_t)n >= buf->asize - buf->size) {
139
- if (bufgrow(buf, buf->size + n + 1) < 0)
139
+ if (bufgrow(buf, buf->size + n + 1) < BUF_OK)
140
140
  return;
141
141
 
142
142
  va_start(ap, fmt);
@@ -156,7 +156,7 @@ bufput(struct buf *buf, const void *data, size_t len)
156
156
  {
157
157
  assert(buf && buf->unit);
158
158
 
159
- if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0)
159
+ if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < BUF_OK)
160
160
  return;
161
161
 
162
162
  memcpy(buf->data + buf->size, data, len);
@@ -177,7 +177,7 @@ bufputc(struct buf *buf, int c)
177
177
  {
178
178
  assert(buf && buf->unit);
179
179
 
180
- if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0)
180
+ if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < BUF_OK)
181
181
  return;
182
182
 
183
183
  buf->data[buf->size] = c;
@@ -55,7 +55,7 @@ int bufgrow(struct buf *, size_t);
55
55
  struct buf *bufnew(size_t) __attribute__ ((malloc));
56
56
 
57
57
  /* bufnullterm: NUL-termination of the string array (making a C-string) */
58
- const char *bufcstr(struct buf *);
58
+ const char *bufcstr(const struct buf *);
59
59
 
60
60
  /* bufprefix: compare the beginning of a buffer with a string */
61
61
  int bufprefix(const struct buf *buf, const char *prefix);
@@ -17,7 +17,6 @@
17
17
 
18
18
  #include "markdown.h"
19
19
  #include "html.h"
20
- #include "ruby.h"
21
20
  #include <string.h>
22
21
  #include <stdlib.h>
23
22
  #include <stdio.h>
@@ -125,7 +124,7 @@ rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, v
125
124
  if (lang && lang->size) {
126
125
  size_t i, cls;
127
126
  if (options->flags & HTML_PRETTIFY) {
128
- BUFPUTSL(ob, "<pre><code class=\"prettyprint ");
127
+ BUFPUTSL(ob, "<pre><code class=\"prettyprint lang-");
129
128
  cls++;
130
129
  } else {
131
130
  BUFPUTSL(ob, "<pre><code class=\"");
@@ -265,17 +264,56 @@ rndr_linebreak(struct buf *ob, void *opaque)
265
264
  return 1;
266
265
  }
267
266
 
268
- char *header_anchor(struct buf *text)
267
+ char *header_anchor(const struct buf *buffer)
269
268
  {
270
- VALUE str = rb_str_new2(bufcstr(text));
271
- VALUE space_regex = rb_reg_new(" +", 2 /* length */, 0);
272
- VALUE tags_regex = rb_reg_new("<\\/?[^>]*>", 10, 0);
269
+ size_t i = 0, j, k, size = buffer->size;
273
270
 
274
- VALUE heading = rb_funcall(str, rb_intern("gsub"), 2, space_regex, rb_str_new2("-"));
275
- heading = rb_funcall(heading, rb_intern("gsub"), 2, tags_regex, rb_str_new2(""));
276
- heading = rb_funcall(heading, rb_intern("downcase"), 0);
271
+ char text[size];
272
+ strcpy(text, bufcstr(buffer));
277
273
 
278
- return StringValueCStr(heading);
274
+ char raw_string[size];
275
+
276
+ /* Strip down the inline HTML markup if needed */
277
+ if (strchr(text, '<') < strchr(text, '>')) {
278
+ char* part = strtok(text, "<>");
279
+
280
+ /* Once every two times, the yielded token is the
281
+ content of a HTML tag so we don't need to copy it */
282
+ for (k = 0; part != NULL; k++) {
283
+ if (k == 0)
284
+ strcpy(raw_string, part);
285
+ else if (k % 2 == 0)
286
+ strcat(raw_string, part);
287
+
288
+ part = strtok(NULL, "<>");
289
+ }
290
+
291
+ size = strlen(raw_string);
292
+ } else {
293
+ strcpy(raw_string, text);
294
+ }
295
+
296
+ char* heading = malloc(size * sizeof(char));
297
+
298
+ /* Remove leading stripped chars */
299
+ while (STRIPPED_CHAR(raw_string[i])) i++;
300
+
301
+ /* Dasherize the string removing extra white spaces
302
+ and stripped chars */
303
+ for (j = 0; i < size; i++, j++) {
304
+ while ((i+1) < size && STRIPPED_CHAR(raw_string[i]) && STRIPPED_CHAR(raw_string[i+1]))
305
+ i++;
306
+
307
+ if (STRIPPED_CHAR(raw_string[i]) && i == size - 1)
308
+ break;
309
+ else if (STRIPPED_CHAR(raw_string[i]))
310
+ heading[j] = '-';
311
+ else
312
+ heading[j] = tolower(raw_string[i]);
313
+ }
314
+
315
+ heading[j++] = '\0';
316
+ return heading;
279
317
  }
280
318
 
281
319
  static void
@@ -395,15 +433,30 @@ rndr_paragraph(struct buf *ob, const struct buf *text, void *opaque)
395
433
  static void
396
434
  rndr_raw_block(struct buf *ob, const struct buf *text, void *opaque)
397
435
  {
398
- size_t org, sz;
399
- if (!text) return;
400
- sz = text->size;
401
- while (sz > 0 && text->data[sz - 1] == '\n') sz--;
402
- org = 0;
403
- while (org < sz && text->data[org] == '\n') org++;
404
- if (org >= sz) return;
405
- if (ob->size) bufputc(ob, '\n');
406
- bufput(ob, text->data + org, sz - org);
436
+ size_t org, size;
437
+ struct html_renderopt *options = opaque;
438
+
439
+ if (!text)
440
+ return;
441
+
442
+ size = text->size;
443
+ while (size > 0 && text->data[size - 1] == '\n')
444
+ size--;
445
+
446
+ for (org = 0; org < size && text->data[org] == '\n'; ++org)
447
+
448
+ if (org >= size)
449
+ return;
450
+
451
+ /* Remove style tags if the `:no_styles` option is enabled */
452
+ if ((options->flags & HTML_SKIP_STYLE) != 0 &&
453
+ sdhtml_is_tag(text->data, size, "style"))
454
+ return;
455
+
456
+ if (ob->size)
457
+ bufputc(ob, '\n');
458
+
459
+ bufput(ob, text->data + org, size - org);
407
460
  bufputc(ob, '\n');
408
461
  }
409
462
 
@@ -429,10 +482,15 @@ static int
429
482
  rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque)
430
483
  {
431
484
  struct html_renderopt *options = opaque;
432
- if (!link || !link->size) return 0;
485
+
486
+ if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size))
487
+ return 0;
433
488
 
434
489
  BUFPUTSL(ob, "<img src=\"");
435
- escape_href(ob, link->data, link->size);
490
+
491
+ if (link && link->size)
492
+ escape_href(ob, link->data, link->size);
493
+
436
494
  BUFPUTSL(ob, "\" alt=\"");
437
495
 
438
496
  if (alt && alt->size)
@@ -440,7 +498,8 @@ rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, cons
440
498
 
441
499
  if (title && title->size) {
442
500
  BUFPUTSL(ob, "\" title=\"");
443
- escape_html(ob, title->data, title->size); }
501
+ escape_html(ob, title->data, title->size);
502
+ }
444
503
 
445
504
  bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
446
505
  return 1;
@@ -452,7 +511,7 @@ rndr_raw_html(struct buf *ob, const struct buf *text, void *opaque)
452
511
  struct html_renderopt *options = opaque;
453
512
 
454
513
  /* HTML_ESCAPE overrides SKIP_HTML, SKIP_STYLE, SKIP_LINKS and SKIP_IMAGES
455
- * It doens't see if there are any valid tags, just escape all of them. */
514
+ It doesn't see if there are any valid tags, just escape all of them. */
456
515
  if((options->flags & HTML_ESCAPE) != 0) {
457
516
  escape_html(ob, text->data, text->size);
458
517
  return 1;
@@ -636,7 +695,14 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
636
695
  }
637
696
 
638
697
  bufprintf(ob, "<a href=\"#%s\">", header_anchor(text));
639
- if (text) escape_html(ob, text->data, text->size);
698
+
699
+ if (text) {
700
+ if (options->flags & HTML_ESCAPE)
701
+ escape_html(ob, text->data, text->size);
702
+ else
703
+ bufput(ob, text->data, text->size);
704
+ }
705
+
640
706
  BUFPUTSL(ob, "</a>\n");
641
707
  }
642
708
  }
@@ -661,7 +727,7 @@ toc_finalize(struct buf *ob, void *opaque)
661
727
  }
662
728
 
663
729
  void
664
- sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, int nesting_level)
730
+ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, unsigned int render_flags)
665
731
  {
666
732
  static const struct sd_callbacks cb_default = {
667
733
  NULL,
@@ -702,8 +768,7 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *optio
702
768
  };
703
769
 
704
770
  memset(options, 0x0, sizeof(struct html_renderopt));
705
- options->flags = HTML_TOC;
706
- options->toc_data.nesting_level = nesting_level;
771
+ options->flags = render_flags;
707
772
 
708
773
  memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
709
774
  }
@@ -65,11 +65,17 @@ extern void
65
65
  sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, unsigned int render_flags);
66
66
 
67
67
  extern void
68
- sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, int nesting_level);
68
+ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, unsigned int render_flags);
69
69
 
70
70
  extern void
71
71
  sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size);
72
72
 
73
+ /* header method used internally in Redcarpet */
74
+ char *header_anchor(const struct buf *buffer);
75
+
76
+ #define STRIPPED_CHARS " -&+$,/:;=?@\"#{}|^~[]`\\*()%.!'"
77
+ #define STRIPPED_CHAR(x) (strchr(STRIPPED_CHARS, x) != NULL)
78
+
73
79
  #ifdef __cplusplus
74
80
  }
75
81
  #endif
@@ -1119,7 +1119,7 @@ char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset
1119
1119
  title_e--;
1120
1120
 
1121
1121
  /* checking for closing quote presence */
1122
- if (data[title_e] != '\'' && data[title_e] != '"') {
1122
+ if (data[title_e] != '\'' && data[title_e] != '"') {
1123
1123
  title_b = title_e = 0;
1124
1124
  link_e = i;
1125
1125
  }
@@ -1548,7 +1548,7 @@ prefix_oli(uint8_t *data, size_t size)
1548
1548
  return i + 2;
1549
1549
  }
1550
1550
 
1551
- /* prefix_uli • returns ordered list item prefix */
1551
+ /* prefix_uli • returns unordered list item prefix */
1552
1552
  static size_t
1553
1553
  prefix_uli(uint8_t *data, size_t size)
1554
1554
  {
@@ -1620,7 +1620,7 @@ parse_blockquote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
1620
1620
  static size_t
1621
1621
  parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render);
1622
1622
 
1623
- /* parse_blockquote • handles parsing of a regular paragraph */
1623
+ /* parse_paragraph • handles parsing of a regular paragraph */
1624
1624
  static size_t
1625
1625
  parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
1626
1626
  {
@@ -2801,6 +2801,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2801
2801
 
2802
2802
  struct buf *text;
2803
2803
  size_t beg, end;
2804
+ int in_fence = 0;
2804
2805
 
2805
2806
  text = bufnew(64);
2806
2807
  if (!text)
@@ -2812,7 +2813,8 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2812
2813
  /* reset the references table */
2813
2814
  memset(&md->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
2814
2815
 
2815
- int footnotes_enabled = md->ext_flags & MKDEXT_FOOTNOTES;
2816
+ int footnotes_enabled = md->ext_flags & MKDEXT_FOOTNOTES;
2817
+ int codefences_enabled = md->ext_flags & MKDEXT_FENCED_CODE;
2816
2818
 
2817
2819
  /* reset the footnotes lists */
2818
2820
  if (footnotes_enabled) {
@@ -2828,10 +2830,13 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2828
2830
  if (doc_size >= 3 && memcmp(document, UTF8_BOM, 3) == 0)
2829
2831
  beg += 3;
2830
2832
 
2831
- while (beg < doc_size) /* iterating over lines */
2832
- if (footnotes_enabled && is_footnote(document, beg, doc_size, &end, &md->footnotes_found))
2833
+ while (beg < doc_size) { /* iterating over lines */
2834
+ if (codefences_enabled && (is_codefence(document + beg, doc_size - beg, NULL) != 0))
2835
+ in_fence = !in_fence;
2836
+
2837
+ if (!in_fence && footnotes_enabled && is_footnote(document, beg, doc_size, &end, &md->footnotes_found))
2833
2838
  beg = end;
2834
- else if (is_ref(document, beg, doc_size, &end, md->refs))
2839
+ else if (!in_fence && is_ref(document, beg, doc_size, &end, md->refs))
2835
2840
  beg = end;
2836
2841
  else { /* skipping to the next line */
2837
2842
  end = beg;
@@ -2851,6 +2856,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2851
2856
 
2852
2857
  beg = end;
2853
2858
  }
2859
+ }
2854
2860
 
2855
2861
  /* pre-grow the output buffer to minimize allocations */
2856
2862
  bufgrow(ob, MARKDOWN_GROW(text->size));
@@ -2861,7 +2867,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2861
2867
 
2862
2868
  if (text->size) {
2863
2869
  /* adding a final newline if not already present */
2864
- if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r')
2870
+ if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r')
2865
2871
  bufputc(text, '\n');
2866
2872
 
2867
2873
  parse_block(ob, md, text->data, text->size);
@@ -2874,6 +2880,9 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
2874
2880
  if (md->cb.doc_footer)
2875
2881
  md->cb.doc_footer(ob, md->opaque);
2876
2882
 
2883
+ /* Null-terminate the buffer */
2884
+ bufcstr(ob);
2885
+
2877
2886
  /* clean-up */
2878
2887
  bufrelease(text);
2879
2888
  free_link_refs(md->refs);