qiita_marker 0.23.2.0 → 0.23.2.3
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 +4 -4
- data/LICENSE.txt +19 -17
- data/README.md +29 -1
- data/ext/qiita_marker/autolink.c +57 -10
- data/ext/qiita_marker/core-extensions.c +2 -0
- data/ext/qiita_marker/html.c +13 -0
- data/ext/qiita_marker/inlines.c +17 -5
- data/ext/qiita_marker/qfm.h +22 -0
- data/ext/qiita_marker/qfm_custom_block.c +265 -0
- data/ext/qiita_marker/qfm_custom_block.h +10 -0
- data/ext/qiita_marker/qfm_mention_no_emphasis.c +37 -0
- data/ext/qiita_marker/qfm_mention_no_emphasis.h +8 -0
- data/ext/qiita_marker/qfm_scanners.c +291 -0
- data/ext/qiita_marker/qfm_scanners.h +20 -0
- data/ext/qiita_marker/qfm_scanners.re +50 -0
- data/lib/qiita_marker/config.rb +7 -2
- data/lib/qiita_marker/renderer/html_renderer.rb +4 -0
- data/lib/qiita_marker/version.rb +1 -1
- data/qiita_marker.gemspec +1 -1
- data/test/test_qfm_autolink_class_name.rb +62 -0
- data/test/test_qfm_code_data_metadata.rb +41 -0
- data/test/test_qfm_custom_block.rb +39 -0
- data/test/test_qfm_mention_no_emphasis.rb +60 -0
- metadata +19 -3
@@ -0,0 +1,37 @@
|
|
1
|
+
#include "cmark-gfm.h"
|
2
|
+
#include "cmark_ctype.h"
|
3
|
+
#include "config.h"
|
4
|
+
|
5
|
+
static bool is_wordchar(char c) {
|
6
|
+
return cmark_isalnum(c) || c == '_' || c == '-';
|
7
|
+
}
|
8
|
+
|
9
|
+
bool is_part_of_mention(unsigned char *data, bufsize_t offset) {
|
10
|
+
int i;
|
11
|
+
int lookbehind_limit = (int)-offset;
|
12
|
+
char character;
|
13
|
+
|
14
|
+
for (i = 0; i >= lookbehind_limit; i--) {
|
15
|
+
character = data[i];
|
16
|
+
|
17
|
+
if (is_wordchar(character)) {
|
18
|
+
// Continue lookbehind.
|
19
|
+
} else if (character == '@') {
|
20
|
+
if (i == offset) {
|
21
|
+
// The "@" is at beginning of the text. (e.g. "@foo")
|
22
|
+
return true;
|
23
|
+
} else {
|
24
|
+
// Check if the previous character of the "@" is alphanumeric or not.
|
25
|
+
// " @foo" and "あ@foo" are mentions.
|
26
|
+
// "a@foo" is not a mention.
|
27
|
+
char prev_character = data[i - 1];
|
28
|
+
return !cmark_isalnum(prev_character);
|
29
|
+
}
|
30
|
+
} else {
|
31
|
+
// Found non-mention character, so this is not a mention.
|
32
|
+
return false;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
return false;
|
37
|
+
}
|
@@ -0,0 +1,291 @@
|
|
1
|
+
/* Generated by re2c 1.3 */
|
2
|
+
|
3
|
+
#include "qfm_scanners.h"
|
4
|
+
#include <stdlib.h>
|
5
|
+
|
6
|
+
bufsize_t _qfm_scan_at(bufsize_t (*scanner)(const unsigned char *),
|
7
|
+
unsigned char *ptr, int len, bufsize_t offset) {
|
8
|
+
bufsize_t res;
|
9
|
+
|
10
|
+
if (ptr == NULL || offset >= len) {
|
11
|
+
return 0;
|
12
|
+
} else {
|
13
|
+
unsigned char lim = ptr[len];
|
14
|
+
|
15
|
+
ptr[len] = '\0';
|
16
|
+
res = scanner(ptr + offset);
|
17
|
+
ptr[len] = lim;
|
18
|
+
}
|
19
|
+
|
20
|
+
return res;
|
21
|
+
}
|
22
|
+
|
23
|
+
// Scan an opening qfm_custom_block fence.
|
24
|
+
bufsize_t _scan_open_qfm_custom_block_fence(const unsigned char *p) {
|
25
|
+
const unsigned char *marker = NULL;
|
26
|
+
const unsigned char *start = p;
|
27
|
+
|
28
|
+
{
|
29
|
+
unsigned char yych;
|
30
|
+
static const unsigned char yybm[] = {
|
31
|
+
0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 0,
|
32
|
+
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
33
|
+
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
34
|
+
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
35
|
+
128, 128, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
36
|
+
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
37
|
+
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
38
|
+
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
39
|
+
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
40
|
+
128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
41
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
42
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
43
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
44
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
45
|
+
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,
|
47
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
48
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
49
|
+
0, 0, 0, 0,
|
50
|
+
};
|
51
|
+
yych = *p;
|
52
|
+
if (yych == ':')
|
53
|
+
goto yy4;
|
54
|
+
++p;
|
55
|
+
yy3 : { return 0; }
|
56
|
+
yy4:
|
57
|
+
yych = *(marker = ++p);
|
58
|
+
if (yych != ':')
|
59
|
+
goto yy3;
|
60
|
+
yych = *++p;
|
61
|
+
if (yybm[0 + yych] & 64) {
|
62
|
+
goto yy7;
|
63
|
+
}
|
64
|
+
yy6:
|
65
|
+
p = marker;
|
66
|
+
goto yy3;
|
67
|
+
yy7:
|
68
|
+
yych = *++p;
|
69
|
+
if (yybm[0 + yych] & 64) {
|
70
|
+
goto yy7;
|
71
|
+
}
|
72
|
+
if (yych <= 0xDF) {
|
73
|
+
if (yych <= '\f') {
|
74
|
+
if (yych <= 0x00)
|
75
|
+
goto yy6;
|
76
|
+
if (yych == '\n') {
|
77
|
+
marker = p;
|
78
|
+
goto yy11;
|
79
|
+
}
|
80
|
+
marker = p;
|
81
|
+
} else {
|
82
|
+
if (yych <= '\r') {
|
83
|
+
marker = p;
|
84
|
+
goto yy11;
|
85
|
+
}
|
86
|
+
if (yych <= 0x7F) {
|
87
|
+
marker = p;
|
88
|
+
goto yy9;
|
89
|
+
}
|
90
|
+
if (yych <= 0xC1)
|
91
|
+
goto yy6;
|
92
|
+
marker = p;
|
93
|
+
goto yy13;
|
94
|
+
}
|
95
|
+
} else {
|
96
|
+
if (yych <= 0xEF) {
|
97
|
+
if (yych <= 0xE0) {
|
98
|
+
marker = p;
|
99
|
+
goto yy14;
|
100
|
+
}
|
101
|
+
if (yych == 0xED) {
|
102
|
+
marker = p;
|
103
|
+
goto yy16;
|
104
|
+
}
|
105
|
+
marker = p;
|
106
|
+
goto yy15;
|
107
|
+
} else {
|
108
|
+
if (yych <= 0xF0) {
|
109
|
+
marker = p;
|
110
|
+
goto yy17;
|
111
|
+
}
|
112
|
+
if (yych <= 0xF3) {
|
113
|
+
marker = p;
|
114
|
+
goto yy18;
|
115
|
+
}
|
116
|
+
if (yych <= 0xF4) {
|
117
|
+
marker = p;
|
118
|
+
goto yy19;
|
119
|
+
}
|
120
|
+
goto yy6;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
yy9:
|
124
|
+
yych = *++p;
|
125
|
+
if (yybm[0 + yych] & 128) {
|
126
|
+
goto yy9;
|
127
|
+
}
|
128
|
+
if (yych <= 0xEC) {
|
129
|
+
if (yych <= 0xC1) {
|
130
|
+
if (yych <= 0x00)
|
131
|
+
goto yy6;
|
132
|
+
if (yych >= 0x0E)
|
133
|
+
goto yy6;
|
134
|
+
} else {
|
135
|
+
if (yych <= 0xDF)
|
136
|
+
goto yy13;
|
137
|
+
if (yych <= 0xE0)
|
138
|
+
goto yy14;
|
139
|
+
goto yy15;
|
140
|
+
}
|
141
|
+
} else {
|
142
|
+
if (yych <= 0xF0) {
|
143
|
+
if (yych <= 0xED)
|
144
|
+
goto yy16;
|
145
|
+
if (yych <= 0xEF)
|
146
|
+
goto yy15;
|
147
|
+
goto yy17;
|
148
|
+
} else {
|
149
|
+
if (yych <= 0xF3)
|
150
|
+
goto yy18;
|
151
|
+
if (yych <= 0xF4)
|
152
|
+
goto yy19;
|
153
|
+
goto yy6;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
yy11:
|
157
|
+
++p;
|
158
|
+
p = marker;
|
159
|
+
{ return (bufsize_t)(p - start); }
|
160
|
+
yy13:
|
161
|
+
yych = *++p;
|
162
|
+
if (yych <= 0x7F)
|
163
|
+
goto yy6;
|
164
|
+
if (yych <= 0xBF)
|
165
|
+
goto yy9;
|
166
|
+
goto yy6;
|
167
|
+
yy14:
|
168
|
+
yych = *++p;
|
169
|
+
if (yych <= 0x9F)
|
170
|
+
goto yy6;
|
171
|
+
if (yych <= 0xBF)
|
172
|
+
goto yy13;
|
173
|
+
goto yy6;
|
174
|
+
yy15:
|
175
|
+
yych = *++p;
|
176
|
+
if (yych <= 0x7F)
|
177
|
+
goto yy6;
|
178
|
+
if (yych <= 0xBF)
|
179
|
+
goto yy13;
|
180
|
+
goto yy6;
|
181
|
+
yy16:
|
182
|
+
yych = *++p;
|
183
|
+
if (yych <= 0x7F)
|
184
|
+
goto yy6;
|
185
|
+
if (yych <= 0x9F)
|
186
|
+
goto yy13;
|
187
|
+
goto yy6;
|
188
|
+
yy17:
|
189
|
+
yych = *++p;
|
190
|
+
if (yych <= 0x8F)
|
191
|
+
goto yy6;
|
192
|
+
if (yych <= 0xBF)
|
193
|
+
goto yy15;
|
194
|
+
goto yy6;
|
195
|
+
yy18:
|
196
|
+
yych = *++p;
|
197
|
+
if (yych <= 0x7F)
|
198
|
+
goto yy6;
|
199
|
+
if (yych <= 0xBF)
|
200
|
+
goto yy15;
|
201
|
+
goto yy6;
|
202
|
+
yy19:
|
203
|
+
yych = *++p;
|
204
|
+
if (yych <= 0x7F)
|
205
|
+
goto yy6;
|
206
|
+
if (yych <= 0x8F)
|
207
|
+
goto yy15;
|
208
|
+
goto yy6;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
// Scan a closing qfm_custom_block fence with length at least len.
|
213
|
+
bufsize_t _scan_close_qfm_custom_block_fence(const unsigned char *p) {
|
214
|
+
const unsigned char *marker = NULL;
|
215
|
+
const unsigned char *start = p;
|
216
|
+
|
217
|
+
{
|
218
|
+
unsigned char yych;
|
219
|
+
static const unsigned char yybm[] = {
|
220
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
221
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
222
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0,
|
223
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
224
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
225
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
226
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
227
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
228
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
229
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
230
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
231
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
232
|
+
};
|
233
|
+
yych = *p;
|
234
|
+
if (yych == ':')
|
235
|
+
goto yy24;
|
236
|
+
++p;
|
237
|
+
yy23 : { return 0; }
|
238
|
+
yy24:
|
239
|
+
yych = *(marker = ++p);
|
240
|
+
if (yych != ':')
|
241
|
+
goto yy23;
|
242
|
+
yych = *++p;
|
243
|
+
if (yybm[0 + yych] & 64) {
|
244
|
+
goto yy27;
|
245
|
+
}
|
246
|
+
yy26:
|
247
|
+
p = marker;
|
248
|
+
goto yy23;
|
249
|
+
yy27:
|
250
|
+
yych = *++p;
|
251
|
+
if (yybm[0 + yych] & 64) {
|
252
|
+
goto yy27;
|
253
|
+
}
|
254
|
+
if (yych <= '\f') {
|
255
|
+
if (yych <= 0x08)
|
256
|
+
goto yy26;
|
257
|
+
if (yych <= '\t') {
|
258
|
+
marker = p;
|
259
|
+
goto yy29;
|
260
|
+
}
|
261
|
+
if (yych <= '\n') {
|
262
|
+
marker = p;
|
263
|
+
goto yy31;
|
264
|
+
}
|
265
|
+
goto yy26;
|
266
|
+
} else {
|
267
|
+
if (yych <= '\r') {
|
268
|
+
marker = p;
|
269
|
+
goto yy31;
|
270
|
+
}
|
271
|
+
if (yych != ' ')
|
272
|
+
goto yy26;
|
273
|
+
marker = p;
|
274
|
+
}
|
275
|
+
yy29:
|
276
|
+
yych = *++p;
|
277
|
+
if (yybm[0 + yych] & 128) {
|
278
|
+
goto yy29;
|
279
|
+
}
|
280
|
+
if (yych <= 0x08)
|
281
|
+
goto yy26;
|
282
|
+
if (yych <= '\n')
|
283
|
+
goto yy31;
|
284
|
+
if (yych != '\r')
|
285
|
+
goto yy26;
|
286
|
+
yy31:
|
287
|
+
++p;
|
288
|
+
p = marker;
|
289
|
+
{ return (bufsize_t)(p - start); }
|
290
|
+
}
|
291
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#include "chunk.h"
|
2
|
+
#include "cmark-gfm.h"
|
3
|
+
|
4
|
+
#ifdef __cplusplus
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
bufsize_t _qfm_scan_at(bufsize_t (*scanner)(const unsigned char *),
|
9
|
+
unsigned char *ptr, int len, bufsize_t offset);
|
10
|
+
bufsize_t _scan_open_qfm_custom_block_fence(const unsigned char *p);
|
11
|
+
bufsize_t _scan_close_qfm_custom_block_fence(const unsigned char *p);
|
12
|
+
|
13
|
+
#define scan_open_qfm_custom_block_fence(c, l, n) \
|
14
|
+
_qfm_scan_at(&_scan_open_qfm_custom_block_fence, c, l, n)
|
15
|
+
#define scan_close_qfm_custom_block_fence(c, l, n) \
|
16
|
+
_qfm_scan_at(&_scan_close_qfm_custom_block_fence, c, l, n)
|
17
|
+
|
18
|
+
#ifdef __cplusplus
|
19
|
+
}
|
20
|
+
#endif
|
@@ -0,0 +1,50 @@
|
|
1
|
+
/*!re2c re2c:flags:no-debug-info = 1; */
|
2
|
+
/*!re2c re2c:indent:string = ' '; */
|
3
|
+
|
4
|
+
#include "qfm_scanners.h"
|
5
|
+
#include <stdlib.h>
|
6
|
+
|
7
|
+
bufsize_t _qfm_scan_at(bufsize_t (*scanner)(const unsigned char *),
|
8
|
+
unsigned char *ptr, int len, bufsize_t offset) {
|
9
|
+
bufsize_t res;
|
10
|
+
|
11
|
+
if (ptr == NULL || offset >= len) {
|
12
|
+
return 0;
|
13
|
+
} else {
|
14
|
+
unsigned char lim = ptr[len];
|
15
|
+
|
16
|
+
ptr[len] = '\0';
|
17
|
+
res = scanner(ptr + offset);
|
18
|
+
ptr[len] = lim;
|
19
|
+
}
|
20
|
+
|
21
|
+
return res;
|
22
|
+
}
|
23
|
+
|
24
|
+
/*!re2c
|
25
|
+
re2c:define:YYCTYPE = "unsigned char";
|
26
|
+
re2c:define:YYCURSOR = p;
|
27
|
+
re2c:define:YYMARKER = marker;
|
28
|
+
re2c:define:YYCTXMARKER = marker;
|
29
|
+
re2c:yyfill:enable = 0;
|
30
|
+
*/
|
31
|
+
|
32
|
+
// Scan an opening qfm_custom_block fence.
|
33
|
+
bufsize_t _scan_open_qfm_custom_block_fence(const unsigned char *p) {
|
34
|
+
const unsigned char *marker = NULL;
|
35
|
+
const unsigned char *start = p;
|
36
|
+
/*!re2c
|
37
|
+
[:]{3,} / [^:\r\n\x00]*[\r\n] { return (bufsize_t)(p - start); }
|
38
|
+
* { return 0; }
|
39
|
+
*/
|
40
|
+
}
|
41
|
+
|
42
|
+
// Scan a closing qfm_custom_block fence with length at least len.
|
43
|
+
bufsize_t _scan_close_qfm_custom_block_fence(const unsigned char *p) {
|
44
|
+
const unsigned char *marker = NULL;
|
45
|
+
const unsigned char *start = p;
|
46
|
+
/*!re2c
|
47
|
+
[:]{3,} / [ \t]*[\r\n] { return (bufsize_t)(p - start); }
|
48
|
+
* { return 0; }
|
49
|
+
*/
|
50
|
+
}
|
data/lib/qiita_marker/config.rb
CHANGED
@@ -13,7 +13,9 @@ module QiitaMarker
|
|
13
13
|
SMART: (1 << 10),
|
14
14
|
LIBERAL_HTML_TAG: (1 << 12),
|
15
15
|
FOOTNOTES: (1 << 13),
|
16
|
-
STRIKETHROUGH_DOUBLE_TILDE: (1 << 14)
|
16
|
+
STRIKETHROUGH_DOUBLE_TILDE: (1 << 14),
|
17
|
+
MENTION_NO_EMPHASIS: (1 << 26),
|
18
|
+
AUTOLINK_CLASS_NAME: (1 << 27)
|
17
19
|
}.freeze,
|
18
20
|
render: {
|
19
21
|
DEFAULT: 0,
|
@@ -28,7 +30,10 @@ module QiitaMarker
|
|
28
30
|
FOOTNOTES: (1 << 13),
|
29
31
|
STRIKETHROUGH_DOUBLE_TILDE: (1 << 14),
|
30
32
|
TABLE_PREFER_STYLE_ATTRIBUTES: (1 << 15),
|
31
|
-
FULL_INFO_STRING: (1 << 16)
|
33
|
+
FULL_INFO_STRING: (1 << 16),
|
34
|
+
CODE_DATA_METADATA: (1 << 25),
|
35
|
+
MENTION_NO_EMPHASIS: (1 << 26),
|
36
|
+
AUTOLINK_CLASS_NAME: (1 << 27)
|
32
37
|
}.freeze,
|
33
38
|
format: %i[html xml commonmark plaintext].freeze
|
34
39
|
}.freeze
|
@@ -94,6 +94,10 @@ module QiitaMarker
|
|
94
94
|
out("<pre#{sourcepos(node)}")
|
95
95
|
out(' lang="', node.fence_info.split(/\s+/)[0], '"') if node.fence_info && !node.fence_info.empty?
|
96
96
|
out('><code>')
|
97
|
+
elsif option_enabled?(:CODE_DATA_METADATA)
|
98
|
+
out("<pre#{sourcepos(node)}><code")
|
99
|
+
out(' data-metadata="', node.fence_info, '"') if node.fence_info && !node.fence_info.empty?
|
100
|
+
out('>')
|
97
101
|
else
|
98
102
|
out("<pre#{sourcepos(node)}><code")
|
99
103
|
if node.fence_info && !node.fence_info.empty?
|
data/lib/qiita_marker/version.rb
CHANGED
data/qiita_marker.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.version = QiitaMarker::VERSION
|
10
10
|
s.summary = 'Qiita Marker is a Ruby library for Markdown processing, based on CommonMarker.'
|
11
11
|
s.description = 'A Ruby library that is the core module of the Qiita-specified markdown processor.'
|
12
|
-
s.authors = ['
|
12
|
+
s.authors = ['Qiita Inc.']
|
13
13
|
s.homepage = 'https://github.com/increments/qiita_marker'
|
14
14
|
s.license = 'MIT'
|
15
15
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('test_helper')
|
4
|
+
|
5
|
+
describe 'TestQfmAutolinkClassName' do
|
6
|
+
let(:options) { %i[AUTOLINK_CLASS_NAME] }
|
7
|
+
let(:extensions) { %i[autolink] }
|
8
|
+
let(:text) do
|
9
|
+
<<~MD
|
10
|
+
https://example.com
|
11
|
+
<https://example.com>
|
12
|
+
[Example](https://example.com)
|
13
|
+
test@example.com
|
14
|
+
MD
|
15
|
+
end
|
16
|
+
let(:doc) { QiitaMarker.render_doc(text, options, extensions) }
|
17
|
+
let(:expected) do
|
18
|
+
<<~HTML
|
19
|
+
<p><a href="https://example.com" class="autolink">https://example.com</a>
|
20
|
+
<a href="https://example.com">https://example.com</a>
|
21
|
+
<a href="https://example.com">Example</a>
|
22
|
+
<a href="mailto:test@example.com" class="autolink">test@example.com</a></p>
|
23
|
+
HTML
|
24
|
+
end
|
25
|
+
let(:rendered_html) { doc.to_html(options, extensions) }
|
26
|
+
|
27
|
+
it "appends class name to extension's autolinks" do
|
28
|
+
assert_equal(expected, rendered_html)
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'without AUTOLINK_CLASS_NAME option' do
|
32
|
+
let(:options) { %i[DEFAULT] }
|
33
|
+
let(:expected) do
|
34
|
+
<<~HTML
|
35
|
+
<p><a href="https://example.com">https://example.com</a>
|
36
|
+
<a href="https://example.com">https://example.com</a>
|
37
|
+
<a href="https://example.com">Example</a>
|
38
|
+
<a href="mailto:test@example.com">test@example.com</a></p>
|
39
|
+
HTML
|
40
|
+
end
|
41
|
+
|
42
|
+
it "does not append class name to extension's autolink" do
|
43
|
+
assert_equal(expected, rendered_html)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'without autolink extension' do
|
48
|
+
let(:extensions) { %i[] }
|
49
|
+
let(:expected) do
|
50
|
+
<<~HTML
|
51
|
+
<p>https://example.com
|
52
|
+
<a href="https://example.com">https://example.com</a>
|
53
|
+
<a href="https://example.com">Example</a>
|
54
|
+
test@example.com</p>
|
55
|
+
HTML
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'does not append class name' do
|
59
|
+
assert_equal(expected, rendered_html)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('test_helper')
|
4
|
+
|
5
|
+
class TestQfmCodeDataMetadata < Minitest::Test
|
6
|
+
def test_to_html
|
7
|
+
text = <<~MD
|
8
|
+
```ruby:example main.rb
|
9
|
+
puts :foo
|
10
|
+
```
|
11
|
+
MD
|
12
|
+
doc = render_doc(text)
|
13
|
+
expected = <<~HTML
|
14
|
+
<pre><code data-metadata="ruby:example main.rb">puts :foo
|
15
|
+
</code></pre>
|
16
|
+
HTML
|
17
|
+
|
18
|
+
assert_equal(expected, doc.to_html(:CODE_DATA_METADATA))
|
19
|
+
assert_equal(expected, QiitaMarker::HtmlRenderer.new(options: :CODE_DATA_METADATA).render(doc))
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_with_character_reference
|
23
|
+
text = <<~MD
|
24
|
+
```ruby:example main.rb
|
25
|
+
puts :foo
|
26
|
+
```
|
27
|
+
MD
|
28
|
+
doc = render_doc(text)
|
29
|
+
expected = <<~HTML
|
30
|
+
<pre><code data-metadata="ruby:example main.rb">puts :foo
|
31
|
+
</code></pre>
|
32
|
+
HTML
|
33
|
+
|
34
|
+
assert_equal(expected, doc.to_html(:CODE_DATA_METADATA))
|
35
|
+
assert_equal(expected, QiitaMarker::HtmlRenderer.new(options: :CODE_DATA_METADATA).render(doc))
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_doc(markdown)
|
39
|
+
QiitaMarker.render_doc(markdown, :DEFAULT, [])
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('test_helper')
|
4
|
+
|
5
|
+
class TestQfmCustomBlock < Minitest::Test
|
6
|
+
def setup
|
7
|
+
text = <<~MD
|
8
|
+
:::foo bar
|
9
|
+
message
|
10
|
+
|
11
|
+
- list1
|
12
|
+
- list2
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
puts 'hello'
|
16
|
+
```
|
17
|
+
|
18
|
+
<div>html block</div>
|
19
|
+
:::
|
20
|
+
MD
|
21
|
+
@doc = QiitaMarker.render_doc(text, %i[UNSAFE], %i[custom_block])
|
22
|
+
@expected = <<~HTML
|
23
|
+
<div data-type="customblock" data-metadata="foo bar">
|
24
|
+
<p>message</p>
|
25
|
+
<ul>
|
26
|
+
<li>list1</li>
|
27
|
+
<li>list2</li>
|
28
|
+
</ul>
|
29
|
+
<pre><code class="language-ruby">puts 'hello'
|
30
|
+
</code></pre>
|
31
|
+
<div>html block</div>
|
32
|
+
</div>
|
33
|
+
HTML
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_to_html
|
37
|
+
assert_equal(@expected, @doc.to_html(%i[UNSAFE], %i[custom_block]))
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class TestQfmMentionNoEmphasis < Minitest::Test
|
6
|
+
describe 'with mention_no_emphasis option' do
|
7
|
+
[
|
8
|
+
['@_username_', false],
|
9
|
+
['@__username__', false],
|
10
|
+
['@___username___', false],
|
11
|
+
['@user__name__', false],
|
12
|
+
['@some__user__name__', false],
|
13
|
+
[' @_username_', false],
|
14
|
+
['あ@_username_', false],
|
15
|
+
['A@_username_', true],
|
16
|
+
['@*username*', true],
|
17
|
+
['_foo_', true],
|
18
|
+
['_', false],
|
19
|
+
['_foo @username_', false],
|
20
|
+
['__foo @username__', false],
|
21
|
+
['___foo @username___', false]
|
22
|
+
].each do |text, emphasize|
|
23
|
+
describe "with text #{text.inspect}" do
|
24
|
+
if emphasize
|
25
|
+
it 'emphasizes the text' do
|
26
|
+
QiitaMarker.render_html(text, :MENTION_NO_EMPHASIS).tap do |out|
|
27
|
+
assert_match(/(<em>|<strong>)/, out.chomp)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
else
|
31
|
+
it 'does not emphasize the text' do
|
32
|
+
QiitaMarker.render_html(text, :MENTION_NO_EMPHASIS).tap do |out|
|
33
|
+
assert_match "<p>#{text.strip}</p>", out.chomp
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'without mention_no_emphasis option' do
|
42
|
+
describe 'with text "@_username_"' do
|
43
|
+
text = '@_username_'
|
44
|
+
it 'emphasizes the text' do
|
45
|
+
QiitaMarker.render_html(text, :DEFAULT, %i[]).tap do |out|
|
46
|
+
assert_match(/<em>/, out.chomp)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'with text "_foo @username_"' do
|
52
|
+
text = '_foo @username_'
|
53
|
+
it 'emphasizes the text' do
|
54
|
+
QiitaMarker.render_html(text, :DEFAULT, %i[]).tap do |out|
|
55
|
+
assert_match(/<em>/, out.chomp)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|