dtext_rb 1.0.0 → 1.0.2
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/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
|
|