| 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
|
|
|
|
|
|
|
} |