line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include "html.h" |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
#include |
4
|
|
|
|
|
|
|
#include |
5
|
|
|
|
|
|
|
#include |
6
|
|
|
|
|
|
|
#include |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
#ifdef _MSC_VER |
9
|
|
|
|
|
|
|
#define snprintf _snprintf |
10
|
|
|
|
|
|
|
#endif |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
struct smartypants_data { |
13
|
|
|
|
|
|
|
int in_squote; |
14
|
|
|
|
|
|
|
int in_dquote; |
15
|
|
|
|
|
|
|
}; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
static size_t smartypants_cb__ltag(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
18
|
|
|
|
|
|
|
static size_t smartypants_cb__dquote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
19
|
|
|
|
|
|
|
static size_t smartypants_cb__amp(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
20
|
|
|
|
|
|
|
static size_t smartypants_cb__period(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
21
|
|
|
|
|
|
|
static size_t smartypants_cb__number(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
22
|
|
|
|
|
|
|
static size_t smartypants_cb__dash(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
23
|
|
|
|
|
|
|
static size_t smartypants_cb__parens(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
24
|
|
|
|
|
|
|
static size_t smartypants_cb__squote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
25
|
|
|
|
|
|
|
static size_t smartypants_cb__backtick(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
26
|
|
|
|
|
|
|
static size_t smartypants_cb__escape(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
static size_t (*smartypants_cb_ptrs[]) |
29
|
|
|
|
|
|
|
(hoedown_buffer *, struct smartypants_data *, uint8_t, const uint8_t *, size_t) = |
30
|
|
|
|
|
|
|
{ |
31
|
|
|
|
|
|
|
NULL, /* 0 */ |
32
|
|
|
|
|
|
|
smartypants_cb__dash, /* 1 */ |
33
|
|
|
|
|
|
|
smartypants_cb__parens, /* 2 */ |
34
|
|
|
|
|
|
|
smartypants_cb__squote, /* 3 */ |
35
|
|
|
|
|
|
|
smartypants_cb__dquote, /* 4 */ |
36
|
|
|
|
|
|
|
smartypants_cb__amp, /* 5 */ |
37
|
|
|
|
|
|
|
smartypants_cb__period, /* 6 */ |
38
|
|
|
|
|
|
|
smartypants_cb__number, /* 7 */ |
39
|
|
|
|
|
|
|
smartypants_cb__ltag, /* 8 */ |
40
|
|
|
|
|
|
|
smartypants_cb__backtick, /* 9 */ |
41
|
|
|
|
|
|
|
smartypants_cb__escape, /* 10 */ |
42
|
|
|
|
|
|
|
}; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
static const uint8_t smartypants_cb_chars[UINT8_MAX+1] = { |
45
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
46
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
47
|
|
|
|
|
|
|
0, 0, 4, 0, 0, 0, 5, 3, 2, 0, 0, 0, 0, 1, 6, 0, |
48
|
|
|
|
|
|
|
0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, |
49
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
50
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, |
51
|
|
|
|
|
|
|
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
52
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
53
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
54
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
55
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
56
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
57
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
58
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
59
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
60
|
|
|
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
61
|
|
|
|
|
|
|
}; |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
static int |
64
|
0
|
|
|
|
|
|
word_boundary(uint8_t c) |
65
|
|
|
|
|
|
|
{ |
66
|
0
|
0
|
|
|
|
|
return c == 0 || isspace(c) || ispunct(c); |
|
|
0
|
|
|
|
|
|
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
/* |
70
|
|
|
|
|
|
|
If 'text' begins with any kind of single quote (e.g. "'" or "'" etc.), |
71
|
|
|
|
|
|
|
returns the length of the sequence of characters that makes up the single- |
72
|
|
|
|
|
|
|
quote. Otherwise, returns zero. |
73
|
|
|
|
|
|
|
*/ |
74
|
|
|
|
|
|
|
static size_t |
75
|
0
|
|
|
|
|
|
squote_len(const uint8_t *text, size_t size) |
76
|
|
|
|
|
|
|
{ |
77
|
|
|
|
|
|
|
static char* single_quote_list[] = { "'", "'", "'", "'", NULL }; |
78
|
|
|
|
|
|
|
char** p; |
79
|
|
|
|
|
|
|
|
80
|
0
|
0
|
|
|
|
|
for (p = single_quote_list; *p; ++p) { |
81
|
0
|
|
|
|
|
|
size_t len = strlen(*p); |
82
|
0
|
0
|
|
|
|
|
if (size >= len && memcmp(text, *p, len) == 0) { |
|
|
0
|
|
|
|
|
|
83
|
|
|
|
|
|
|
return len; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
return 0; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
/* Converts " or ' at very beginning or end of a word to left or right quote */ |
91
|
|
|
|
|
|
|
static int |
92
|
0
|
|
|
|
|
|
smartypants_quotes(hoedown_buffer *ob, uint8_t previous_char, uint8_t next_char, uint8_t quote, int *is_open) |
93
|
|
|
|
|
|
|
{ |
94
|
|
|
|
|
|
|
char ent[8]; |
95
|
|
|
|
|
|
|
|
96
|
0
|
0
|
|
|
|
|
if (*is_open && !word_boundary(next_char)) |
|
|
0
|
|
|
|
|
|
97
|
|
|
|
|
|
|
return 0; |
98
|
|
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
|
if (!(*is_open) && !word_boundary(previous_char)) |
|
|
0
|
|
|
|
|
|
100
|
|
|
|
|
|
|
return 0; |
101
|
|
|
|
|
|
|
|
102
|
0
|
0
|
|
|
|
|
snprintf(ent, sizeof(ent), "&%c%cquo;", (*is_open) ? 'r' : 'l', quote); |
103
|
0
|
|
|
|
|
|
*is_open = !(*is_open); |
104
|
0
|
|
|
|
|
|
hoedown_buffer_puts(ob, ent); |
105
|
0
|
|
|
|
|
|
return 1; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
/* |
109
|
|
|
|
|
|
|
Converts ' to left or right single quote; but the initial ' might be in |
110
|
|
|
|
|
|
|
different forms, e.g. ' or ' or '. |
111
|
|
|
|
|
|
|
'squote_text' points to the original single quote, and 'squote_size' is its length. |
112
|
|
|
|
|
|
|
'text' points at the last character of the single-quote, e.g. ' or ; |
113
|
|
|
|
|
|
|
*/ |
114
|
|
|
|
|
|
|
static size_t |
115
|
0
|
|
|
|
|
|
smartypants_squote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size, |
116
|
|
|
|
|
|
|
const uint8_t *squote_text, size_t squote_size) |
117
|
|
|
|
|
|
|
{ |
118
|
0
|
0
|
|
|
|
|
if (size >= 2) { |
119
|
0
|
|
|
|
|
|
uint8_t t1 = tolower(text[1]); |
120
|
0
|
|
|
|
|
|
size_t next_squote_len = squote_len(text+1, size-1); |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
/* convert '' to “ or ” */ |
123
|
0
|
0
|
|
|
|
|
if (next_squote_len > 0) { |
124
|
0
|
0
|
|
|
|
|
uint8_t next_char = (size > 1+next_squote_len) ? text[1+next_squote_len] : 0; |
125
|
0
|
0
|
|
|
|
|
if (smartypants_quotes(ob, previous_char, next_char, 'd', &smrt->in_dquote)) |
126
|
|
|
|
|
|
|
return next_squote_len; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
/* Tom's, isn't, I'm, I'd */ |
130
|
0
|
0
|
|
|
|
|
if ((t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') && |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
131
|
0
|
0
|
|
|
|
|
(size == 3 || word_boundary(text[2]))) { |
132
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "’"); |
133
|
0
|
|
|
|
|
|
return 0; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
/* you're, you'll, you've */ |
137
|
0
|
0
|
|
|
|
|
if (size >= 3) { |
138
|
0
|
|
|
|
|
|
uint8_t t2 = tolower(text[2]); |
139
|
|
|
|
|
|
|
|
140
|
0
|
0
|
|
|
|
|
if (((t1 == 'r' && t2 == 'e') || |
|
|
0
|
|
|
|
|
|
141
|
0
|
0
|
|
|
|
|
(t1 == 'l' && t2 == 'l') || |
142
|
0
|
0
|
|
|
|
|
(t1 == 'v' && t2 == 'e')) && |
143
|
0
|
0
|
|
|
|
|
(size == 4 || word_boundary(text[3]))) { |
144
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "’"); |
145
|
0
|
|
|
|
|
|
return 0; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
0
|
0
|
|
|
|
|
if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote)) |
|
|
0
|
|
|
|
|
|
151
|
|
|
|
|
|
|
return 0; |
152
|
|
|
|
|
|
|
|
153
|
0
|
|
|
|
|
|
hoedown_buffer_put(ob, squote_text, squote_size); |
154
|
0
|
|
|
|
|
|
return 0; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
/* Converts ' to left or right single quote. */ |
158
|
|
|
|
|
|
|
static size_t |
159
|
0
|
|
|
|
|
|
smartypants_cb__squote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
160
|
|
|
|
|
|
|
{ |
161
|
0
|
|
|
|
|
|
return smartypants_squote(ob, smrt, previous_char, text, size, text, 1); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
/* Converts (c), (r), (tm) */ |
165
|
|
|
|
|
|
|
static size_t |
166
|
0
|
|
|
|
|
|
smartypants_cb__parens(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
167
|
|
|
|
|
|
|
{ |
168
|
0
|
0
|
|
|
|
|
if (size >= 3) { |
169
|
0
|
|
|
|
|
|
uint8_t t1 = tolower(text[1]); |
170
|
0
|
|
|
|
|
|
uint8_t t2 = tolower(text[2]); |
171
|
|
|
|
|
|
|
|
172
|
0
|
0
|
|
|
|
|
if (t1 == 'c' && t2 == ')') { |
173
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "©"); |
174
|
0
|
|
|
|
|
|
return 2; |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
0
|
0
|
|
|
|
|
if (t1 == 'r' && t2 == ')') { |
178
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "®"); |
179
|
0
|
|
|
|
|
|
return 2; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
0
|
0
|
|
|
|
|
if (size >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
183
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "™"); |
184
|
0
|
|
|
|
|
|
return 3; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
0
|
|
|
|
|
|
hoedown_buffer_putc(ob, text[0]); |
189
|
0
|
|
|
|
|
|
return 0; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
/* Converts "--" to em-dash, etc. */ |
193
|
|
|
|
|
|
|
static size_t |
194
|
0
|
|
|
|
|
|
smartypants_cb__dash(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
195
|
|
|
|
|
|
|
{ |
196
|
0
|
0
|
|
|
|
|
if (size >= 3 && text[1] == '-' && text[2] == '-') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
197
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "—"); |
198
|
0
|
|
|
|
|
|
return 2; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
0
|
0
|
|
|
|
|
if (size >= 2 && text[1] == '-') { |
|
|
0
|
|
|
|
|
|
202
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "–"); |
203
|
0
|
|
|
|
|
|
return 1; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
0
|
|
|
|
|
|
hoedown_buffer_putc(ob, text[0]); |
207
|
0
|
|
|
|
|
|
return 0; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
/* Converts " etc. */ |
211
|
|
|
|
|
|
|
static size_t |
212
|
0
|
|
|
|
|
|
smartypants_cb__amp(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
213
|
|
|
|
|
|
|
{ |
214
|
|
|
|
|
|
|
size_t len; |
215
|
0
|
0
|
|
|
|
|
if (size >= 6 && memcmp(text, """, 6) == 0) { |
|
|
0
|
|
|
|
|
|
216
|
0
|
0
|
|
|
|
|
if (smartypants_quotes(ob, previous_char, size >= 7 ? text[6] : 0, 'd', &smrt->in_dquote)) |
|
|
0
|
|
|
|
|
|
217
|
|
|
|
|
|
|
return 5; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
0
|
|
|
|
|
|
len = squote_len(text, size); |
221
|
0
|
0
|
|
|
|
|
if (len > 0) { |
222
|
0
|
|
|
|
|
|
return (len-1) + smartypants_squote(ob, smrt, previous_char, text+(len-1), size-(len-1), text, len); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
0
|
0
|
|
|
|
|
if (size >= 4 && memcmp(text, "", 4) == 0) |
|
|
0
|
|
|
|
|
|
226
|
|
|
|
|
|
|
return 3; |
227
|
|
|
|
|
|
|
|
228
|
0
|
|
|
|
|
|
hoedown_buffer_putc(ob, '&'); |
229
|
0
|
|
|
|
|
|
return 0; |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
/* Converts "..." to ellipsis */ |
233
|
|
|
|
|
|
|
static size_t |
234
|
0
|
|
|
|
|
|
smartypants_cb__period(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
235
|
|
|
|
|
|
|
{ |
236
|
0
|
0
|
|
|
|
|
if (size >= 3 && text[1] == '.' && text[2] == '.') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
237
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "…"); |
238
|
0
|
|
|
|
|
|
return 2; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
0
|
0
|
|
|
|
|
if (size >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
242
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "…"); |
243
|
0
|
|
|
|
|
|
return 4; |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
|
246
|
0
|
|
|
|
|
|
hoedown_buffer_putc(ob, text[0]); |
247
|
0
|
|
|
|
|
|
return 0; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
/* Converts `` to opening double quote */ |
251
|
|
|
|
|
|
|
static size_t |
252
|
0
|
|
|
|
|
|
smartypants_cb__backtick(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
253
|
|
|
|
|
|
|
{ |
254
|
0
|
0
|
|
|
|
|
if (size >= 2 && text[1] == '`') { |
|
|
0
|
|
|
|
|
|
255
|
0
|
0
|
|
|
|
|
if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote)) |
|
|
0
|
|
|
|
|
|
256
|
|
|
|
|
|
|
return 1; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
0
|
|
|
|
|
|
hoedown_buffer_putc(ob, text[0]); |
260
|
0
|
|
|
|
|
|
return 0; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
/* Converts 1/2, 1/4, 3/4 */ |
264
|
|
|
|
|
|
|
static size_t |
265
|
0
|
|
|
|
|
|
smartypants_cb__number(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
266
|
|
|
|
|
|
|
{ |
267
|
0
|
0
|
|
|
|
|
if (word_boundary(previous_char) && size >= 3) { |
|
|
0
|
|
|
|
|
|
268
|
0
|
0
|
|
|
|
|
if (text[0] == '1' && text[1] == '/' && text[2] == '2') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
269
|
0
|
0
|
|
|
|
|
if (size == 3 || word_boundary(text[3])) { |
|
|
0
|
|
|
|
|
|
270
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "½"); |
271
|
0
|
|
|
|
|
|
return 2; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
0
|
0
|
|
|
|
|
if (text[0] == '1' && text[1] == '/' && text[2] == '4') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
276
|
0
|
0
|
|
|
|
|
if (size == 3 || word_boundary(text[3]) || |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
277
|
0
|
0
|
|
|
|
|
(size >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h')) { |
|
|
0
|
|
|
|
|
|
278
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "¼"); |
279
|
0
|
|
|
|
|
|
return 2; |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
0
|
0
|
|
|
|
|
if (text[0] == '3' && text[1] == '/' && text[2] == '4') { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
284
|
0
|
0
|
|
|
|
|
if (size == 3 || word_boundary(text[3]) || |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
285
|
0
|
0
|
|
|
|
|
(size >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's')) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
286
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, "¾"); |
287
|
0
|
|
|
|
|
|
return 2; |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
|
292
|
0
|
|
|
|
|
|
hoedown_buffer_putc(ob, text[0]); |
293
|
0
|
|
|
|
|
|
return 0; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
/* Converts " to left or right double quote */ |
297
|
|
|
|
|
|
|
static size_t |
298
|
0
|
|
|
|
|
|
smartypants_cb__dquote(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
299
|
|
|
|
|
|
|
{ |
300
|
0
|
0
|
|
|
|
|
if (!smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 'd', &smrt->in_dquote)) |
|
|
0
|
|
|
|
|
|
301
|
0
|
|
|
|
|
|
HOEDOWN_BUFPUTSL(ob, """); |
302
|
|
|
|
|
|
|
|
303
|
0
|
|
|
|
|
|
return 0; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
static size_t |
307
|
0
|
|
|
|
|
|
smartypants_cb__ltag(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
308
|
|
|
|
|
|
|
{ |
309
|
|
|
|
|
|
|
static const char *skip_tags[] = { |
310
|
|
|
|
|
|
|
"pre", "code", "var", "samp", "kbd", "math", "script", "style" |
311
|
|
|
|
|
|
|
}; |
312
|
|
|
|
|
|
|
static const size_t skip_tags_count = 8; |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
size_t tag, i = 0; |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
/* This is a comment. Copy everything verbatim until --> or EOF is seen. */ |
317
|
0
|
0
|
|
|
|
|
if (i + 4 < size && memcmp(text + i, "", 3) != 0) |
|
|
0
|
|
|
|
|
|
320
|
0
|
|
|
|
|
|
i++; |
321
|
|
|
|
|
|
|
i += 3; |
322
|
0
|
|
|
|
|
|
hoedown_buffer_put(ob, text, i + 1); |
323
|
0
|
|
|
|
|
|
return i; |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
0
|
0
|
|
|
|
|
while (i < size && text[i] != '>') |
|
|
0
|
|
|
|
|
|
327
|
0
|
|
|
|
|
|
i++; |
328
|
|
|
|
|
|
|
|
329
|
0
|
0
|
|
|
|
|
for (tag = 0; tag < skip_tags_count; ++tag) { |
330
|
0
|
0
|
|
|
|
|
if (hoedown_html_is_tag(text, size, skip_tags[tag]) == HOEDOWN_HTML_TAG_OPEN) |
331
|
|
|
|
|
|
|
break; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
0
|
0
|
|
|
|
|
if (tag < skip_tags_count) { |
335
|
|
|
|
|
|
|
for (;;) { |
336
|
0
|
0
|
|
|
|
|
while (i < size && text[i] != '<') |
|
|
0
|
|
|
|
|
|
337
|
0
|
|
|
|
|
|
i++; |
338
|
|
|
|
|
|
|
|
339
|
0
|
0
|
|
|
|
|
if (i == size) |
340
|
|
|
|
|
|
|
break; |
341
|
|
|
|
|
|
|
|
342
|
0
|
0
|
|
|
|
|
if (hoedown_html_is_tag(text + i, size - i, skip_tags[tag]) == HOEDOWN_HTML_TAG_CLOSE) |
343
|
|
|
|
|
|
|
break; |
344
|
|
|
|
|
|
|
|
345
|
0
|
|
|
|
|
|
i++; |
346
|
0
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
0
|
0
|
|
|
|
|
while (i < size && text[i] != '>') |
|
|
0
|
|
|
|
|
|
349
|
0
|
|
|
|
|
|
i++; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
|
352
|
0
|
|
|
|
|
|
hoedown_buffer_put(ob, text, i + 1); |
353
|
0
|
|
|
|
|
|
return i; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
static size_t |
357
|
0
|
|
|
|
|
|
smartypants_cb__escape(hoedown_buffer *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size) |
358
|
|
|
|
|
|
|
{ |
359
|
0
|
0
|
|
|
|
|
if (size < 2) |
360
|
|
|
|
|
|
|
return 0; |
361
|
|
|
|
|
|
|
|
362
|
0
|
0
|
|
|
|
|
switch (text[1]) { |
|
|
0
|
|
|
|
|
|
363
|
|
|
|
|
|
|
case '\\': |
364
|
|
|
|
|
|
|
case '"': |
365
|
|
|
|
|
|
|
case '\'': |
366
|
|
|
|
|
|
|
case '.': |
367
|
|
|
|
|
|
|
case '-': |
368
|
|
|
|
|
|
|
case '`': |
369
|
0
|
|
|
|
|
|
hoedown_buffer_putc(ob, text[1]); |
370
|
0
|
|
|
|
|
|
return 1; |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
default: |
373
|
0
|
|
|
|
|
|
hoedown_buffer_putc(ob, '\\'); |
374
|
0
|
|
|
|
|
|
return 0; |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
#if 0 |
379
|
|
|
|
|
|
|
static struct { |
380
|
|
|
|
|
|
|
uint8_t c0; |
381
|
|
|
|
|
|
|
const uint8_t *pattern; |
382
|
|
|
|
|
|
|
const uint8_t *entity; |
383
|
|
|
|
|
|
|
int skip; |
384
|
|
|
|
|
|
|
} smartypants_subs[] = { |
385
|
|
|
|
|
|
|
{ '\'', "'s>", "’", 0 }, |
386
|
|
|
|
|
|
|
{ '\'', "'t>", "’", 0 }, |
387
|
|
|
|
|
|
|
{ '\'', "'re>", "’", 0 }, |
388
|
|
|
|
|
|
|
{ '\'', "'ll>", "’", 0 }, |
389
|
|
|
|
|
|
|
{ '\'', "'ve>", "’", 0 }, |
390
|
|
|
|
|
|
|
{ '\'', "'m>", "’", 0 }, |
391
|
|
|
|
|
|
|
{ '\'', "'d>", "’", 0 }, |
392
|
|
|
|
|
|
|
{ '-', "--", "—", 1 }, |
393
|
|
|
|
|
|
|
{ '-', "<->", "–", 0 }, |
394
|
|
|
|
|
|
|
{ '.', "...", "…", 2 }, |
395
|
|
|
|
|
|
|
{ '.', ". . .", "…", 4 }, |
396
|
|
|
|
|
|
|
{ '(', "(c)", "©", 2 }, |
397
|
|
|
|
|
|
|
{ '(', "(r)", "®", 2 }, |
398
|
|
|
|
|
|
|
{ '(', "(tm)", "™", 3 }, |
399
|
|
|
|
|
|
|
{ '3', "<3/4>", "¾", 2 }, |
400
|
|
|
|
|
|
|
{ '3', "<3/4ths>", "¾", 2 }, |
401
|
|
|
|
|
|
|
{ '1', "<1/2>", "½", 2 }, |
402
|
|
|
|
|
|
|
{ '1', "<1/4>", "¼", 2 }, |
403
|
|
|
|
|
|
|
{ '1', "<1/4th>", "¼", 2 }, |
404
|
|
|
|
|
|
|
{ '&', "", 0, 3 }, |
405
|
|
|
|
|
|
|
}; |
406
|
|
|
|
|
|
|
#endif |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
void |
409
|
0
|
|
|
|
|
|
hoedown_html_smartypants(hoedown_buffer *ob, const uint8_t *text, size_t size) |
410
|
|
|
|
|
|
|
{ |
411
|
|
|
|
|
|
|
size_t i; |
412
|
0
|
|
|
|
|
|
struct smartypants_data smrt = {0, 0}; |
413
|
|
|
|
|
|
|
|
414
|
0
|
0
|
|
|
|
|
if (!text) |
415
|
0
|
|
|
|
|
|
return; |
416
|
|
|
|
|
|
|
|
417
|
0
|
|
|
|
|
|
hoedown_buffer_grow(ob, size); |
418
|
|
|
|
|
|
|
|
419
|
0
|
0
|
|
|
|
|
for (i = 0; i < size; ++i) { |
420
|
|
|
|
|
|
|
size_t org; |
421
|
|
|
|
|
|
|
uint8_t action = 0; |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
org = i; |
424
|
0
|
0
|
|
|
|
|
while (i < size && (action = smartypants_cb_chars[text[i]]) == 0) |
|
|
0
|
|
|
|
|
|
425
|
0
|
|
|
|
|
|
i++; |
426
|
|
|
|
|
|
|
|
427
|
0
|
0
|
|
|
|
|
if (i > org) |
428
|
0
|
|
|
|
|
|
hoedown_buffer_put(ob, text + org, i - org); |
429
|
|
|
|
|
|
|
|
430
|
0
|
0
|
|
|
|
|
if (i < size) { |
431
|
0
|
0
|
|
|
|
|
i += smartypants_cb_ptrs[(int)action] |
432
|
0
|
|
|
|
|
|
(ob, &smrt, i ? text[i - 1] : 0, text + i, size - i); |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
} |