redcarpet 3.3.4 → 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.
- checksums.yaml +5 -5
- data/Gemfile +2 -2
- data/README.markdown +45 -34
- data/ext/redcarpet/autolink.c +7 -1
- data/ext/redcarpet/buffer.h +0 -1
- data/ext/redcarpet/houdini_href_e.c +5 -11
- data/ext/redcarpet/houdini_html_e.c +0 -1
- data/ext/redcarpet/html.c +34 -7
- data/ext/redcarpet/html.h +1 -2
- data/ext/redcarpet/html_blocks.h +68 -70
- data/ext/redcarpet/html_smartypants.c +20 -5
- data/ext/redcarpet/markdown.c +5 -7
- data/ext/redcarpet/rc_markdown.c +17 -2
- data/ext/redcarpet/rc_render.c +28 -5
- data/lib/redcarpet/cli.rb +1 -1
- data/lib/redcarpet/compat.rb +0 -2
- data/lib/redcarpet/render_strip.rb +1 -1
- data/lib/redcarpet.rb +1 -1
- data/redcarpet.gemspec +5 -4
- data/test/custom_render_test.rb +40 -1
- data/test/html5_test.rb +51 -38
- data/test/html_render_test.rb +86 -60
- data/test/html_toc_render_test.rb +41 -4
- data/test/markdown_test.rb +226 -181
- data/test/redcarpet_bin_test.rb +2 -2
- data/test/smarty_html_test.rb +11 -5
- data/test/smarty_pants_test.rb +5 -0
- data/test/stripdown_render_test.rb +14 -6
- data/test/test_helper.rb +9 -1
- metadata +24 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3e6ea78031a1e40620168cd57fcbfae06bec5bafabc8f6e600adc552a4fe5b40
|
4
|
+
data.tar.gz: 658dd33e836daa11effa88e0491d09387963ea349751efd278e9fbdac7026066
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b17b0208c25d4e8566fb4a154d0f66e778b702abcf58d1d1227fa2510be421c7496e20fd6402066adba3485778e935b46aff73fd412802eedb89e44470a7ad94
|
7
|
+
data.tar.gz: 1e1c8dd559979b8bd5f4de2d20e1127b2a964c03a267133c3d9a3703f71bce44a2f4dc2efdb0dc0cc331e0ab779bfad23e9b62af0ffc4ee9078896376bd86865
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -3,6 +3,7 @@ Redcarpet is written with sugar, spice and everything nice
|
|
3
3
|
|
4
4
|
[](https://travis-ci.org/vmg/redcarpet)
|
5
5
|
[](https://www.versioneye.com/ruby/redcarpet)
|
6
|
+
[](https://www.codetriage.com/vmg/redcarpet)
|
6
7
|
|
7
8
|
Redcarpet is a Ruby library for Markdown processing that smells like
|
8
9
|
butterflies and popcorn.
|
@@ -25,7 +26,7 @@ Starting with Redcarpet 3.0, the minimum required Ruby version is 1.9.2 (or Rubi
|
|
25
26
|
|
26
27
|
$ [sudo] gem install redcarpet
|
27
28
|
|
28
|
-
If you need to use it with Ruby 1.8.7, you will
|
29
|
+
If you need to use it with Ruby 1.8.7, you will have to stick with 2.3.0:
|
29
30
|
|
30
31
|
$ [sudo] gem install redcarpet -v 2.3.0
|
31
32
|
|
@@ -45,10 +46,10 @@ output.
|
|
45
46
|
The `Redcarpet::Markdown` object is encouraged to be instantiated once with the
|
46
47
|
required settings, and reused between parses.
|
47
48
|
|
48
|
-
|
49
|
+
~~~~ ruby
|
49
50
|
# Initializes a Markdown parser
|
50
51
|
markdown = Redcarpet::Markdown.new(renderer, extensions = {})
|
51
|
-
|
52
|
+
~~~~
|
52
53
|
|
53
54
|
Here, the `renderer` variable refers to a renderer object, inheriting
|
54
55
|
from `Redcarpet::Render::Base`. If the given object has not been
|
@@ -59,10 +60,10 @@ Unlike in the RedCloth API, the text to render is passed as an argument
|
|
59
60
|
and not stored inside the `Markdown` instance, to encourage reusability.
|
60
61
|
Example:
|
61
62
|
|
62
|
-
|
63
|
+
~~~~ ruby
|
63
64
|
markdown.render("This is *bongos*, indeed.")
|
64
65
|
# => "<p>This is <em>bongos</em>, indeed.</p>"
|
65
|
-
|
66
|
+
~~~~
|
66
67
|
|
67
68
|
You can also specify a hash containing the Markdown extensions which the
|
68
69
|
parser will identify. The following extensions are accepted:
|
@@ -119,9 +120,9 @@ within the document (e.g. `[^1]: This is a footnote.`).
|
|
119
120
|
|
120
121
|
Example:
|
121
122
|
|
122
|
-
|
123
|
+
~~~~ ruby
|
123
124
|
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: true, tables: true)
|
124
|
-
|
125
|
+
~~~~
|
125
126
|
|
126
127
|
Darling, I packed you a couple renderers for lunch
|
127
128
|
--------------------------------------------------
|
@@ -136,9 +137,9 @@ All the rendering flags that previously applied only to HTML output have
|
|
136
137
|
now been moved to the `Redcarpet::Render::HTML` class, and may be enabled when
|
137
138
|
instantiating the renderer:
|
138
139
|
|
139
|
-
|
140
|
+
~~~~ ruby
|
140
141
|
Redcarpet::Render::HTML.new(render_options = {})
|
141
|
-
|
142
|
+
~~~~
|
142
143
|
|
143
144
|
Initializes an HTML renderer. The following flags are available:
|
144
145
|
|
@@ -172,9 +173,9 @@ Markdown document had newlines (by default, Markdown ignores these newlines).
|
|
172
173
|
|
173
174
|
Example:
|
174
175
|
|
175
|
-
|
176
|
+
~~~~ ruby
|
176
177
|
renderer = Redcarpet::Render::HTML.new(no_links: true, hard_wrap: true)
|
177
|
-
|
178
|
+
~~~~
|
178
179
|
|
179
180
|
|
180
181
|
The `HTML` renderer has an alternate version, `Redcarpet::Render::HTML_TOC`,
|
@@ -182,12 +183,21 @@ which will output a table of contents in HTML based on the headers of the
|
|
182
183
|
Markdown document.
|
183
184
|
|
184
185
|
When instantiating this render object, you can optionally pass a `nesting_level`
|
185
|
-
option which takes an integer and allows you to make it render only
|
186
|
-
|
186
|
+
option which takes an integer or a range and allows you to make it render only
|
187
|
+
headers at certain levels.
|
187
188
|
|
188
|
-
|
189
|
-
|
190
|
-
|
189
|
+
Redcarpet also includes a plaintext renderer, `Redcarpet::Render::StripDown`, that
|
190
|
+
strips out all the formatting:
|
191
|
+
|
192
|
+
~~~~ ruby
|
193
|
+
require 'redcarpet'
|
194
|
+
require 'redcarpet/render_strip'
|
195
|
+
|
196
|
+
markdown = Redcarpet::Markdown.new(Redcarpet::Render::StripDown)
|
197
|
+
|
198
|
+
markdown.render("**This** _is_ an [example](http://example.org/).")
|
199
|
+
# => "This is an example (http://example.org/)."
|
200
|
+
~~~~
|
191
201
|
|
192
202
|
|
193
203
|
And you can even cook your own
|
@@ -196,25 +206,26 @@ And you can even cook your own
|
|
196
206
|
Custom renderers are created by inheriting from an existing renderer. The
|
197
207
|
built-in renderers, `HTML` and `XHTML` may be extended as such:
|
198
208
|
|
199
|
-
|
200
|
-
#
|
201
|
-
class
|
202
|
-
def
|
203
|
-
|
209
|
+
~~~~ ruby
|
210
|
+
# Create a custom renderer that sets a custom class for block-quotes.
|
211
|
+
class CustomRender < Redcarpet::Render::HTML
|
212
|
+
def block_quote(quote)
|
213
|
+
%(<blockquote class="my-custom-class">#{quote}</blockquote>)
|
204
214
|
end
|
205
215
|
end
|
206
216
|
|
207
|
-
markdown = Redcarpet::Markdown.new(
|
208
|
-
|
217
|
+
markdown = Redcarpet::Markdown.new(CustomRender, fenced_code_blocks: true)
|
218
|
+
~~~~
|
209
219
|
|
210
|
-
But new renderers can also be created from scratch
|
211
|
-
|
220
|
+
But new renderers can also be created from scratch by extending the abstract
|
221
|
+
base class `Redcarpet::Render::Base` (see `lib/redcarpet/render_man.rb` for
|
222
|
+
an example implementation of a Manpage renderer):
|
212
223
|
|
213
|
-
|
224
|
+
~~~~ ruby
|
214
225
|
class ManPage < Redcarpet::Render::Base
|
215
226
|
# you get the drill -- keep going from here
|
216
227
|
end
|
217
|
-
|
228
|
+
~~~~
|
218
229
|
|
219
230
|
The following instance methods may be implemented by the renderer:
|
220
231
|
|
@@ -302,7 +313,7 @@ or after the rendering process begins:
|
|
302
313
|
* postprocess(full_document)
|
303
314
|
|
304
315
|
You can look at
|
305
|
-
["How to extend the Redcarpet 2 Markdown library?"](http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html)
|
316
|
+
["How to extend the Redcarpet 2 Markdown library?"](https://web.archive.org/web/20170505231254/http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html)
|
306
317
|
for some more explanations.
|
307
318
|
|
308
319
|
Also, now our Pants are much smarter
|
@@ -327,7 +338,7 @@ end
|
|
327
338
|
|
328
339
|
# Standalone
|
329
340
|
Redcarpet::Render::SmartyPants.render("<p>Oh SmartyPants, you're so crazy...</p>")
|
330
|
-
|
341
|
+
~~~~
|
331
342
|
|
332
343
|
SmartyPants works on top of already-rendered HTML, and will ignore replacements
|
333
344
|
inside the content of HTML tags and inside specific HTML blocks such as
|
@@ -352,16 +363,16 @@ renderer-independent, the results will be completely unreliable!
|
|
352
363
|
Still, if major forces (let's say, tornadoes or other natural disasters) force you
|
353
364
|
to keep a Markdown-compatibility layer, Redcarpet also supports this:
|
354
365
|
|
355
|
-
|
366
|
+
~~~~ ruby
|
356
367
|
require 'redcarpet/compat'
|
357
|
-
|
368
|
+
~~~~
|
358
369
|
|
359
370
|
Requiring the compatibility library will declare a `Markdown` class with the
|
360
371
|
classical RedCloth API, e.g.
|
361
372
|
|
362
|
-
|
373
|
+
~~~~ ruby
|
363
374
|
Markdown.new('this is my text').to_html
|
364
|
-
|
375
|
+
~~~~
|
365
376
|
|
366
377
|
This class renders 100% standards compliant Markdown with 0 extensions. Nada.
|
367
378
|
Don't even try to enable extensions with a compatibility layer, because
|
@@ -373,7 +384,7 @@ monkeypatches the Markdown class, you're a terrible human being. Just saying.
|
|
373
384
|
Boring legal stuff
|
374
385
|
------------------
|
375
386
|
|
376
|
-
Copyright (c) 2011-
|
387
|
+
Copyright (c) 2011-2016, Vicent Martí
|
377
388
|
|
378
389
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
379
390
|
of this software and associated documentation files (the "Software"), to deal
|
data/ext/redcarpet/autolink.c
CHANGED
@@ -294,9 +294,15 @@ sd_autolink__url(
|
|
294
294
|
if (link_end == 0)
|
295
295
|
return 0;
|
296
296
|
|
297
|
+
/**
|
298
|
+
* In certain cases, we may refer to a link at the end of a
|
299
|
+
* sentence so the period should not be part of the URL.
|
300
|
+
*/
|
301
|
+
if (data[link_end - 1] == '.')
|
302
|
+
link_end--;
|
303
|
+
|
297
304
|
bufput(link, data - rewind, link_end + rewind);
|
298
305
|
*rewind_p = rewind;
|
299
306
|
|
300
307
|
return link_end;
|
301
308
|
}
|
302
|
-
|
data/ext/redcarpet/buffer.h
CHANGED
@@ -44,10 +44,10 @@
|
|
44
44
|
* have its native function (i.e. as an URL
|
45
45
|
* component/separator) and hence needs no escaping.
|
46
46
|
*
|
47
|
-
* There
|
48
|
-
*
|
49
|
-
*
|
50
|
-
*
|
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
|
51
51
|
* to generate valid HTML markup.
|
52
52
|
*
|
53
53
|
* All other characters will be escaped to %XX.
|
@@ -56,7 +56,7 @@
|
|
56
56
|
static const char HREF_SAFE[] = {
|
57
57
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
58
58
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
59
|
-
0, 1, 0, 1, 1, 1,
|
59
|
+
0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
60
60
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
|
61
61
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
62
62
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
|
@@ -95,12 +95,6 @@ houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size)
|
|
95
95
|
break;
|
96
96
|
|
97
97
|
switch (src[i]) {
|
98
|
-
/* amp appears all the time in URLs, but needs
|
99
|
-
* HTML-entity escaping to be inside an href */
|
100
|
-
case '&':
|
101
|
-
BUFPUTSL(ob, "&");
|
102
|
-
break;
|
103
|
-
|
104
98
|
/* the single quote is a valid URL character
|
105
99
|
* according to the standard; it needs HTML
|
106
100
|
* entity escaping too */
|
data/ext/redcarpet/html.c
CHANGED
@@ -255,8 +255,15 @@ rndr_quote(struct buf *ob, const struct buf *text, void *opaque)
|
|
255
255
|
if (!text || !text->size)
|
256
256
|
return 0;
|
257
257
|
|
258
|
+
struct html_renderopt *options = opaque;
|
259
|
+
|
258
260
|
BUFPUTSL(ob, "<q>");
|
259
|
-
|
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
|
+
|
260
267
|
BUFPUTSL(ob, "</q>");
|
261
268
|
|
262
269
|
return 1;
|
@@ -281,13 +288,20 @@ rndr_header_anchor(struct buf *out, const struct buf *anchor)
|
|
281
288
|
int stripped = 0, inserted = 0;
|
282
289
|
|
283
290
|
for (; i < size; ++i) {
|
291
|
+
// skip html tags
|
284
292
|
if (a[i] == '<') {
|
285
293
|
while (i < size && a[i] != '>')
|
286
294
|
i++;
|
295
|
+
// skip html entities
|
296
|
+
} else if (a[i] == '&') {
|
297
|
+
while (i < size && a[i] != ';')
|
298
|
+
i++;
|
287
299
|
}
|
300
|
+
// replace non-ascii or invalid characters with dashes
|
288
301
|
else if (!isascii(a[i]) || strchr(STRIPPED, a[i])) {
|
289
302
|
if (inserted && !stripped)
|
290
303
|
bufputc(out, '-');
|
304
|
+
// and do it only once
|
291
305
|
stripped = 1;
|
292
306
|
}
|
293
307
|
else {
|
@@ -297,8 +311,18 @@ rndr_header_anchor(struct buf *out, const struct buf *anchor)
|
|
297
311
|
}
|
298
312
|
}
|
299
313
|
|
300
|
-
if
|
314
|
+
// replace the last dash if there was anything added
|
315
|
+
if (stripped && inserted)
|
301
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
|
+
}
|
302
326
|
}
|
303
327
|
|
304
328
|
static void
|
@@ -309,7 +333,8 @@ rndr_header(struct buf *ob, const struct buf *text, int level, void *opaque)
|
|
309
333
|
if (ob->size)
|
310
334
|
bufputc(ob, '\n');
|
311
335
|
|
312
|
-
if ((options->flags & HTML_TOC) &&
|
336
|
+
if ((options->flags & HTML_TOC) && level >= options->toc_data.nesting_bounds[0] &&
|
337
|
+
level <= options->toc_data.nesting_bounds[1]) {
|
313
338
|
bufprintf(ob, "<h%d id=\"", level);
|
314
339
|
rndr_header_anchor(ob, text);
|
315
340
|
BUFPUTSL(ob, "\">");
|
@@ -638,7 +663,7 @@ rndr_footnote_def(struct buf *ob, const struct buf *text, unsigned int num, void
|
|
638
663
|
bufprintf(ob, "\n<li id=\"fn%d\">\n", num);
|
639
664
|
if (pfound) {
|
640
665
|
bufput(ob, text->data, i);
|
641
|
-
bufprintf(ob, " <a href=\"#fnref%d\"
|
666
|
+
bufprintf(ob, " <a href=\"#fnref%d\">↩</a>", num);
|
642
667
|
bufput(ob, text->data + i, text->size - i);
|
643
668
|
} else if (text) {
|
644
669
|
bufput(ob, text->data, text->size);
|
@@ -649,7 +674,7 @@ rndr_footnote_def(struct buf *ob, const struct buf *text, unsigned int num, void
|
|
649
674
|
static int
|
650
675
|
rndr_footnote_ref(struct buf *ob, unsigned int num, void *opaque)
|
651
676
|
{
|
652
|
-
bufprintf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\"
|
677
|
+
bufprintf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\">%d</a></sup>", num, num, num);
|
653
678
|
return 1;
|
654
679
|
}
|
655
680
|
|
@@ -658,7 +683,8 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
|
|
658
683
|
{
|
659
684
|
struct html_renderopt *options = opaque;
|
660
685
|
|
661
|
-
if (level
|
686
|
+
if (level >= options->toc_data.nesting_bounds[0] &&
|
687
|
+
level <= options->toc_data.nesting_bounds[1]) {
|
662
688
|
/* set the level offset if this is the first header
|
663
689
|
* we're parsing for the document */
|
664
690
|
if (options->toc_data.current_level == 0)
|
@@ -807,7 +833,8 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options,
|
|
807
833
|
/* Prepare the options pointer */
|
808
834
|
memset(options, 0x0, sizeof(struct html_renderopt));
|
809
835
|
options->flags = render_flags;
|
810
|
-
options->toc_data.
|
836
|
+
options->toc_data.nesting_bounds[0] = 1;
|
837
|
+
options->toc_data.nesting_bounds[1] = 6;
|
811
838
|
|
812
839
|
/* Prepare the callbacks */
|
813
840
|
memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
|
data/ext/redcarpet/html.h
CHANGED
@@ -35,7 +35,7 @@ struct html_renderopt {
|
|
35
35
|
struct {
|
36
36
|
int current_level;
|
37
37
|
int level_offset;
|
38
|
-
int
|
38
|
+
int nesting_bounds[2];
|
39
39
|
} toc_data;
|
40
40
|
|
41
41
|
unsigned int flags;
|
@@ -81,4 +81,3 @@ sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size);
|
|
81
81
|
#endif
|
82
82
|
|
83
83
|
#endif
|
84
|
-
|
data/ext/redcarpet/html_blocks.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
/* C code produced by gperf version 3.0.
|
1
|
+
/* C code produced by gperf version 3.0.3 */
|
2
2
|
/* Command-line: gperf -N find_block_tag -H hash_block_tag -C -c -E --ignore-case html_block_names.txt */
|
3
|
-
/* See
|
3
|
+
/* See https://git.io/vPLqa for the list of recognized elements */
|
4
4
|
/* Computed positions: -k'1-2' */
|
5
5
|
|
6
6
|
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
@@ -30,7 +30,7 @@
|
|
30
30
|
error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
|
31
31
|
#endif
|
32
32
|
|
33
|
-
/* maximum key range =
|
33
|
+
/* maximum key range = 72, duplicates = 0 */
|
34
34
|
|
35
35
|
#ifndef GPERF_DOWNCASE
|
36
36
|
#define GPERF_DOWNCASE 1
|
@@ -94,34 +94,34 @@ hash_block_tag (str, len)
|
|
94
94
|
{
|
95
95
|
static const unsigned char asso_values[] =
|
96
96
|
{
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
0,
|
105
|
-
0,
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
97
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
98
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
99
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
100
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
101
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
102
|
+
26, 60, 55, 45, 40, 35, 73, 73, 73, 73,
|
103
|
+
73, 73, 73, 73, 73, 20, 15, 15, 0, 35,
|
104
|
+
0, 25, 10, 10, 5, 73, 73, 0, 15, 15,
|
105
|
+
0, 73, 73, 15, 20, 10, 10, 73, 73, 73,
|
106
|
+
73, 73, 73, 73, 73, 73, 73, 20, 15, 15,
|
107
|
+
0, 35, 0, 25, 10, 10, 5, 73, 73, 0,
|
108
|
+
15, 15, 0, 73, 73, 15, 20, 10, 10, 73,
|
109
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
110
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
111
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
112
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
113
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
114
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
115
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
116
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
117
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
118
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
119
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
120
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
121
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
122
|
+
73, 73, 73, 73, 73, 73, 73
|
123
123
|
};
|
124
|
-
register int hval = len;
|
124
|
+
register unsigned int hval = len;
|
125
125
|
|
126
126
|
switch (hval)
|
127
127
|
{
|
@@ -135,12 +135,6 @@ hash_block_tag (str, len)
|
|
135
135
|
return hval;
|
136
136
|
}
|
137
137
|
|
138
|
-
#ifdef __GNUC__
|
139
|
-
__inline
|
140
|
-
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
|
141
|
-
__attribute__ ((__gnu_inline__))
|
142
|
-
#endif
|
143
|
-
#endif
|
144
138
|
const char *
|
145
139
|
find_block_tag (str, len)
|
146
140
|
register const char *str;
|
@@ -148,76 +142,80 @@ find_block_tag (str, len)
|
|
148
142
|
{
|
149
143
|
enum
|
150
144
|
{
|
151
|
-
TOTAL_KEYWORDS =
|
145
|
+
TOTAL_KEYWORDS = 43,
|
152
146
|
MIN_WORD_LENGTH = 1,
|
153
147
|
MAX_WORD_LENGTH = 10,
|
154
148
|
MIN_HASH_VALUE = 1,
|
155
|
-
MAX_HASH_VALUE =
|
149
|
+
MAX_HASH_VALUE = 72
|
156
150
|
};
|
157
151
|
|
158
152
|
static const char * const wordlist[] =
|
159
153
|
{
|
160
154
|
"",
|
161
155
|
"p",
|
162
|
-
"
|
163
|
-
"
|
156
|
+
"dl",
|
157
|
+
"del",
|
164
158
|
"form",
|
165
|
-
"
|
159
|
+
"",
|
166
160
|
"footer",
|
167
|
-
"
|
168
|
-
"",
|
161
|
+
"details",
|
162
|
+
"div",
|
163
|
+
"", "",
|
169
164
|
"figure",
|
170
|
-
"
|
165
|
+
"ul",
|
171
166
|
"fieldset",
|
172
|
-
"
|
167
|
+
"",
|
173
168
|
"figcaption",
|
174
169
|
"header",
|
175
|
-
"
|
176
|
-
"
|
177
|
-
"",
|
178
|
-
"
|
170
|
+
"ol",
|
171
|
+
"pre",
|
172
|
+
"math",
|
173
|
+
"video",
|
179
174
|
"script",
|
180
|
-
"
|
181
|
-
"
|
175
|
+
"section",
|
176
|
+
"noscript",
|
182
177
|
"",
|
183
|
-
"
|
178
|
+
"blockquote",
|
184
179
|
"hgroup",
|
185
|
-
"
|
186
|
-
"
|
187
|
-
"",
|
180
|
+
"hr",
|
181
|
+
"ins",
|
182
|
+
"",
|
183
|
+
"style",
|
184
|
+
"output",
|
185
|
+
"summary",
|
186
|
+
"nav",
|
187
|
+
"",
|
188
|
+
"audio",
|
188
189
|
"canvas",
|
189
190
|
"dd",
|
190
|
-
"
|
191
|
+
"h1",
|
191
192
|
"abbr",
|
192
|
-
"audio",
|
193
|
-
"iframe",
|
194
|
-
"address",
|
195
|
-
"ins",
|
196
|
-
"",
|
197
193
|
"table",
|
198
|
-
"",
|
199
|
-
"
|
194
|
+
"iframe",
|
195
|
+
"article",
|
200
196
|
"", "",
|
201
197
|
"aside",
|
202
|
-
"
|
203
|
-
"
|
198
|
+
"",
|
199
|
+
"h6",
|
204
200
|
"", "",
|
205
201
|
"tfoot",
|
206
202
|
"",
|
203
|
+
"h5",
|
204
|
+
"", "", "", "",
|
207
205
|
"h4",
|
208
206
|
"", "", "", "",
|
209
|
-
"
|
207
|
+
"address",
|
210
208
|
"", "", "", "",
|
211
|
-
"
|
209
|
+
"h3",
|
212
210
|
"", "", "", "",
|
213
|
-
"
|
211
|
+
"h2"
|
214
212
|
};
|
215
213
|
|
216
214
|
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
217
215
|
{
|
218
|
-
|
216
|
+
unsigned int key = hash_block_tag (str, len);
|
219
217
|
|
220
|
-
if (key <= MAX_HASH_VALUE
|
218
|
+
if (key <= MAX_HASH_VALUE)
|
221
219
|
{
|
222
220
|
register const char *s = wordlist[key];
|
223
221
|
|
@@ -151,6 +151,9 @@ smartypants_squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previo
|
|
151
151
|
return next_squote_len;
|
152
152
|
}
|
153
153
|
|
154
|
+
if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
|
155
|
+
return 0;
|
156
|
+
|
154
157
|
// trailing single quotes: students', tryin'
|
155
158
|
if (word_boundary(t1)) {
|
156
159
|
BUFPUTSL(ob, "’");
|
@@ -178,9 +181,6 @@ smartypants_squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previo
|
|
178
181
|
}
|
179
182
|
}
|
180
183
|
|
181
|
-
if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
|
182
|
-
return 0;
|
183
|
-
|
184
184
|
bufput(ob, squote_text, squote_size);
|
185
185
|
return 0;
|
186
186
|
}
|
@@ -341,6 +341,7 @@ smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t prev
|
|
341
341
|
};
|
342
342
|
static const size_t skip_tags_count = 8;
|
343
343
|
|
344
|
+
size_t next_to_closing_a = 0;
|
344
345
|
size_t tag, i = 0;
|
345
346
|
|
346
347
|
while (i < size && text[i] != '>')
|
@@ -369,7 +370,23 @@ smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t prev
|
|
369
370
|
i++;
|
370
371
|
}
|
371
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
|
+
|
372
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("'", text+(i+1), 5) == 0) {
|
386
|
+
bufput(ob, "’", 7);
|
387
|
+
i += 5;
|
388
|
+
}
|
389
|
+
|
373
390
|
return i;
|
374
391
|
}
|
375
392
|
|
@@ -453,5 +470,3 @@ sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size)
|
|
453
470
|
}
|
454
471
|
}
|
455
472
|
}
|
456
|
-
|
457
|
-
|