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