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.
data/ext/dtext/dtext.rl CHANGED
@@ -9,7 +9,7 @@
9
9
  #include <glib.h>
10
10
 
11
11
  typedef struct StateMachine {
12
- int top;
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 int MAX_STACK_DEPTH = 512;
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, "\">post #");
145
- append_segment(sm, sm->a1, sm->a2 - 1);
146
- append(sm, "</a>");
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, "\">forum #");
153
- append_segment(sm, sm->a1, sm->a2 - 1);
154
- append(sm, "</a>");
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, "\">topic #");
161
- append_segment(sm, sm->a1, sm->a2 - 1);
162
- append(sm, "</a>");
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, "\">topic #");
171
- append_segment(sm, sm->a1, sm->a2 - 1);
172
- append(sm, "/p");
173
- append_segment(sm, sm->b1, sm->b2 - 1);
174
- append(sm, "</a>");
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, "\">comment #");
181
- append_segment(sm, sm->a1, sm->a2 - 1);
182
- append(sm, "</a>");
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, "\">pool #");
189
- append_segment(sm, sm->a1, sm->a2 - 1);
190
- append(sm, "</a>");
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, "\">user #");
197
- append_segment(sm, sm->a1, sm->a2 - 1);
198
- append(sm, "</a>");
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, "\">artist #");
205
- append_segment(sm, sm->a1, sm->a2 - 1);
206
- append(sm, "</a>");
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, "\">issue #");
213
- append_segment(sm, sm->a1, sm->a2 - 1);
214
- append(sm, "</a>");
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, "\">pixiv #");
221
- append_segment(sm, sm->a1, sm->a2 - 1);
222
- append(sm, "</a>");
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, "\">pixiv #");
231
- append_segment(sm, sm->a1, sm->a2 - 1);
232
- append(sm, "/p");
233
- append_segment(sm, sm->b1, sm->b2 - 1);
234
- append(sm, "</a>");
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
- append_segment(sm, sm->ts, sm->te - 1);
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
- append(sm, "[/tn]");
458
+ append_block(sm, "[/tn]");
445
459
  }
446
460
  };
447
461
 
@@ -453,7 +467,7 @@ inline := |*
453
467
  fret;
454
468
  };
455
469
 
456
- (space* '[quote]') => {
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->p - 6;
482
+ fexec sm->ts;
469
483
  fret;
470
484
  };
471
485
 
472
- (space* '[/quote]') => {
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
- append(sm, "[/quote]");
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
- (space* '[/spoiler]') => {
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
- append(sm, "[/spoiler]");
530
+ append_block(sm, "[/spoiler]");
517
531
  }
518
532
  };
519
533
 
520
- (space* '[expand]' space*) => {
534
+ '[expand]' => {
535
+ g_debug("inline [expand]");
521
536
  dstack_rewind(sm);
522
- fexec(sm->p - 8);
537
+ fexec(sm->p - 7);
523
538
  fret;
524
539
  };
525
540
 
526
- (space* '[/expand]') => {
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
- append(sm, "[/expand]");
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
- append(sm, "[/th]");
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
- append(sm, "[/td]");
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
- for (int i=prev_nest; i<sm->list_nest; ++i) {
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
- for (int i=sm->list_nest; i<prev_nest; ++i) {
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
- append(sm, "<h");
820
- append_c(sm, header);
821
- append_c(sm, '>');
822
- append_segment(sm, sm->b1, sm->b2 - 1);
823
- append(sm, "</h");
824
- append_c(sm, header);
825
- append(sm, ">");
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
- ('[quote]' space*) => {
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
- ('[spoiler]' space*) => {
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
- ('[code]' space*) => {
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
- ('[expand]' space*) => {
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
- (aliased_expand space*) => {
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
- ('[nodtext]' space*) => {
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
- sm->output = g_string_append(sm->output, s);
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
- sm->output = g_string_append_len(sm->output, a, b - a + 1);
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
- int * top2 = g_queue_peek_nth(sm->dstack, sm->dstack->length - 2);
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
- switch (*element) {
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
- case INLINE_SPOILER:
1114
- append(sm, "</span>");
1115
- break;
1136
+ } else if (*element == INLINE_SPOILER) {
1137
+ append(sm, true, "</span>");
1116
1138
 
1117
- case BLOCK_SPOILER:
1139
+ } else if (*element == BLOCK_SPOILER) {
1118
1140
  append_block(sm, "</div>");
1119
- break;
1120
1141
 
1121
- case BLOCK_QUOTE:
1142
+ } else if (*element == BLOCK_QUOTE) {
1122
1143
  append_block(sm, "</blockquote>");
1123
- break;
1124
1144
 
1125
- case BLOCK_EXPAND:
1145
+ } else if (*element == BLOCK_EXPAND) {
1126
1146
  append_block(sm, "</div></div>");
1127
- break;
1128
1147
 
1129
- case BLOCK_NODTEXT:
1148
+ } else if (*element == BLOCK_NODTEXT) {
1130
1149
  append_closing_p(sm);
1131
1150
  append_newline(sm);
1132
- break;
1133
1151
 
1134
- case BLOCK_CODE:
1152
+ } else if (*element == BLOCK_CODE) {
1135
1153
  append_block(sm, "</pre>");
1136
- break;
1137
1154
 
1138
- case BLOCK_TD:
1155
+ } else if (*element == BLOCK_TD) {
1139
1156
  append_block(sm, "</td>");
1140
- break;
1141
1157
 
1142
- case INLINE_NODTEXT:
1143
- break;
1158
+ } else if (*element == INLINE_NODTEXT) {
1144
1159
 
1145
- case INLINE_B:
1146
- append(sm, "</strong>");
1147
- break;
1160
+ } else if (*element == INLINE_B) {
1161
+ append(sm, true, "</strong>");
1148
1162
 
1149
- case INLINE_I:
1150
- append(sm, "</em>");
1151
- break;
1163
+ } else if (*element == INLINE_I) {
1164
+ append(sm, true, "</em>");
1152
1165
 
1153
- case INLINE_U:
1154
- append(sm, "</u>");
1155
- break;
1166
+ } else if (*element == INLINE_U) {
1167
+ append(sm, true, "</u>");
1156
1168
 
1157
- case INLINE_S:
1158
- append(sm, "</s>");
1159
- break;
1169
+ } else if (*element == INLINE_S) {
1170
+ append(sm, true, "</s>");
1160
1171
 
1161
- case INLINE_TN:
1162
- append(sm, "</span>");
1163
- break;
1172
+ } else if (*element == INLINE_TN) {
1173
+ append(sm, true, "</span>");
1164
1174
 
1165
- case BLOCK_TN:
1175
+ } else if (*element == BLOCK_TN) {
1166
1176
  append_closing_p(sm);
1167
1177
  append_newline(sm);
1168
- break;
1169
1178
 
1170
- case BLOCK_TABLE:
1179
+ } else if (*element == BLOCK_TABLE) {
1171
1180
  append_block(sm, "</table>");
1172
- break;
1173
1181
 
1174
- case BLOCK_THEAD:
1182
+ } else if (*element == BLOCK_THEAD) {
1175
1183
  append_block(sm, "</thead>");
1176
- break;
1177
1184
 
1178
- case BLOCK_TBODY:
1185
+ } else if (*element == BLOCK_TBODY) {
1179
1186
  append_block(sm, "</tbody>");
1180
- break;
1181
1187
 
1182
- case BLOCK_TR:
1188
+ } else if (*element == BLOCK_TR) {
1183
1189
  append_block(sm, "</tr>");
1184
- break;
1185
1190
 
1186
- case BLOCK_UL:
1191
+ } else if (*element == BLOCK_UL) {
1187
1192
  append_block(sm, "</ul>");
1188
1193
  append_newline(sm);
1189
- break;
1190
1194
 
1191
- case BLOCK_LI:
1195
+ } else if (*element == BLOCK_LI) {
1192
1196
  append_block(sm, "</li>");
1193
1197
  append_newline(sm);
1194
- break;
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
- size_t output_length = RSTRING_LEN(input);
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
- VALUE input = argv[0];
1273
+ input = argv[0];
1262
1274
 
1263
- StateMachine * sm = (StateMachine *)g_malloc0(sizeof(StateMachine));
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
- VALUE options = argv[1];
1280
+ options = argv[1];
1269
1281
 
1270
1282
  if (!NIL_P(options)) {
1271
- VALUE opt_inline = rb_hash_aref(options, ID2SYM(rb_intern("inline")));
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
- VALUE ret = rb_str_new(sm->output->str, sm->output->len);
1300
+ ret = rb_str_new(sm->output->str, sm->output->len);
1285
1301
 
1286
1302
  free_machine(sm);
1287
1303