redcarpet 3.3.2 → 3.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  }