redcarpet 3.3.2 → 3.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +1,23 @@
1
1
  /*
2
- * Copyright (c) 2011, Vicent Marti
2
+ * Copyright (c) 2015, Vicent Marti
3
3
  *
4
- * Permission to use, copy, modify, and distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
7
10
  *
8
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
15
21
  */
16
22
 
17
23
  #include "buffer.h"
@@ -83,6 +89,12 @@ word_boundary(uint8_t c)
83
89
  return c == 0 || isspace(c) || ispunct(c);
84
90
  }
85
91
 
92
+ static inline int
93
+ fraction_boundary(uint8_t c)
94
+ {
95
+ return c == 0 || isspace(c) || (c != '/' && ispunct(c));
96
+ }
97
+
86
98
  // If 'text' begins with any kind of single quote (e.g. "'" or "'" etc.),
87
99
  // returns the length of the sequence of characters that makes up the single-
88
100
  // quote. Otherwise, returns zero.
@@ -139,6 +151,9 @@ smartypants_squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previo
139
151
  return next_squote_len;
140
152
  }
141
153
 
154
+ if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
155
+ return 0;
156
+
142
157
  // trailing single quotes: students', tryin'
143
158
  if (word_boundary(t1)) {
144
159
  BUFPUTSL(ob, "’");
@@ -166,9 +181,6 @@ smartypants_squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previo
166
181
  }
167
182
  }
168
183
 
169
- if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
170
- return 0;
171
-
172
184
  bufput(ob, squote_text, squote_size);
173
185
  return 0;
174
186
  }
@@ -282,16 +294,16 @@ smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, uint8_t
282
294
  static size_t
283
295
  smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
284
296
  {
285
- if (word_boundary(previous_char) && size >= 3) {
297
+ if (fraction_boundary(previous_char) && size >= 3) {
286
298
  if (text[0] == '1' && text[1] == '/' && text[2] == '2') {
287
- if (size == 3 || word_boundary(text[3])) {
299
+ if (size == 3 || fraction_boundary(text[3])) {
288
300
  BUFPUTSL(ob, "½");
289
301
  return 2;
290
302
  }
291
303
  }
292
304
 
293
305
  if (text[0] == '1' && text[1] == '/' && text[2] == '4') {
294
- if (size == 3 || word_boundary(text[3]) ||
306
+ if (size == 3 || fraction_boundary(text[3]) ||
295
307
  (size >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h')) {
296
308
  BUFPUTSL(ob, "¼");
297
309
  return 2;
@@ -299,7 +311,7 @@ smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, uint8_t pr
299
311
  }
300
312
 
301
313
  if (text[0] == '3' && text[1] == '/' && text[2] == '4') {
302
- if (size == 3 || word_boundary(text[3]) ||
314
+ if (size == 3 || fraction_boundary(text[3]) ||
303
315
  (size >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's')) {
304
316
  BUFPUTSL(ob, "¾");
305
317
  return 2;
@@ -329,6 +341,7 @@ smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t prev
329
341
  };
330
342
  static const size_t skip_tags_count = 8;
331
343
 
344
+ size_t next_to_closing_a = 0;
332
345
  size_t tag, i = 0;
333
346
 
334
347
  while (i < size && text[i] != '>')
@@ -357,7 +370,23 @@ smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t prev
357
370
  i++;
358
371
  }
359
372
 
373
+ if (sdhtml_is_tag(text, size, "a") == HTML_TAG_CLOSE) {
374
+ while (i < size && text[i] != '>')
375
+ i++;
376
+
377
+ next_to_closing_a = 1;
378
+ }
379
+
360
380
  bufput(ob, text, i + 1);
381
+
382
+ // Pretty tricky: since people may refer to something or someone
383
+ // with a link but use the possessive form right after it, we need
384
+ // to check whether a single quote is next to a closing "</a"> tag.
385
+ if (next_to_closing_a && strncmp("&#39;", text+(i+1), 5) == 0) {
386
+ bufput(ob, "&rsquo;", 7);
387
+ i += 5;
388
+ }
389
+
361
390
  return i;
362
391
  }
363
392
 
@@ -441,5 +470,3 @@ sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size)
441
470
  }
442
471
  }
443
472
  }
444
-
445
-
@@ -1,20 +1,24 @@
1
- /* markdown.c - generic markdown parser */
2
-
3
1
  /*
4
2
  * Copyright (c) 2009, Natacha Porté
5
- * Copyright (c) 2011, Vicent Marti
3
+ * Copyright (c) 2015, Vicent Marti
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
6
11
  *
7
- * Permission to use, copy, modify, and distribute this software for any
8
- * purpose with or without fee is hereby granted, provided that the above
9
- * copyright notice and this permission notice appear in all copies.
12
+ * The above copyright notice and this permission notice shall be included in
13
+ * all copies or substantial portions of the Software.
10
14
  *
11
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ * THE SOFTWARE.
18
22
  */
19
23
 
20
24
  #include "markdown.h"
@@ -88,7 +92,6 @@ typedef size_t
88
92
 
89
93
  static size_t char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
90
94
  static size_t char_underline(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
91
- static size_t char_highlight(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
92
95
  static size_t char_quote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
93
96
  static size_t char_linebreak(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
94
97
  static size_t char_codespan(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
@@ -609,7 +612,7 @@ parse_emph1(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size
609
612
  if (data[i] == c && !_isspace(data[i - 1])) {
610
613
 
611
614
  if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
612
- if (i + i < size && _isalnum(data[i + 1]))
615
+ if (i + 1 < size && _isalnum(data[i + 1]))
613
616
  continue;
614
617
  }
615
618
 
@@ -841,7 +844,6 @@ char_quote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offse
841
844
  return end;
842
845
  }
843
846
 
844
-
845
847
  /* char_escape • '\\' backslash escape */
846
848
  static size_t
847
849
  char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
@@ -2335,7 +2337,7 @@ parse_table_header(
2335
2337
  if (i < under_end && data[i] != '|' && data[i] != '+')
2336
2338
  break;
2337
2339
 
2338
- if (dashes < 3)
2340
+ if (dashes < 1)
2339
2341
  break;
2340
2342
 
2341
2343
  i++;
@@ -2753,10 +2755,13 @@ sd_markdown_new(
2753
2755
  if (md->cb.emphasis || md->cb.double_emphasis || md->cb.triple_emphasis) {
2754
2756
  md->active_char['*'] = MD_CHAR_EMPHASIS;
2755
2757
  md->active_char['_'] = MD_CHAR_EMPHASIS;
2758
+
2756
2759
  if (extensions & MKDEXT_STRIKETHROUGH)
2757
2760
  md->active_char['~'] = MD_CHAR_EMPHASIS;
2758
2761
  if (extensions & MKDEXT_HIGHLIGHT)
2759
2762
  md->active_char['='] = MD_CHAR_EMPHASIS;
2763
+ if (extensions & MKDEXT_QUOTE)
2764
+ md->active_char['"'] = MD_CHAR_QUOTE;
2760
2765
  }
2761
2766
 
2762
2767
  if (md->cb.codespan)
@@ -2781,9 +2786,6 @@ sd_markdown_new(
2781
2786
  if (extensions & MKDEXT_SUPERSCRIPT)
2782
2787
  md->active_char['^'] = MD_CHAR_SUPERSCRIPT;
2783
2788
 
2784
- if (extensions & MKDEXT_QUOTE)
2785
- md->active_char['"'] = MD_CHAR_QUOTE;
2786
-
2787
2789
  /* Extension data */
2788
2790
  md->ext_flags = extensions;
2789
2791
  md->opaque = opaque;
@@ -1,19 +1,24 @@
1
- /* markdown.h - generic markdown parser */
2
-
3
1
  /*
4
2
  * Copyright (c) 2009, Natacha Porté
3
+ * Copyright (c) 2015, Vicent Marti
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
5
11
  *
6
- * Permission to use, copy, modify, and distribute this software for any
7
- * purpose with or without fee is hereby granted, provided that the above
8
- * copyright notice and this permission notice appear in all copies.
12
+ * The above copyright notice and this permission notice shall be included in
13
+ * all copies or substantial portions of the Software.
9
14
  *
10
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ * THE SOFTWARE.
17
22
  */
18
23
 
19
24
  #ifndef MARKDOWN_H__
@@ -1,22 +1,30 @@
1
1
  /*
2
- * Copyright (c) 2011, Vicent Marti
2
+ * Copyright (c) 2015, Vicent Marti
3
3
  *
4
- * Permission to use, copy, modify, and distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
7
10
  *
8
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
15
21
  */
22
+
16
23
  #include "redcarpet.h"
17
24
 
18
25
  VALUE rb_mRedcarpet;
19
26
  VALUE rb_cMarkdown;
27
+ VALUE rb_cRenderHTML_TOC;
20
28
 
21
29
  extern VALUE rb_cRenderBase;
22
30
 
@@ -79,7 +87,7 @@ rb_redcarpet_md__free(void *markdown)
79
87
 
80
88
  static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
81
89
  {
82
- VALUE rb_markdown, rb_rndr, hash;
90
+ VALUE rb_markdown, rb_rndr, hash, rndr_options;
83
91
  unsigned int extensions = 0;
84
92
 
85
93
  struct rb_redcarpet_rndr *rndr;
@@ -94,8 +102,23 @@ static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
94
102
  if (!rb_obj_is_kind_of(rb_rndr, rb_cRenderBase))
95
103
  rb_raise(rb_eTypeError, "Invalid Renderer instance given");
96
104
 
105
+ /**
106
+ * Automatically enable the `fenced_code_blocks` option if
107
+ * given a kind of `HTML_TOC` object since many languages
108
+ * like Ruby use the sharp to comment code so these comments
109
+ * would be processed as titles.
110
+ */
111
+ if (rb_obj_is_kind_of(rb_rndr, rb_cRenderHTML_TOC))
112
+ extensions |= MKDEXT_FENCED_CODE;
113
+
97
114
  Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, rndr);
98
115
 
116
+ /* Merge the current options in the @options hash */
117
+ if (hash != Qnil) {
118
+ rndr_options = rb_funcall(rb_iv_get(rb_rndr, "@options"), rb_intern("merge"), 1, hash);
119
+ rb_iv_set(rb_rndr, "@options", rndr_options);
120
+ }
121
+
99
122
  markdown = sd_markdown_new(extensions, 16, &rndr->callbacks, &rndr->options);
100
123
  if (!markdown)
101
124
  rb_raise(rb_eRuntimeError, "Failed to create new Renderer class");
@@ -158,4 +181,3 @@ void Init_redcarpet()
158
181
 
159
182
  Init_redcarpet_rndr();
160
183
  }
161
-
@@ -1,17 +1,23 @@
1
1
  /*
2
- * Copyright (c) 2011, Vicent Marti
2
+ * Copyright (c) 2015, Vicent Marti
3
3
  *
4
- * Permission to use, copy, modify, and distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
7
10
  *
8
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
15
21
  */
16
22
 
17
23
  #include "redcarpet.h"
@@ -34,10 +40,10 @@
34
40
  }
35
41
 
36
42
  extern VALUE rb_mRedcarpet;
43
+ extern VALUE rb_cRenderHTML_TOC;
37
44
  VALUE rb_mRender;
38
45
  VALUE rb_cRenderBase;
39
46
  VALUE rb_cRenderHTML;
40
- VALUE rb_cRenderHTML_TOC;
41
47
  VALUE rb_mSmartyPants;
42
48
 
43
49
  #define buf2str(t) ((t) ? rb_enc_str_new((const char*)(t)->data, (t)->size, opt->active_enc) : Qnil)
@@ -369,16 +375,22 @@ static void rb_redcarpet_rbase_mark(struct rb_redcarpet_rndr *rndr)
369
375
  rb_gc_mark(rndr->options.link_attributes);
370
376
  }
371
377
 
378
+ static void rndr_deallocate(void *rndr)
379
+ {
380
+ xfree(rndr);
381
+ }
382
+
372
383
  static VALUE rb_redcarpet_rbase_alloc(VALUE klass)
373
384
  {
374
385
  struct rb_redcarpet_rndr *rndr = ALLOC(struct rb_redcarpet_rndr);
375
386
  memset(rndr, 0x0, sizeof(struct rb_redcarpet_rndr));
376
- return Data_Wrap_Struct(klass, rb_redcarpet_rbase_mark, NULL, rndr);
387
+ return Data_Wrap_Struct(klass, rb_redcarpet_rbase_mark, rndr_deallocate, rndr);
377
388
  }
378
389
 
379
390
  static void rb_redcarpet__overload(VALUE self, VALUE base_class)
380
391
  {
381
392
  struct rb_redcarpet_rndr *rndr;
393
+ VALUE options_ivar;
382
394
 
383
395
  Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
384
396
  rndr->options.self = self;
@@ -399,6 +411,10 @@ static void rb_redcarpet__overload(VALUE self, VALUE base_class)
399
411
  dest[i] = source[i];
400
412
  }
401
413
  }
414
+
415
+ options_ivar = rb_attr_get(self, rb_intern("@options"));
416
+ if (options_ivar == Qundef || options_ivar == Qnil)
417
+ rb_iv_set(self, "@options", rb_hash_new());
402
418
  }
403
419
 
404
420
  static VALUE rb_redcarpet_rbase_init(VALUE self)
@@ -418,6 +434,9 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
418
434
  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
419
435
  Check_Type(hash, T_HASH);
420
436
 
437
+ /* Give access to the passed options through `@options` */
438
+ rb_iv_set(self, "@options", hash);
439
+
421
440
  /* escape_html */
422
441
  if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
423
442
  render_flags |= HTML_ESCAPE;
@@ -480,6 +499,9 @@ static VALUE rb_redcarpet_htmltoc_init(int argc, VALUE *argv, VALUE self)
480
499
  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
481
500
  Check_Type(hash, T_HASH);
482
501
 
502
+ /* Give access to the passed options through `@options` */
503
+ rb_iv_set(self, "@options", hash);
504
+
483
505
  /* escape_html */
484
506
  if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
485
507
  render_flags |= HTML_ESCAPE;
@@ -491,10 +513,22 @@ static VALUE rb_redcarpet_htmltoc_init(int argc, VALUE *argv, VALUE self)
491
513
  sdhtml_toc_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, render_flags);
492
514
  rb_redcarpet__overload(self, rb_cRenderHTML_TOC);
493
515
 
494
- if (!(NIL_P(nesting_level)))
495
- rndr->options.html.toc_data.nesting_level = NUM2INT(nesting_level);
496
- else
497
- rndr->options.html.toc_data.nesting_level = 6;
516
+ /* Check whether we are dealing with a Range object by
517
+ checking whether the object responds to min and max */
518
+ if (rb_respond_to(nesting_level, rb_intern("min")) &&
519
+ rb_respond_to(nesting_level, rb_intern("max"))) {
520
+ int min = NUM2INT(rb_funcall(nesting_level, rb_intern("min"), 0));
521
+ int max = NUM2INT(rb_funcall(nesting_level, rb_intern("max"), 0));
522
+
523
+ rndr->options.html.toc_data.nesting_bounds[0] = min;
524
+ rndr->options.html.toc_data.nesting_bounds[1] = max;
525
+ } else if (FIXNUM_P(nesting_level)) {
526
+ rndr->options.html.toc_data.nesting_bounds[0] = 1;
527
+ rndr->options.html.toc_data.nesting_bounds[1] = NUM2INT(nesting_level);
528
+ } else {
529
+ rndr->options.html.toc_data.nesting_bounds[0] = 1;
530
+ rndr->options.html.toc_data.nesting_bounds[1] = 6;
531
+ }
498
532
 
499
533
  return Qnil;
500
534
  }