dtext_rb 1.0.0 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/dtext_rb.gemspec +2 -2
- data/ext/dtext/dtext.c +2482 -2565
- data/ext/dtext/dtext.rl +229 -213
- data/ext/dtext/extconf.rb +2 -0
- data/lib/dtext.rb +10 -0
- data/test/dtext_test.rb +17 -13
- metadata +1 -1
data/ext/dtext/dtext.rl
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
#include <glib.h>
|
10
10
|
|
11
11
|
typedef struct StateMachine {
|
12
|
-
|
12
|
+
size_t top;
|
13
13
|
int cs;
|
14
14
|
int act;
|
15
15
|
const char * p;
|
@@ -23,6 +23,7 @@ typedef struct StateMachine {
|
|
23
23
|
const char * b1;
|
24
24
|
const char * b2;
|
25
25
|
bool f_inline;
|
26
|
+
bool f_strip;
|
26
27
|
bool list_mode;
|
27
28
|
GString * output;
|
28
29
|
GArray * stack;
|
@@ -32,7 +33,8 @@ typedef struct StateMachine {
|
|
32
33
|
int b;
|
33
34
|
} StateMachine;
|
34
35
|
|
35
|
-
static const
|
36
|
+
static const size_t MAX_STACK_DEPTH = 512;
|
37
|
+
|
36
38
|
static const int BLOCK_P = 1;
|
37
39
|
static const int INLINE_SPOILER = 2;
|
38
40
|
static const int BLOCK_SPOILER = 3;
|
@@ -139,113 +141,124 @@ list_item = '*'+ >mark_a1 %mark_a2 ws+ nonnewline+ >mark_b1 %mark_b2;
|
|
139
141
|
|
140
142
|
inline := |*
|
141
143
|
post_id => {
|
142
|
-
append(sm, "<a href=\"/posts/");
|
143
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
144
|
-
append(sm, "\">
|
145
|
-
|
146
|
-
|
144
|
+
append(sm, true, "<a href=\"/posts/");
|
145
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
146
|
+
append(sm, true, "\">");
|
147
|
+
append(sm, false, "post #");
|
148
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
149
|
+
append(sm, true, "</a>");
|
147
150
|
};
|
148
151
|
|
149
152
|
forum_post_id => {
|
150
|
-
append(sm, "<a href=\"/forum_posts/");
|
151
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
152
|
-
append(sm, "\">
|
153
|
-
|
154
|
-
|
153
|
+
append(sm, true, "<a href=\"/forum_posts/");
|
154
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
155
|
+
append(sm, true, "\">");
|
156
|
+
append(sm, false, "forum #");
|
157
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
158
|
+
append(sm, true, "</a>");
|
155
159
|
};
|
156
160
|
|
157
161
|
forum_topic_id => {
|
158
|
-
append(sm, "<a href=\"/forum_topics/");
|
159
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
160
|
-
append(sm, "\">
|
161
|
-
|
162
|
-
|
162
|
+
append(sm, true, "<a href=\"/forum_topics/");
|
163
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
164
|
+
append(sm, true, "\">");
|
165
|
+
append(sm, false, "topic #");
|
166
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
167
|
+
append(sm, true, "</a>");
|
163
168
|
};
|
164
169
|
|
165
170
|
forum_topic_paged_id => {
|
166
|
-
append(sm, "<a href=\"/forum_topics/");
|
167
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
168
|
-
append(sm, "?page=");
|
169
|
-
append_segment(sm, sm->b1, sm->b2 - 1);
|
170
|
-
append(sm, "\">
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
171
|
+
append(sm, true, "<a href=\"/forum_topics/");
|
172
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
173
|
+
append(sm, true, "?page=");
|
174
|
+
append_segment(sm, true, sm->b1, sm->b2 - 1);
|
175
|
+
append(sm, true, "\">");
|
176
|
+
append(sm, false, "topic #");
|
177
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
178
|
+
append(sm, false, "/p");
|
179
|
+
append_segment(sm, false, sm->b1, sm->b2 - 1);
|
180
|
+
append(sm, true, "</a>");
|
175
181
|
};
|
176
182
|
|
177
183
|
comment_id => {
|
178
|
-
append(sm, "<a href=\"/comments/");
|
179
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
180
|
-
append(sm, "\">
|
181
|
-
|
182
|
-
|
184
|
+
append(sm, true, "<a href=\"/comments/");
|
185
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
186
|
+
append(sm, true, "\">");
|
187
|
+
append(sm, false, "comment #");
|
188
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
189
|
+
append(sm, true, "</a>");
|
183
190
|
};
|
184
191
|
|
185
192
|
pool_id => {
|
186
|
-
append(sm, "<a href=\"/pools/");
|
187
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
188
|
-
append(sm, "\">
|
189
|
-
|
190
|
-
|
193
|
+
append(sm, true, "<a href=\"/pools/");
|
194
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
195
|
+
append(sm, true, "\">");
|
196
|
+
append(sm, false, "pool #");
|
197
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
198
|
+
append(sm, true, "</a>");
|
191
199
|
};
|
192
200
|
|
193
201
|
user_id => {
|
194
|
-
append(sm, "<a href=\"/users/");
|
195
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
196
|
-
append(sm, "\">
|
197
|
-
|
198
|
-
|
202
|
+
append(sm, true, "<a href=\"/users/");
|
203
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
204
|
+
append(sm, true, "\">");
|
205
|
+
append(sm, false, "user #");
|
206
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
207
|
+
append(sm, true, "</a>");
|
199
208
|
};
|
200
209
|
|
201
210
|
artist_id => {
|
202
|
-
append(sm, "<a href=\"/artists/");
|
203
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
204
|
-
append(sm, "\">
|
205
|
-
|
206
|
-
|
211
|
+
append(sm, true, "<a href=\"/artists/");
|
212
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
213
|
+
append(sm, true, "\">");
|
214
|
+
append(sm, false, "artist #");
|
215
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
216
|
+
append(sm, true, "</a>");
|
207
217
|
};
|
208
218
|
|
209
219
|
github_issue_id => {
|
210
|
-
append(sm, "<a href=\"https://github.com/r888888888/danbooru/issues/");
|
211
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
212
|
-
append(sm, "\">
|
213
|
-
|
214
|
-
|
220
|
+
append(sm, true, "<a href=\"https://github.com/r888888888/danbooru/issues/");
|
221
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
222
|
+
append(sm, true, "\">");
|
223
|
+
append(sm, false, "issue #");
|
224
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
225
|
+
append(sm, true, "</a>");
|
215
226
|
};
|
216
227
|
|
217
228
|
pixiv_id => {
|
218
|
-
append(sm, "<a href=\"http://www.pixiv.net/member_illust.php?mode=medium&illust_id=");
|
219
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
220
|
-
append(sm, "\">
|
221
|
-
|
222
|
-
|
229
|
+
append(sm, true, "<a href=\"http://www.pixiv.net/member_illust.php?mode=medium&illust_id=");
|
230
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
231
|
+
append(sm, true, "\">");
|
232
|
+
append(sm, false, "pixiv #");
|
233
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
234
|
+
append(sm, true, "</a>");
|
223
235
|
};
|
224
236
|
|
225
237
|
pixiv_paged_id => {
|
226
|
-
append(sm, "<a href=\"http://www.pixiv.net/member_illust.php?mode=manga_big&illust_id=");
|
227
|
-
append_segment(sm, sm->a1, sm->a2 - 1);
|
228
|
-
append(sm, "&page=");
|
229
|
-
append_segment(sm, sm->b1, sm->b2 - 1);
|
230
|
-
append(sm, "\">
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
238
|
+
append(sm, true, "<a href=\"http://www.pixiv.net/member_illust.php?mode=manga_big&illust_id=");
|
239
|
+
append_segment(sm, true, sm->a1, sm->a2 - 1);
|
240
|
+
append(sm, true, "&page=");
|
241
|
+
append_segment(sm, true, sm->b1, sm->b2 - 1);
|
242
|
+
append(sm, true, "\">");
|
243
|
+
append(sm, false, "pixiv #");
|
244
|
+
append_segment(sm, false, sm->a1, sm->a2 - 1);
|
245
|
+
append(sm, false, "/p");
|
246
|
+
append_segment(sm, false, sm->b1, sm->b2 - 1);
|
247
|
+
append(sm, true, "</a>");
|
235
248
|
};
|
236
249
|
|
237
250
|
post_link => {
|
238
|
-
append(sm, "<a rel=\"nofollow\" href=\"/posts?tags=");
|
251
|
+
append(sm, true, "<a rel=\"nofollow\" href=\"/posts?tags=");
|
239
252
|
append_segment_uri_escaped(sm, sm->a1, sm->a2 - 1);
|
240
|
-
append(sm, "\">");
|
253
|
+
append(sm, true, "\">");
|
241
254
|
append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
|
242
|
-
append(sm, "</a>");
|
255
|
+
append(sm, true, "</a>");
|
243
256
|
};
|
244
257
|
|
245
258
|
basic_wiki_link => {
|
246
259
|
GString * segment = g_string_new_len(sm->a1, sm->a2 - sm->a1);
|
247
|
-
underscore_string(segment->str, segment->len);
|
248
260
|
GString * lowercase_segment = NULL;
|
261
|
+
underscore_string(segment->str, segment->len);
|
249
262
|
|
250
263
|
if (g_utf8_validate(segment->str, -1, NULL)) {
|
251
264
|
lowercase_segment = g_string_new(g_utf8_strdown(segment->str, -1));
|
@@ -253,11 +266,11 @@ inline := |*
|
|
253
266
|
lowercase_segment = g_string_new(g_ascii_strdown(segment->str, -1));
|
254
267
|
}
|
255
268
|
|
256
|
-
append(sm, "<a href=\"/wiki_pages/show_or_new?title=");
|
269
|
+
append(sm, true, "<a href=\"/wiki_pages/show_or_new?title=");
|
257
270
|
append_segment_uri_escaped(sm, lowercase_segment->str, lowercase_segment->str + lowercase_segment->len - 1);
|
258
|
-
append(sm, "\">");
|
271
|
+
append(sm, true, "\">");
|
259
272
|
append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
|
260
|
-
append(sm, "</a>");
|
273
|
+
append(sm, true, "</a>");
|
261
274
|
|
262
275
|
g_string_free(lowercase_segment, TRUE);
|
263
276
|
g_string_free(segment, TRUE);
|
@@ -265,8 +278,8 @@ inline := |*
|
|
265
278
|
|
266
279
|
aliased_wiki_link => {
|
267
280
|
GString * segment = g_string_new_len(sm->a1, sm->a2 - sm->a1);
|
268
|
-
underscore_string(segment->str, segment->len);
|
269
281
|
GString * lowercase_segment = NULL;
|
282
|
+
underscore_string(segment->str, segment->len);
|
270
283
|
|
271
284
|
if (g_utf8_validate(segment->str, -1, NULL)) {
|
272
285
|
lowercase_segment = g_string_new(g_utf8_strdown(segment->str, -1));
|
@@ -274,11 +287,11 @@ inline := |*
|
|
274
287
|
lowercase_segment = g_string_new(g_ascii_strdown(segment->str, -1));
|
275
288
|
}
|
276
289
|
|
277
|
-
append(sm, "<a href=\"/wiki_pages/show_or_new?title=");
|
290
|
+
append(sm, true, "<a href=\"/wiki_pages/show_or_new?title=");
|
278
291
|
append_segment_uri_escaped(sm, lowercase_segment->str, lowercase_segment->str + lowercase_segment->len - 1);
|
279
|
-
append(sm, "\">");
|
292
|
+
append(sm, true, "\">");
|
280
293
|
append_segment_html_escaped(sm, sm->b1, sm->b2 - 1);
|
281
|
-
append(sm, "</a>");
|
294
|
+
append(sm, true, "</a>");
|
282
295
|
|
283
296
|
g_string_free(lowercase_segment, TRUE);
|
284
297
|
g_string_free(segment, TRUE);
|
@@ -293,11 +306,11 @@ inline := |*
|
|
293
306
|
sm->b = false;
|
294
307
|
}
|
295
308
|
|
296
|
-
append(sm, "<a href=\"");
|
309
|
+
append(sm, true, "<a href=\"");
|
297
310
|
append_segment_uri_escaped(sm, sm->b1, sm->b2 - sm->d);
|
298
|
-
append(sm, "\">");
|
311
|
+
append(sm, true, "\">");
|
299
312
|
append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
|
300
|
-
append(sm, "</a>");
|
313
|
+
append(sm, true, "</a>");
|
301
314
|
|
302
315
|
if (sm->b) {
|
303
316
|
append_c_html_escaped(sm, fc);
|
@@ -305,11 +318,11 @@ inline := |*
|
|
305
318
|
};
|
306
319
|
|
307
320
|
bracketed_textile_link => {
|
308
|
-
append(sm, "<a href=\"");
|
321
|
+
append(sm, true, "<a href=\"");
|
309
322
|
append_segment_uri_escaped(sm, sm->b1, sm->b2 - 1);
|
310
|
-
append(sm, "\">");
|
323
|
+
append(sm, true, "\">");
|
311
324
|
append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
|
312
|
-
append(sm, "</a>");
|
325
|
+
append(sm, true, "</a>");
|
313
326
|
};
|
314
327
|
|
315
328
|
url => {
|
@@ -321,11 +334,11 @@ inline := |*
|
|
321
334
|
sm->d = 1;
|
322
335
|
}
|
323
336
|
|
324
|
-
append(sm, "<a href=\"");
|
337
|
+
append(sm, true, "<a href=\"");
|
325
338
|
append_segment_uri_escaped(sm, sm->ts, sm->te - sm->d);
|
326
|
-
append(sm, "\">");
|
339
|
+
append(sm, true, "\">");
|
327
340
|
append_segment_html_escaped(sm, sm->ts, sm->te - sm->d);
|
328
|
-
append(sm, "</a>");
|
341
|
+
append(sm, true, "</a>");
|
329
342
|
|
330
343
|
if (sm->b) {
|
331
344
|
append_c_html_escaped(sm, fc);
|
@@ -334,7 +347,7 @@ inline := |*
|
|
334
347
|
|
335
348
|
# probably a tag. examples include @.@ and @_@
|
336
349
|
'@' graph '@' => {
|
337
|
-
|
350
|
+
append_segment_html_escaped(sm, sm->ts, sm->te - 1);
|
338
351
|
};
|
339
352
|
|
340
353
|
mention => {
|
@@ -346,11 +359,12 @@ inline := |*
|
|
346
359
|
sm->d = 1;
|
347
360
|
}
|
348
361
|
|
349
|
-
append(sm, "<a rel=\"nofollow\" href=\"/users?name=");
|
362
|
+
append(sm, true, "<a rel=\"nofollow\" href=\"/users?name=");
|
350
363
|
append_segment_uri_escaped(sm, sm->a1, sm->a2 - sm->d);
|
351
|
-
append(sm, "\"
|
364
|
+
append(sm, true, "\">");
|
365
|
+
append_c(sm, '@');
|
352
366
|
append_segment_html_escaped(sm, sm->a1, sm->a2 - sm->d);
|
353
|
-
append(sm, "</a>");
|
367
|
+
append(sm, true, "</a>");
|
354
368
|
|
355
369
|
if (sm->b) {
|
356
370
|
append_c_html_escaped(sm, fc);
|
@@ -372,63 +386,63 @@ inline := |*
|
|
372
386
|
|
373
387
|
'[b]' => {
|
374
388
|
dstack_push(sm, &INLINE_B);
|
375
|
-
append(sm, "<strong>");
|
389
|
+
append(sm, true, "<strong>");
|
376
390
|
};
|
377
391
|
|
378
392
|
'[/b]' => {
|
379
393
|
if (dstack_check(sm, INLINE_B)) {
|
380
394
|
dstack_pop(sm);
|
381
|
-
append(sm, "</strong>");
|
395
|
+
append(sm, true, "</strong>");
|
382
396
|
} else {
|
383
|
-
append(sm, "[/b]");
|
397
|
+
append(sm, true, "[/b]");
|
384
398
|
}
|
385
399
|
};
|
386
400
|
|
387
401
|
'[i]' => {
|
388
402
|
dstack_push(sm, &INLINE_I);
|
389
|
-
append(sm, "<em>");
|
403
|
+
append(sm, true, "<em>");
|
390
404
|
};
|
391
405
|
|
392
406
|
'[/i]' => {
|
393
407
|
if (dstack_check(sm, INLINE_I)) {
|
394
408
|
dstack_pop(sm);
|
395
|
-
append(sm, "</em>");
|
409
|
+
append(sm, true, "</em>");
|
396
410
|
} else {
|
397
|
-
append(sm, "[/i]");
|
411
|
+
append(sm, true, "[/i]");
|
398
412
|
}
|
399
413
|
};
|
400
414
|
|
401
415
|
'[s]' => {
|
402
416
|
dstack_push(sm, &INLINE_S);
|
403
|
-
append(sm, "<s>");
|
417
|
+
append(sm, true, "<s>");
|
404
418
|
};
|
405
419
|
|
406
420
|
'[/s]' => {
|
407
421
|
if (dstack_check(sm, INLINE_S)) {
|
408
422
|
dstack_pop(sm);
|
409
|
-
append(sm, "</s>");
|
423
|
+
append(sm, true, "</s>");
|
410
424
|
} else {
|
411
|
-
append(sm, "[/s]");
|
425
|
+
append(sm, true, "[/s]");
|
412
426
|
}
|
413
427
|
};
|
414
428
|
|
415
429
|
'[u]' => {
|
416
430
|
dstack_push(sm, &INLINE_U);
|
417
|
-
append(sm, "<u>");
|
431
|
+
append(sm, true, "<u>");
|
418
432
|
};
|
419
433
|
|
420
434
|
'[/u]' => {
|
421
435
|
if (dstack_check(sm, INLINE_U)) {
|
422
436
|
dstack_pop(sm);
|
423
|
-
append(sm, "</u>");
|
437
|
+
append(sm, true, "</u>");
|
424
438
|
} else {
|
425
|
-
append(sm, "[/u]");
|
439
|
+
append(sm, true, "[/u]");
|
426
440
|
}
|
427
441
|
};
|
428
442
|
|
429
443
|
'[tn]' => {
|
430
444
|
dstack_push(sm, &INLINE_TN);
|
431
|
-
append(sm, "<span class=\"tn\">");
|
445
|
+
append(sm, true, "<span class=\"tn\">");
|
432
446
|
};
|
433
447
|
|
434
448
|
'[/tn]' => {
|
@@ -439,9 +453,9 @@ inline := |*
|
|
439
453
|
fret;
|
440
454
|
} else if (dstack_check(sm, INLINE_TN)) {
|
441
455
|
dstack_pop(sm);
|
442
|
-
append(sm, "</span>");
|
456
|
+
append(sm, true, "</span>");
|
443
457
|
} else {
|
444
|
-
|
458
|
+
append_block(sm, "[/tn]");
|
445
459
|
}
|
446
460
|
};
|
447
461
|
|
@@ -453,7 +467,7 @@ inline := |*
|
|
453
467
|
fret;
|
454
468
|
};
|
455
469
|
|
456
|
-
|
470
|
+
'[quote]' => {
|
457
471
|
g_debug("inline [quote]");
|
458
472
|
|
459
473
|
if (dstack_check(sm, BLOCK_P)) {
|
@@ -465,11 +479,11 @@ inline := |*
|
|
465
479
|
append_newline(sm);
|
466
480
|
}
|
467
481
|
|
468
|
-
fexec sm->
|
482
|
+
fexec sm->ts;
|
469
483
|
fret;
|
470
484
|
};
|
471
485
|
|
472
|
-
|
486
|
+
'[/quote]' space* => {
|
473
487
|
g_debug("inline [/quote]");
|
474
488
|
|
475
489
|
if (dstack_check(sm, BLOCK_P)) {
|
@@ -480,7 +494,7 @@ inline := |*
|
|
480
494
|
dstack_rewind(sm);
|
481
495
|
fret;
|
482
496
|
} else {
|
483
|
-
|
497
|
+
append_block(sm, "[/quote]");
|
484
498
|
}
|
485
499
|
};
|
486
500
|
|
@@ -488,17 +502,17 @@ inline := |*
|
|
488
502
|
g_debug("inline [spoiler]");
|
489
503
|
g_debug(" push <span>");
|
490
504
|
dstack_push(sm, &INLINE_SPOILER);
|
491
|
-
append(sm, "<span class=\"spoiler\">");
|
505
|
+
append(sm, true, "<span class=\"spoiler\">");
|
492
506
|
};
|
493
507
|
|
494
|
-
|
508
|
+
'[/spoiler]' => {
|
495
509
|
g_debug("inline [/spoiler]");
|
496
510
|
|
497
511
|
if (dstack_check(sm, INLINE_SPOILER)) {
|
498
512
|
g_debug(" pop dstack");
|
499
513
|
g_debug(" print </span>");
|
500
514
|
dstack_pop(sm);
|
501
|
-
append(sm, "</span>");
|
515
|
+
append(sm, true, "</span>");
|
502
516
|
} else if (dstack_check(sm, BLOCK_P) && dstack_check2(sm, BLOCK_SPOILER)) {
|
503
517
|
g_debug(" pop dstack");
|
504
518
|
g_debug(" print </p></div>");
|
@@ -513,17 +527,18 @@ inline := |*
|
|
513
527
|
|
514
528
|
fret;
|
515
529
|
} else {
|
516
|
-
|
530
|
+
append_block(sm, "[/spoiler]");
|
517
531
|
}
|
518
532
|
};
|
519
533
|
|
520
|
-
|
534
|
+
'[expand]' => {
|
535
|
+
g_debug("inline [expand]");
|
521
536
|
dstack_rewind(sm);
|
522
|
-
fexec(sm->p -
|
537
|
+
fexec(sm->p - 7);
|
523
538
|
fret;
|
524
539
|
};
|
525
540
|
|
526
|
-
|
541
|
+
'[/expand]' => {
|
527
542
|
if (dstack_check(sm, BLOCK_P)) {
|
528
543
|
append_closing_p(sm);
|
529
544
|
append_newline(sm);
|
@@ -538,7 +553,7 @@ inline := |*
|
|
538
553
|
dstack_pop(sm);
|
539
554
|
fret;
|
540
555
|
} else {
|
541
|
-
|
556
|
+
append_block(sm, "[/expand]");
|
542
557
|
}
|
543
558
|
};
|
544
559
|
|
@@ -555,7 +570,7 @@ inline := |*
|
|
555
570
|
append_newline(sm);
|
556
571
|
fret;
|
557
572
|
} else {
|
558
|
-
|
573
|
+
append_block(sm, "[/th]");
|
559
574
|
}
|
560
575
|
};
|
561
576
|
|
@@ -567,7 +582,7 @@ inline := |*
|
|
567
582
|
append_newline(sm);
|
568
583
|
fret;
|
569
584
|
} else {
|
570
|
-
|
585
|
+
append_block(sm, "[/td]");
|
571
586
|
}
|
572
587
|
};
|
573
588
|
|
@@ -601,7 +616,7 @@ inline := |*
|
|
601
616
|
if (sm->list_mode && (*(sm->p+1) == '*') && dstack_check(sm, BLOCK_LI)) {
|
602
617
|
dstack_rewind(sm);
|
603
618
|
} else {
|
604
|
-
append(sm, "<br>");
|
619
|
+
append(sm, true, "<br>");
|
605
620
|
append_newline(sm);
|
606
621
|
}
|
607
622
|
};
|
@@ -617,7 +632,7 @@ code := |*
|
|
617
632
|
if (dstack_check(sm, BLOCK_CODE)) {
|
618
633
|
dstack_rewind(sm);
|
619
634
|
} else {
|
620
|
-
append(sm, "[/code]");
|
635
|
+
append(sm, true, "[/code]");
|
621
636
|
}
|
622
637
|
fret;
|
623
638
|
};
|
@@ -645,7 +660,7 @@ nodtext := |*
|
|
645
660
|
dstack_pop(sm);
|
646
661
|
fret;
|
647
662
|
} else {
|
648
|
-
append(sm, "[/nodtext]");
|
663
|
+
append(sm, true, "[/nodtext]");
|
649
664
|
}
|
650
665
|
};
|
651
666
|
|
@@ -674,7 +689,7 @@ table := |*
|
|
674
689
|
append_block(sm, "</thead>");
|
675
690
|
append_newline(sm);
|
676
691
|
} else {
|
677
|
-
append(sm, "[/thead]");
|
692
|
+
append(sm, true, "[/thead]");
|
678
693
|
}
|
679
694
|
};
|
680
695
|
|
@@ -692,7 +707,7 @@ table := |*
|
|
692
707
|
append_block(sm, "</tbody>");
|
693
708
|
append_newline(sm);
|
694
709
|
} else {
|
695
|
-
append(sm, "[/tbody]");
|
710
|
+
append(sm, true, "[/tbody]");
|
696
711
|
}
|
697
712
|
};
|
698
713
|
|
@@ -718,7 +733,7 @@ table := |*
|
|
718
733
|
append_block(sm, "</tr>");
|
719
734
|
append_newline(sm);
|
720
735
|
} else {
|
721
|
-
append(sm, "[/tr]");
|
736
|
+
append(sm, true, "[/tr]");
|
722
737
|
}
|
723
738
|
};
|
724
739
|
|
@@ -739,7 +754,7 @@ table := |*
|
|
739
754
|
append_newline(sm);
|
740
755
|
fret;
|
741
756
|
} else {
|
742
|
-
append(sm, "[/table]");
|
757
|
+
append(sm, true, "[/table]");
|
743
758
|
}
|
744
759
|
};
|
745
760
|
|
@@ -753,15 +768,16 @@ table := |*
|
|
753
768
|
|
754
769
|
list := |*
|
755
770
|
list_item => {
|
771
|
+
int prev_nest = sm->list_nest;
|
756
772
|
g_debug("list start");
|
757
773
|
|
758
|
-
int prev_nest = sm->list_nest;
|
759
774
|
sm->list_mode = true;
|
760
775
|
sm->list_nest = sm->a2 - sm->a1;
|
761
776
|
fexec sm->b1;
|
762
777
|
|
763
778
|
if (sm->list_nest > prev_nest) {
|
764
|
-
|
779
|
+
int i=0;
|
780
|
+
for (i=prev_nest; i<sm->list_nest; ++i) {
|
765
781
|
g_debug(" dstack push ul");
|
766
782
|
g_debug(" print <ul>");
|
767
783
|
append_block(sm, "<ul>");
|
@@ -769,7 +785,8 @@ list := |*
|
|
769
785
|
dstack_push(sm, &BLOCK_UL);
|
770
786
|
}
|
771
787
|
} else if (sm->list_nest < prev_nest) {
|
772
|
-
|
788
|
+
int i=0;
|
789
|
+
for (i=sm->list_nest; i<prev_nest; ++i) {
|
773
790
|
if (dstack_check(sm, BLOCK_UL)) {
|
774
791
|
g_debug(" dstack pop");
|
775
792
|
g_debug(" print </ul>");
|
@@ -816,18 +833,22 @@ main := |*
|
|
816
833
|
|
817
834
|
append_newline(sm);
|
818
835
|
append_newline(sm);
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
836
|
+
if (!sm->f_strip) {
|
837
|
+
append(sm, true, "<h");
|
838
|
+
append_c(sm, header);
|
839
|
+
append_c(sm, '>');
|
840
|
+
}
|
841
|
+
append_segment(sm, false, sm->b1, sm->b2 - 1);
|
842
|
+
if (!sm->f_strip) {
|
843
|
+
append(sm, true, "</h");
|
844
|
+
append_c(sm, header);
|
845
|
+
append_c(sm, '>');
|
846
|
+
}
|
826
847
|
append_newline(sm);
|
827
848
|
append_newline(sm);
|
828
849
|
};
|
829
850
|
|
830
|
-
|
851
|
+
'[quote]' space* => {
|
831
852
|
g_debug("block [quote]");
|
832
853
|
g_debug(" push quote");
|
833
854
|
g_debug(" push p");
|
@@ -844,7 +865,7 @@ main := |*
|
|
844
865
|
fcall inline;
|
845
866
|
};
|
846
867
|
|
847
|
-
|
868
|
+
'[spoiler]' space* => {
|
848
869
|
g_debug("block [spoiler]");
|
849
870
|
g_debug(" push spoiler");
|
850
871
|
g_debug(" push p");
|
@@ -870,7 +891,7 @@ main := |*
|
|
870
891
|
}
|
871
892
|
};
|
872
893
|
|
873
|
-
|
894
|
+
'[code]' space* => {
|
874
895
|
dstack_push(sm, &BLOCK_CODE);
|
875
896
|
append_newline(sm);
|
876
897
|
append_newline(sm);
|
@@ -879,7 +900,7 @@ main := |*
|
|
879
900
|
fcall code;
|
880
901
|
};
|
881
902
|
|
882
|
-
|
903
|
+
'[expand]' space* => {
|
883
904
|
dstack_push(sm, &BLOCK_EXPAND);
|
884
905
|
dstack_push(sm, &BLOCK_P);
|
885
906
|
append_newline(sm);
|
@@ -892,22 +913,22 @@ main := |*
|
|
892
913
|
fcall inline;
|
893
914
|
};
|
894
915
|
|
895
|
-
|
916
|
+
aliased_expand space* => {
|
896
917
|
dstack_push(sm, &BLOCK_EXPAND);
|
897
918
|
dstack_push(sm, &BLOCK_P);
|
898
919
|
append_newline(sm);
|
899
920
|
append_newline(sm);
|
900
921
|
append_block(sm, "<div class=\"expandable\"><div class=\"expandable-header\">");
|
901
|
-
append(sm, "<span>");
|
922
|
+
append(sm, true, "<span>");
|
902
923
|
append_segment_html_escaped(sm, sm->a1, sm->a2);
|
903
|
-
append(sm, "</span>");
|
924
|
+
append(sm, true, "</span>");
|
904
925
|
append_block(sm, "<input type=\"button\" value=\"Show\" class=\"expandable-button\"/></div>");
|
905
926
|
append_block(sm, "<div class=\"expandable-content\">");
|
906
927
|
append_newline(sm);
|
907
928
|
fcall inline;
|
908
929
|
};
|
909
930
|
|
910
|
-
|
931
|
+
'[nodtext]' space* => {
|
911
932
|
dstack_push(sm, &BLOCK_NODTEXT);
|
912
933
|
append_newline(sm);
|
913
934
|
append_block(sm, "<p>");
|
@@ -965,7 +986,7 @@ main := |*
|
|
965
986
|
g_debug("block c: %c", fc);
|
966
987
|
fhold;
|
967
988
|
|
968
|
-
if (g_queue_is_empty(sm->dstack) || dstack_check(sm, BLOCK_QUOTE) || dstack_check(sm, BLOCK_SPOILER)) {
|
989
|
+
if (g_queue_is_empty(sm->dstack) || dstack_check(sm, BLOCK_QUOTE) || dstack_check(sm, BLOCK_SPOILER) || dstack_check(sm, BLOCK_EXPAND)) {
|
969
990
|
g_debug(" push p");
|
970
991
|
g_debug(" print <p>");
|
971
992
|
dstack_push(sm, &BLOCK_P);
|
@@ -989,8 +1010,10 @@ static inline void underscore_string(char * str, size_t len) {
|
|
989
1010
|
}
|
990
1011
|
}
|
991
1012
|
|
992
|
-
static inline void append(StateMachine * sm, const char * s) {
|
993
|
-
|
1013
|
+
static inline void append(StateMachine * sm, bool is_markup, const char * s) {
|
1014
|
+
if (!(is_markup && sm->f_strip)) {
|
1015
|
+
sm->output = g_string_append(sm->output, s);
|
1016
|
+
}
|
994
1017
|
}
|
995
1018
|
|
996
1019
|
static inline void append_newline(StateMachine * sm) {
|
@@ -1023,11 +1046,17 @@ static inline void append_c_html_escaped(StateMachine * sm, char s) {
|
|
1023
1046
|
}
|
1024
1047
|
}
|
1025
1048
|
|
1026
|
-
static inline void append_segment(StateMachine * sm, const char * a, const char * b) {
|
1027
|
-
|
1049
|
+
static inline void append_segment(StateMachine * sm, bool is_markup, const char * a, const char * b) {
|
1050
|
+
if (!(is_markup && sm->f_strip)) {
|
1051
|
+
sm->output = g_string_append_len(sm->output, a, b - a + 1);
|
1052
|
+
}
|
1028
1053
|
}
|
1029
1054
|
|
1030
1055
|
static inline void append_segment_uri_escaped(StateMachine * sm, const char * a, const char * b) {
|
1056
|
+
if (sm->f_strip) {
|
1057
|
+
return;
|
1058
|
+
}
|
1059
|
+
|
1031
1060
|
GString * segment_string = g_string_new_len(a, b - a + 1);
|
1032
1061
|
char * segment = g_uri_escape_string(segment_string->str, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH "#%?", TRUE);
|
1033
1062
|
sm->output = g_string_append(sm->output, segment);
|
@@ -1044,6 +1073,8 @@ static inline void append_segment_html_escaped(StateMachine * sm, const char * a
|
|
1044
1073
|
static inline void append_block(StateMachine * sm, const char * s) {
|
1045
1074
|
if (sm->f_inline) {
|
1046
1075
|
sm->output = g_string_append_c(sm->output, ' ');
|
1076
|
+
} else if (sm->f_strip) {
|
1077
|
+
// do nothing
|
1047
1078
|
} else {
|
1048
1079
|
sm->output = g_string_append(sm->output, s);
|
1049
1080
|
}
|
@@ -1081,22 +1112,16 @@ static inline bool dstack_check(StateMachine * sm, int expected_element) {
|
|
1081
1112
|
}
|
1082
1113
|
|
1083
1114
|
static inline bool dstack_check2(StateMachine * sm, int expected_element) {
|
1115
|
+
int * top2 = NULL;
|
1116
|
+
|
1084
1117
|
if (sm->dstack->length < 2) {
|
1085
1118
|
return false;
|
1086
1119
|
}
|
1087
1120
|
|
1088
|
-
|
1121
|
+
top2 = g_queue_peek_nth(sm->dstack, sm->dstack->length - 2);
|
1089
1122
|
return top2 && *top2 == expected_element;
|
1090
1123
|
}
|
1091
1124
|
|
1092
|
-
static void dstack_print_element(gpointer data, gpointer user_data) {
|
1093
|
-
printf("%i\n", *(int *)data);
|
1094
|
-
}
|
1095
|
-
|
1096
|
-
static void dstack_dump(StateMachine * sm) {
|
1097
|
-
g_queue_foreach(sm->dstack, dstack_print_element, NULL);
|
1098
|
-
}
|
1099
|
-
|
1100
1125
|
static void dstack_rewind(StateMachine * sm) {
|
1101
1126
|
int * element = dstack_pop(sm);
|
1102
1127
|
|
@@ -1104,95 +1129,73 @@ static void dstack_rewind(StateMachine * sm) {
|
|
1104
1129
|
return;
|
1105
1130
|
}
|
1106
1131
|
|
1107
|
-
|
1108
|
-
case BLOCK_P:
|
1132
|
+
if (*element == BLOCK_P) {
|
1109
1133
|
append_closing_p(sm);
|
1110
1134
|
append_newline(sm);
|
1111
|
-
break;
|
1112
1135
|
|
1113
|
-
|
1114
|
-
append(sm, "</span>");
|
1115
|
-
break;
|
1136
|
+
} else if (*element == INLINE_SPOILER) {
|
1137
|
+
append(sm, true, "</span>");
|
1116
1138
|
|
1117
|
-
|
1139
|
+
} else if (*element == BLOCK_SPOILER) {
|
1118
1140
|
append_block(sm, "</div>");
|
1119
|
-
break;
|
1120
1141
|
|
1121
|
-
|
1142
|
+
} else if (*element == BLOCK_QUOTE) {
|
1122
1143
|
append_block(sm, "</blockquote>");
|
1123
|
-
break;
|
1124
1144
|
|
1125
|
-
|
1145
|
+
} else if (*element == BLOCK_EXPAND) {
|
1126
1146
|
append_block(sm, "</div></div>");
|
1127
|
-
break;
|
1128
1147
|
|
1129
|
-
|
1148
|
+
} else if (*element == BLOCK_NODTEXT) {
|
1130
1149
|
append_closing_p(sm);
|
1131
1150
|
append_newline(sm);
|
1132
|
-
break;
|
1133
1151
|
|
1134
|
-
|
1152
|
+
} else if (*element == BLOCK_CODE) {
|
1135
1153
|
append_block(sm, "</pre>");
|
1136
|
-
break;
|
1137
1154
|
|
1138
|
-
|
1155
|
+
} else if (*element == BLOCK_TD) {
|
1139
1156
|
append_block(sm, "</td>");
|
1140
|
-
break;
|
1141
1157
|
|
1142
|
-
|
1143
|
-
break;
|
1158
|
+
} else if (*element == INLINE_NODTEXT) {
|
1144
1159
|
|
1145
|
-
|
1146
|
-
append(sm, "</strong>");
|
1147
|
-
break;
|
1160
|
+
} else if (*element == INLINE_B) {
|
1161
|
+
append(sm, true, "</strong>");
|
1148
1162
|
|
1149
|
-
|
1150
|
-
append(sm, "</em>");
|
1151
|
-
break;
|
1163
|
+
} else if (*element == INLINE_I) {
|
1164
|
+
append(sm, true, "</em>");
|
1152
1165
|
|
1153
|
-
|
1154
|
-
append(sm, "</u>");
|
1155
|
-
break;
|
1166
|
+
} else if (*element == INLINE_U) {
|
1167
|
+
append(sm, true, "</u>");
|
1156
1168
|
|
1157
|
-
|
1158
|
-
append(sm, "</s>");
|
1159
|
-
break;
|
1169
|
+
} else if (*element == INLINE_S) {
|
1170
|
+
append(sm, true, "</s>");
|
1160
1171
|
|
1161
|
-
|
1162
|
-
append(sm, "</span>");
|
1163
|
-
break;
|
1172
|
+
} else if (*element == INLINE_TN) {
|
1173
|
+
append(sm, true, "</span>");
|
1164
1174
|
|
1165
|
-
|
1175
|
+
} else if (*element == BLOCK_TN) {
|
1166
1176
|
append_closing_p(sm);
|
1167
1177
|
append_newline(sm);
|
1168
|
-
break;
|
1169
1178
|
|
1170
|
-
|
1179
|
+
} else if (*element == BLOCK_TABLE) {
|
1171
1180
|
append_block(sm, "</table>");
|
1172
|
-
break;
|
1173
1181
|
|
1174
|
-
|
1182
|
+
} else if (*element == BLOCK_THEAD) {
|
1175
1183
|
append_block(sm, "</thead>");
|
1176
|
-
break;
|
1177
1184
|
|
1178
|
-
|
1185
|
+
} else if (*element == BLOCK_TBODY) {
|
1179
1186
|
append_block(sm, "</tbody>");
|
1180
|
-
break;
|
1181
1187
|
|
1182
|
-
|
1188
|
+
} else if (*element == BLOCK_TR) {
|
1183
1189
|
append_block(sm, "</tr>");
|
1184
|
-
break;
|
1185
1190
|
|
1186
|
-
|
1191
|
+
} else if (*element == BLOCK_UL) {
|
1187
1192
|
append_block(sm, "</ul>");
|
1188
1193
|
append_newline(sm);
|
1189
|
-
break;
|
1190
1194
|
|
1191
|
-
|
1195
|
+
} else if (*element == BLOCK_LI) {
|
1192
1196
|
append_block(sm, "</li>");
|
1193
1197
|
append_newline(sm);
|
1194
|
-
|
1195
|
-
}
|
1198
|
+
}
|
1196
1199
|
}
|
1197
1200
|
|
1198
1201
|
static void dstack_close(StateMachine * sm) {
|
@@ -1220,6 +1223,7 @@ static inline bool is_boundary_c(char c) {
|
|
1220
1223
|
}
|
1221
1224
|
|
1222
1225
|
static void init_machine(StateMachine * sm, VALUE input) {
|
1226
|
+
size_t output_length = 0;
|
1223
1227
|
sm->p = RSTRING_PTR(input);
|
1224
1228
|
sm->pe = sm->p + RSTRING_LEN(input);
|
1225
1229
|
sm->eof = sm->pe;
|
@@ -1228,7 +1232,7 @@ static void init_machine(StateMachine * sm, VALUE input) {
|
|
1228
1232
|
sm->cs = 0;
|
1229
1233
|
sm->act = 0;
|
1230
1234
|
sm->top = 0;
|
1231
|
-
|
1235
|
+
output_length = RSTRING_LEN(input);
|
1232
1236
|
if (output_length < (INT16_MAX / 2)) {
|
1233
1237
|
output_length *= 2;
|
1234
1238
|
}
|
@@ -1238,6 +1242,7 @@ static void init_machine(StateMachine * sm, VALUE input) {
|
|
1238
1242
|
sm->b1 = NULL;
|
1239
1243
|
sm->b2 = NULL;
|
1240
1244
|
sm->f_inline = false;
|
1245
|
+
sm->f_strip = false;
|
1241
1246
|
sm->stack = g_array_sized_new(FALSE, TRUE, sizeof(int), 16);
|
1242
1247
|
sm->dstack = g_queue_new();
|
1243
1248
|
sm->list_nest = 0;
|
@@ -1252,24 +1257,35 @@ static void free_machine(StateMachine * sm) {
|
|
1252
1257
|
}
|
1253
1258
|
|
1254
1259
|
static VALUE parse(int argc, VALUE * argv, VALUE self) {
|
1260
|
+
VALUE input;
|
1261
|
+
VALUE options;
|
1262
|
+
VALUE opt_inline;
|
1263
|
+
VALUE opt_strip;
|
1264
|
+
VALUE ret;
|
1265
|
+
StateMachine * sm = NULL;
|
1266
|
+
|
1255
1267
|
g_debug("start\n");
|
1256
1268
|
|
1257
1269
|
if (argc == 0) {
|
1258
1270
|
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
|
1259
1271
|
}
|
1260
1272
|
|
1261
|
-
|
1273
|
+
input = argv[0];
|
1262
1274
|
|
1263
|
-
|
1275
|
+
sm = (StateMachine *)g_malloc0(sizeof(StateMachine));
|
1264
1276
|
input = rb_str_cat(input, "\0", 1);
|
1265
1277
|
init_machine(sm, input);
|
1266
1278
|
|
1267
1279
|
if (argc > 1) {
|
1268
|
-
|
1280
|
+
options = argv[1];
|
1269
1281
|
|
1270
1282
|
if (!NIL_P(options)) {
|
1271
|
-
|
1283
|
+
opt_strip = rb_hash_aref(options, ID2SYM(rb_intern("strip")));
|
1284
|
+
if (RTEST(opt_strip)) {
|
1285
|
+
sm->f_strip = true;
|
1286
|
+
}
|
1272
1287
|
|
1288
|
+
opt_inline = rb_hash_aref(options, ID2SYM(rb_intern("inline")));
|
1273
1289
|
if (RTEST(opt_inline)) {
|
1274
1290
|
sm->f_inline = true;
|
1275
1291
|
}
|
@@ -1281,7 +1297,7 @@ static VALUE parse(int argc, VALUE * argv, VALUE self) {
|
|
1281
1297
|
|
1282
1298
|
dstack_close(sm);
|
1283
1299
|
|
1284
|
-
|
1300
|
+
ret = rb_str_new(sm->output->str, sm->output->len);
|
1285
1301
|
|
1286
1302
|
free_machine(sm);
|
1287
1303
|
|