greenmat 3.2.2.4 → 3.5.1.0

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 "greenmat.h"
@@ -34,10 +40,10 @@
34
40
  }
35
41
 
36
42
  extern VALUE rb_mGreenmat;
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_greenmat_rbase_mark(struct rb_greenmat_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_greenmat_rbase_alloc(VALUE klass)
373
384
  {
374
385
  struct rb_greenmat_rndr *rndr = ALLOC(struct rb_greenmat_rndr);
375
386
  memset(rndr, 0x0, sizeof(struct rb_greenmat_rndr));
376
- return Data_Wrap_Struct(klass, rb_greenmat_rbase_mark, NULL, rndr);
387
+ return Data_Wrap_Struct(klass, rb_greenmat_rbase_mark, rndr_deallocate, rndr);
377
388
  }
378
389
 
379
390
  static void rb_greenmat__overload(VALUE self, VALUE base_class)
380
391
  {
381
392
  struct rb_greenmat_rndr *rndr;
393
+ VALUE options_ivar;
382
394
 
383
395
  Data_Get_Struct(self, struct rb_greenmat_rndr, rndr);
384
396
  rndr->options.self = self;
@@ -399,6 +411,10 @@ static void rb_greenmat__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_greenmat_rbase_init(VALUE self)
@@ -418,6 +434,9 @@ static VALUE rb_greenmat_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;
@@ -472,25 +491,45 @@ static VALUE rb_greenmat_html_init(int argc, VALUE *argv, VALUE self)
472
491
  static VALUE rb_greenmat_htmltoc_init(int argc, VALUE *argv, VALUE self)
473
492
  {
474
493
  struct rb_greenmat_rndr *rndr;
475
- int nesting_level = 6;
476
- VALUE hash, key = Qnil;
494
+ unsigned int render_flags = HTML_TOC;
495
+ VALUE hash, nesting_level = Qnil;
477
496
 
478
497
  Data_Get_Struct(self, struct rb_greenmat_rndr, rndr);
479
498
 
480
499
  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
481
500
  Check_Type(hash, T_HASH);
482
501
 
483
- key = CSTR2SYM("nesting_level");
502
+ /* Give access to the passed options through `@options` */
503
+ rb_iv_set(self, "@options", hash);
484
504
 
485
- if (RTEST(rb_hash_aref(hash, key))) {
486
- Check_Type(rb_hash_aref(hash, key), T_FIXNUM);
487
- nesting_level = NUM2INT(rb_hash_aref(hash, key));
488
- }
505
+ /* escape_html */
506
+ if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
507
+ render_flags |= HTML_ESCAPE;
508
+
509
+ /* Nesting level */
510
+ nesting_level = rb_hash_aref(hash, CSTR2SYM("nesting_level"));
489
511
  }
490
512
 
491
- sdhtml_toc_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, nesting_level);
513
+ sdhtml_toc_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, render_flags);
492
514
  rb_greenmat__overload(self, rb_cRenderHTML_TOC);
493
515
 
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
+ }
532
+
494
533
  return Qnil;
495
534
  }
496
535
 
@@ -1,3 +1,25 @@
1
+ /*
2
+ * Copyright (c) 2015, Vicent Marti
3
+ *
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:
10
+ *
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.
21
+ */
22
+
1
23
  #ifndef GREENMAT_H__
2
24
  #define GREENMAT_H__
3
25
 
@@ -1,3 +1,25 @@
1
+ /*
2
+ * Copyright (c) 2015, Vicent Marti
3
+ *
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:
10
+ *
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.
21
+ */
22
+
1
23
  #ifndef HOUDINI_H__
2
24
  #define HOUDINI_H__
3
25
 
@@ -1,3 +1,25 @@
1
+ /*
2
+ * Copyright (c) 2015, Vicent Marti
3
+ *
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:
10
+ *
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.
21
+ */
22
+
1
23
  #include <assert.h>
2
24
  #include <stdio.h>
3
25
  #include <string.h>
@@ -22,10 +44,10 @@
22
44
  * have its native function (i.e. as an URL
23
45
  * component/separator) and hence needs no escaping.
24
46
  *
25
- * There are two exceptions: the chacters & (amp)
26
- * and ' (single quote) do not appear in the table.
27
- * They are meant to appear in the URL as components,
28
- * yet they require special HTML-entity escaping
47
+ * There is one exception: the ' (single quote)
48
+ * character does not appear in the table.
49
+ * It is meant to appear in the URL as components,
50
+ * however it require special HTML-entity escaping
29
51
  * to generate valid HTML markup.
30
52
  *
31
53
  * All other characters will be escaped to %XX.
@@ -34,7 +56,7 @@
34
56
  static const char HREF_SAFE[] = {
35
57
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36
58
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37
- 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
59
+ 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
38
60
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
39
61
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
40
62
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
@@ -73,12 +95,6 @@ houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size)
73
95
  break;
74
96
 
75
97
  switch (src[i]) {
76
- /* amp appears all the time in URLs, but needs
77
- * HTML-entity escaping to be inside an href */
78
- case '&':
79
- BUFPUTSL(ob, "&amp;");
80
- break;
81
-
82
98
  /* the single quote is a valid URL character
83
99
  * according to the standard; it needs HTML
84
100
  * entity escaping too */
@@ -1,3 +1,25 @@
1
+ /*
2
+ * Copyright (c) 2015, Vicent Marti
3
+ *
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:
10
+ *
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.
21
+ */
22
+
1
23
  #include <assert.h>
2
24
  #include <stdio.h>
3
25
  #include <string.h>
@@ -80,4 +102,3 @@ houdini_escape_html(struct buf *ob, const uint8_t *src, size_t size)
80
102
  {
81
103
  houdini_escape_html0(ob, src, size, 1);
82
104
  }
83
-
data/ext/greenmat/html.c CHANGED
@@ -1,23 +1,28 @@
1
1
  /*
2
2
  * Copyright (c) 2009, Natacha Porté
3
- * Copyright (c) 2011, Vicent Marti
3
+ * Copyright (c) 2015, Vicent Marti
4
4
  *
5
- * Permission to use, copy, modify, and distribute this software for any
6
- * purpose with or without fee is hereby granted, provided that the above
7
- * copyright notice and this permission notice appear in all copies.
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:
8
11
  *
9
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
12
+ * The above copyright notice and this permission notice shall be included in
13
+ * all copies or substantial portions of the Software.
14
+ *
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.
16
22
  */
17
23
 
18
24
  #include "markdown.h"
19
25
  #include "html.h"
20
- #include "ruby.h"
21
26
  #include <string.h>
22
27
  #include <stdlib.h>
23
28
  #include <stdio.h>
@@ -250,8 +255,15 @@ rndr_quote(struct buf *ob, const struct buf *text, void *opaque)
250
255
  if (!text || !text->size)
251
256
  return 0;
252
257
 
258
+ struct html_renderopt *options = opaque;
259
+
253
260
  BUFPUTSL(ob, "<q>");
254
- bufput(ob, text->data, text->size);
261
+
262
+ if (options->flags & HTML_ESCAPE)
263
+ escape_html(ob, text->data, text->size);
264
+ else
265
+ bufput(ob, text->data, text->size);
266
+
255
267
  BUFPUTSL(ob, "</q>");
256
268
 
257
269
  return 1;
@@ -265,17 +277,52 @@ rndr_linebreak(struct buf *ob, void *opaque)
265
277
  return 1;
266
278
  }
267
279
 
268
- char *header_anchor(struct buf *text)
280
+ static void
281
+ rndr_header_anchor(struct buf *out, const struct buf *anchor)
269
282
  {
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);
283
+ static const char *STRIPPED = " -&+$,/:;=?@\"#{}|^~[]`\\*()%.!'";
273
284
 
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);
285
+ const uint8_t *a = anchor->data;
286
+ const size_t size = anchor->size;
287
+ size_t i = 0;
288
+ int stripped = 0, inserted = 0;
277
289
 
278
- return StringValueCStr(heading);
290
+ for (; i < size; ++i) {
291
+ // skip html tags
292
+ if (a[i] == '<') {
293
+ while (i < size && a[i] != '>')
294
+ i++;
295
+ // skip html entities
296
+ } else if (a[i] == '&') {
297
+ while (i < size && a[i] != ';')
298
+ i++;
299
+ }
300
+ // replace non-ascii or invalid characters with dashes
301
+ else if (!isascii(a[i]) || strchr(STRIPPED, a[i])) {
302
+ if (inserted && !stripped)
303
+ bufputc(out, '-');
304
+ // and do it only once
305
+ stripped = 1;
306
+ }
307
+ else {
308
+ bufputc(out, tolower(a[i]));
309
+ stripped = 0;
310
+ inserted++;
311
+ }
312
+ }
313
+
314
+ // replace the last dash if there was anything added
315
+ if (stripped && inserted)
316
+ out->size--;
317
+
318
+ // if anchor found empty, use djb2 hash for it
319
+ if (!inserted && anchor->size) {
320
+ unsigned long hash = 5381;
321
+ for (i = 0; i < size; ++i) {
322
+ hash = ((hash << 5) + hash) + a[i]; /* h * 33 + c */
323
+ }
324
+ bufprintf(out, "part-%lx", hash);
325
+ }
279
326
  }
280
327
 
281
328
  static void
@@ -286,8 +333,12 @@ rndr_header(struct buf *ob, const struct buf *text, int level, void *opaque)
286
333
  if (ob->size)
287
334
  bufputc(ob, '\n');
288
335
 
289
- if ((options->flags & HTML_TOC) && (level <= options->toc_data.nesting_level))
290
- bufprintf(ob, "<h%d id=\"%s\">", level, header_anchor(text));
336
+ if ((options->flags & HTML_TOC) && level >= options->toc_data.nesting_bounds[0] &&
337
+ level <= options->toc_data.nesting_bounds[1]) {
338
+ bufprintf(ob, "<h%d id=\"", level);
339
+ rndr_header_anchor(ob, text);
340
+ BUFPUTSL(ob, "\">");
341
+ }
291
342
  else
292
343
  bufprintf(ob, "<h%d>", level);
293
344
 
@@ -395,15 +446,30 @@ rndr_paragraph(struct buf *ob, const struct buf *text, void *opaque)
395
446
  static void
396
447
  rndr_raw_block(struct buf *ob, const struct buf *text, void *opaque)
397
448
  {
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);
449
+ size_t org, size;
450
+ struct html_renderopt *options = opaque;
451
+
452
+ if (!text)
453
+ return;
454
+
455
+ size = text->size;
456
+ while (size > 0 && text->data[size - 1] == '\n')
457
+ size--;
458
+
459
+ for (org = 0; org < size && text->data[org] == '\n'; ++org)
460
+
461
+ if (org >= size)
462
+ return;
463
+
464
+ /* Remove style tags if the `:no_styles` option is enabled */
465
+ if ((options->flags & HTML_SKIP_STYLE) != 0 &&
466
+ sdhtml_is_tag(text->data, size, "style"))
467
+ return;
468
+
469
+ if (ob->size)
470
+ bufputc(ob, '\n');
471
+
472
+ bufput(ob, text->data + org, size - org);
407
473
  bufputc(ob, '\n');
408
474
  }
409
475
 
@@ -429,10 +495,15 @@ static int
429
495
  rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque)
430
496
  {
431
497
  struct html_renderopt *options = opaque;
432
- if (!link || !link->size) return 0;
498
+
499
+ if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size))
500
+ return 0;
433
501
 
434
502
  BUFPUTSL(ob, "<img src=\"");
435
- escape_href(ob, link->data, link->size);
503
+
504
+ if (link && link->size)
505
+ escape_href(ob, link->data, link->size);
506
+
436
507
  BUFPUTSL(ob, "\" alt=\"");
437
508
 
438
509
  if (alt && alt->size)
@@ -440,7 +511,8 @@ rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, cons
440
511
 
441
512
  if (title && title->size) {
442
513
  BUFPUTSL(ob, "\" title=\"");
443
- escape_html(ob, title->data, title->size); }
514
+ escape_html(ob, title->data, title->size);
515
+ }
444
516
 
445
517
  bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
446
518
  return 1;
@@ -452,7 +524,7 @@ rndr_raw_html(struct buf *ob, const struct buf *text, void *opaque)
452
524
  struct html_renderopt *options = opaque;
453
525
 
454
526
  /* 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. */
527
+ It doesn't see if there are any valid tags, just escape all of them. */
456
528
  if((options->flags & HTML_ESCAPE) != 0) {
457
529
  escape_html(ob, text->data, text->size);
458
530
  return 1;
@@ -591,7 +663,7 @@ rndr_footnote_def(struct buf *ob, const struct buf *text, unsigned int num, void
591
663
  bufprintf(ob, "\n<li id=\"fn%d\">\n", num);
592
664
  if (pfound) {
593
665
  bufput(ob, text->data, i);
594
- bufprintf(ob, "&nbsp;<a href=\"#fnref%d\" rev=\"footnote\">&#8617;</a>", num);
666
+ bufprintf(ob, "&nbsp;<a href=\"#fnref%d\">&#8617;</a>", num);
595
667
  bufput(ob, text->data + i, text->size - i);
596
668
  } else if (text) {
597
669
  bufput(ob, text->data, text->size);
@@ -602,7 +674,7 @@ rndr_footnote_def(struct buf *ob, const struct buf *text, unsigned int num, void
602
674
  static int
603
675
  rndr_footnote_ref(struct buf *ob, unsigned int num, void *opaque)
604
676
  {
605
- bufprintf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\" rel=\"footnote\">%d</a></sup>", num, num, num);
677
+ bufprintf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\">%d</a></sup>", num, num, num);
606
678
  return 1;
607
679
  }
608
680
 
@@ -611,7 +683,8 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
611
683
  {
612
684
  struct html_renderopt *options = opaque;
613
685
 
614
- if (level <= options->toc_data.nesting_level) {
686
+ if (level >= options->toc_data.nesting_bounds[0] &&
687
+ level <= options->toc_data.nesting_bounds[1]) {
615
688
  /* set the level offset if this is the first header
616
689
  * we're parsing for the document */
617
690
  if (options->toc_data.current_level == 0)
@@ -635,8 +708,17 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
635
708
  BUFPUTSL(ob,"</li>\n<li>\n");
636
709
  }
637
710
 
638
- bufprintf(ob, "<a href=\"#%s\">", header_anchor(text));
639
- if (text) escape_html(ob, text->data, text->size);
711
+ bufprintf(ob, "<a href=\"#");
712
+ rndr_header_anchor(ob, text);
713
+ BUFPUTSL(ob, "\">");
714
+
715
+ if (text) {
716
+ if (options->flags & HTML_ESCAPE)
717
+ escape_html(ob, text->data, text->size);
718
+ else
719
+ bufput(ob, text->data, text->size);
720
+ }
721
+
640
722
  BUFPUTSL(ob, "</a>\n");
641
723
  }
642
724
  }
@@ -661,7 +743,7 @@ toc_finalize(struct buf *ob, void *opaque)
661
743
  }
662
744
 
663
745
  void
664
- sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, int nesting_level)
746
+ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, unsigned int render_flags)
665
747
  {
666
748
  static const struct sd_callbacks cb_default = {
667
749
  NULL,
@@ -702,8 +784,7 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *optio
702
784
  };
703
785
 
704
786
  memset(options, 0x0, sizeof(struct html_renderopt));
705
- options->flags = HTML_TOC;
706
- options->toc_data.nesting_level = nesting_level;
787
+ options->flags = render_flags;
707
788
 
708
789
  memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
709
790
  }
@@ -752,7 +833,8 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options,
752
833
  /* Prepare the options pointer */
753
834
  memset(options, 0x0, sizeof(struct html_renderopt));
754
835
  options->flags = render_flags;
755
- options->toc_data.nesting_level = 99;
836
+ options->toc_data.nesting_bounds[0] = 1;
837
+ options->toc_data.nesting_bounds[1] = 6;
756
838
 
757
839
  /* Prepare the callbacks */
758
840
  memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));