dtext_rb 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/dtext/dtext.rl CHANGED
@@ -13,6 +13,7 @@ typedef struct StateMachine {
13
13
  int cs;
14
14
  int act;
15
15
  const char * p;
16
+ const char * pb;
16
17
  const char * pe;
17
18
  const char * eof;
18
19
  const char * ts;
@@ -25,6 +26,7 @@ typedef struct StateMachine {
25
26
  bool f_inline;
26
27
  bool f_strip;
27
28
  bool list_mode;
29
+ bool header_mode;
28
30
  GString * output;
29
31
  GArray * stack;
30
32
  GQueue * dstack;
@@ -57,6 +59,12 @@ static const int BLOCK_TR = 19;
57
59
  static const int BLOCK_UL = 20;
58
60
  static const int BLOCK_LI = 21;
59
61
  static const int BLOCK_TH = 22;
62
+ static const int BLOCK_H1 = 23;
63
+ static const int BLOCK_H2 = 24;
64
+ static const int BLOCK_H3 = 25;
65
+ static const int BLOCK_H4 = 26;
66
+ static const int BLOCK_H5 = 27;
67
+ static const int BLOCK_H6 = 28;
60
68
 
61
69
  %%{
62
70
  machine dtext;
@@ -100,9 +108,9 @@ action mark_b2 {
100
108
  sm->b2 = sm->p;
101
109
  }
102
110
 
103
- newline = '\r\n' | '\r' | '\n';
111
+ newline = '\r\n' | '\n';
104
112
 
105
- nonnewline = any - (newline | '\0');
113
+ nonnewline = any - (newline | '\0' | '\r');
106
114
  nonquote = ^'"';
107
115
  nonbracket = ^']';
108
116
  nonpipe = ^'|';
@@ -121,20 +129,20 @@ aliased_wiki_link = '[[' nonpipebracket+ >mark_a1 %mark_a2 '|' nonbracket+ >mark
121
129
 
122
130
  post_link = '{{' noncurly+ >mark_a1 %mark_a2 '}}';
123
131
 
124
- post_id = 'post #' digit+ >mark_a1 %mark_a2;
125
- forum_post_id = 'forum #' digit+ >mark_a1 %mark_a2;
126
- forum_topic_id = 'topic #' digit+ >mark_a1 %mark_a2;
127
- forum_topic_paged_id = 'topic #' digit+ >mark_a1 %mark_a2 '/p' digit+ >mark_b1 %mark_b2;
128
- comment_id = 'comment #' digit+ >mark_a1 %mark_a2;
129
- pool_id = 'pool #' digit+ >mark_a1 %mark_a2;
130
- user_id = 'user #' digit+ >mark_a1 %mark_a2;
131
- artist_id = 'artist #' digit+ >mark_a1 %mark_a2;
132
- github_issue_id = 'issue #' digit+ >mark_a1 %mark_a2;
133
- pixiv_id = 'pixiv #' digit+ >mark_a1 %mark_a2;
134
- pixiv_paged_id = 'pixiv #' digit+ >mark_a1 %mark_a2 '/p' digit+ >mark_b1 %mark_b2;
132
+ post_id = 'post #'i digit+ >mark_a1 %mark_a2;
133
+ forum_post_id = 'forum #'i digit+ >mark_a1 %mark_a2;
134
+ forum_topic_id = 'topic #'i digit+ >mark_a1 %mark_a2;
135
+ forum_topic_paged_id = 'topic #'i digit+ >mark_a1 %mark_a2 '/p' digit+ >mark_b1 %mark_b2;
136
+ comment_id = 'comment #'i digit+ >mark_a1 %mark_a2;
137
+ pool_id = 'pool #'i digit+ >mark_a1 %mark_a2;
138
+ user_id = 'user #'i digit+ >mark_a1 %mark_a2;
139
+ artist_id = 'artist #'i digit+ >mark_a1 %mark_a2;
140
+ github_issue_id = 'issue #'i digit+ >mark_a1 %mark_a2;
141
+ pixiv_id = 'pixiv #'i digit+ >mark_a1 %mark_a2;
142
+ pixiv_paged_id = 'pixiv #'i digit+ >mark_a1 %mark_a2 '/p' digit+ >mark_b1 %mark_b2;
135
143
 
136
144
  ws = ' ' | '\t';
137
- header = 'h' [123456] >mark_a1 %mark_a2 '.' ws* nonnewline+ >mark_b1 %mark_b2;
145
+ header = 'h' [123456] >mark_a1 %mark_a2 '.' ws*;
138
146
  aliased_expand = '[expand=' (nonbracket+ >mark_a1 %mark_a2) ']';
139
147
 
140
148
  list_item = '*'+ >mark_a1 %mark_a2 ws+ nonnewline+ >mark_b1 %mark_b2;
@@ -307,7 +315,7 @@ inline := |*
307
315
  }
308
316
 
309
317
  append(sm, true, "<a href=\"");
310
- append_segment_uri_escaped(sm, sm->b1, sm->b2 - sm->d);
318
+ append_segment_html_escaped(sm, sm->b1, sm->b2 - sm->d);
311
319
  append(sm, true, "\">");
312
320
  append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
313
321
  append(sm, true, "</a>");
@@ -319,7 +327,7 @@ inline := |*
319
327
 
320
328
  bracketed_textile_link => {
321
329
  append(sm, true, "<a href=\"");
322
- append_segment_uri_escaped(sm, sm->b1, sm->b2 - 1);
330
+ append_segment_html_escaped(sm, sm->b1, sm->b2 - 1);
323
331
  append(sm, true, "\">");
324
332
  append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
325
333
  append(sm, true, "</a>");
@@ -335,7 +343,7 @@ inline := |*
335
343
  }
336
344
 
337
345
  append(sm, true, "<a href=\"");
338
- append_segment_uri_escaped(sm, sm->ts, sm->te - sm->d);
346
+ append_segment_html_escaped(sm, sm->ts, sm->te - sm->d);
339
347
  append(sm, true, "\">");
340
348
  append_segment_html_escaped(sm, sm->ts, sm->te - sm->d);
341
349
  append(sm, true, "</a>");
@@ -371,17 +379,20 @@ inline := |*
371
379
  }
372
380
  };
373
381
 
374
- list_item => {
382
+ newline list_item => {
375
383
  g_debug("inline list");
376
384
 
377
- if (dstack_check(sm, BLOCK_P)) {
385
+ if (dstack_check(sm, BLOCK_LI)) {
386
+ g_debug(" rewind li");
387
+ dstack_rewind(sm);
388
+ } else if (dstack_check(sm, BLOCK_P)) {
378
389
  g_debug(" rewind p");
379
390
  dstack_rewind(sm);
380
391
  }
381
392
 
382
- g_debug(" call list");
383
- fexec sm->ts;
384
- fcall list;
393
+ g_debug(" next list");
394
+ fexec sm->ts + 1;
395
+ fnext list;
385
396
  };
386
397
 
387
398
  '[b]' => {
@@ -446,10 +457,10 @@ inline := |*
446
457
  };
447
458
 
448
459
  '[/tn]' => {
460
+ dstack_close_before_block(sm);
461
+
449
462
  if (dstack_check(sm, BLOCK_TN)) {
450
463
  dstack_pop(sm);
451
- append_closing_p(sm);
452
- append_newline(sm);
453
464
  fret;
454
465
  } else if (dstack_check(sm, INLINE_TN)) {
455
466
  dstack_pop(sm);
@@ -469,25 +480,17 @@ inline := |*
469
480
 
470
481
  '[quote]' => {
471
482
  g_debug("inline [quote]");
472
-
473
- if (dstack_check(sm, BLOCK_P)) {
474
- g_debug(" pop dstack");
475
- g_debug(" print </p>");
476
-
477
- dstack_pop(sm);
478
- append_closing_p(sm);
479
- append_newline(sm);
480
- }
481
-
483
+ dstack_close_before_block(sm);
482
484
  fexec sm->ts;
483
485
  fret;
484
486
  };
485
487
 
486
488
  '[/quote]' space* => {
487
489
  g_debug("inline [/quote]");
490
+ dstack_close_before_block(sm);
488
491
 
489
- if (dstack_check(sm, BLOCK_P)) {
490
- dstack_rewind(sm);
492
+ if (dstack_check(sm, BLOCK_LI)) {
493
+ dstack_close_list(sm);
491
494
  }
492
495
 
493
496
  if (dstack_check(sm, BLOCK_QUOTE)) {
@@ -507,24 +510,19 @@ inline := |*
507
510
 
508
511
  '[/spoiler]' => {
509
512
  g_debug("inline [/spoiler]");
513
+ dstack_close_before_block(sm);
510
514
 
511
515
  if (dstack_check(sm, INLINE_SPOILER)) {
512
516
  g_debug(" pop dstack");
513
517
  g_debug(" print </span>");
514
518
  dstack_pop(sm);
515
519
  append(sm, true, "</span>");
516
- } else if (dstack_check(sm, BLOCK_P) && dstack_check2(sm, BLOCK_SPOILER)) {
520
+ } else if (dstack_check(sm, BLOCK_SPOILER)) {
517
521
  g_debug(" pop dstack");
518
- g_debug(" print </p></div>");
522
+ g_debug(" print </div>");
519
523
  g_debug(" return");
520
524
  dstack_pop(sm);
521
- dstack_pop(sm);
522
- append_newline(sm);
523
- append_closing_p(sm);
524
525
  append_block(sm, "</div>");
525
- append_newline(sm);
526
- append_newline(sm);
527
-
528
526
  fret;
529
527
  } else {
530
528
  append_block(sm, "[/spoiler]");
@@ -539,17 +537,10 @@ inline := |*
539
537
  };
540
538
 
541
539
  '[/expand]' => {
542
- if (dstack_check(sm, BLOCK_P)) {
543
- append_closing_p(sm);
544
- append_newline(sm);
545
- dstack_pop(sm);
546
- }
540
+ dstack_close_before_block(sm);
547
541
 
548
542
  if (dstack_check(sm, BLOCK_EXPAND)) {
549
- append_newline(sm);
550
543
  append_block(sm, "</div></div>");
551
- append_newline(sm);
552
- append_newline(sm);
553
544
  dstack_pop(sm);
554
545
  fret;
555
546
  } else {
@@ -565,9 +556,7 @@ inline := |*
565
556
  '[/th]' => {
566
557
  if (dstack_check(sm, BLOCK_TH)) {
567
558
  dstack_pop(sm);
568
- append_newline(sm);
569
559
  append_block(sm, "</th>");
570
- append_newline(sm);
571
560
  fret;
572
561
  } else {
573
562
  append_block(sm, "[/th]");
@@ -577,9 +566,7 @@ inline := |*
577
566
  '[/td]' => {
578
567
  if (dstack_check(sm, BLOCK_TD)) {
579
568
  dstack_pop(sm);
580
- append_newline(sm);
581
569
  append_block(sm, "</td>");
582
- append_newline(sm);
583
570
  fret;
584
571
  } else {
585
572
  append_block(sm, "[/td]");
@@ -599,10 +586,7 @@ inline := |*
599
586
  g_debug(" return");
600
587
 
601
588
  if (sm->list_mode) {
602
- if (dstack_check(sm, BLOCK_LI)) {
603
- dstack_rewind(sm);
604
- }
605
-
589
+ dstack_close_list(sm);
606
590
  sm->list_mode = false;
607
591
  }
608
592
 
@@ -613,16 +597,21 @@ inline := |*
613
597
  newline => {
614
598
  g_debug("inline newline");
615
599
 
616
- if (sm->list_mode && (*(sm->p+1) == '*') && dstack_check(sm, BLOCK_LI)) {
600
+ if (sm->header_mode) {
601
+ sm->header_mode = false;
617
602
  dstack_rewind(sm);
603
+ fret;
618
604
  } else {
619
605
  append(sm, true, "<br>");
620
- append_newline(sm);
621
606
  }
622
607
  };
623
608
 
609
+ '\r' => {
610
+ append_c(sm, ' ');
611
+ };
612
+
624
613
  any => {
625
- g_debug("inline c: %c", fc);
614
+ g_debug("inline char: %c", fc);
626
615
  append_c_html_escaped(sm, fc);
627
616
  };
628
617
  *|;
@@ -651,10 +640,7 @@ nodtext := |*
651
640
  '[/nodtext]' => {
652
641
  if (dstack_check(sm, BLOCK_NODTEXT)) {
653
642
  dstack_pop(sm);
654
- append_newline(sm);
655
- append_closing_p(sm);
656
- append_newline(sm);
657
- append_newline(sm);
643
+ append_block(sm, "</p>");
658
644
  fret;
659
645
  } else if (dstack_check(sm, INLINE_NODTEXT)) {
660
646
  dstack_pop(sm);
@@ -677,17 +663,13 @@ nodtext := |*
677
663
  table := |*
678
664
  '[thead]' => {
679
665
  dstack_push(sm, &BLOCK_THEAD);
680
- append_newline(sm);
681
666
  append_block(sm, "<thead>");
682
- append_newline(sm);
683
667
  };
684
668
 
685
669
  '[/thead]' => {
686
670
  if (dstack_check(sm, BLOCK_THEAD)) {
687
671
  dstack_pop(sm);
688
- append_newline(sm);
689
672
  append_block(sm, "</thead>");
690
- append_newline(sm);
691
673
  } else {
692
674
  append(sm, true, "[/thead]");
693
675
  }
@@ -695,17 +677,13 @@ table := |*
695
677
 
696
678
  '[tbody]' => {
697
679
  dstack_push(sm, &BLOCK_TBODY);
698
- append_newline(sm);
699
680
  append_block(sm, "<tbody>");
700
- append_newline(sm);
701
681
  };
702
682
 
703
683
  '[/tbody]' => {
704
684
  if (dstack_check(sm, BLOCK_TBODY)) {
705
685
  dstack_pop(sm);
706
- append_newline(sm);
707
686
  append_block(sm, "</tbody>");
708
- append_newline(sm);
709
687
  } else {
710
688
  append(sm, true, "[/tbody]");
711
689
  }
@@ -713,25 +691,19 @@ table := |*
713
691
 
714
692
  '[th]' => {
715
693
  dstack_push(sm, &BLOCK_TH);
716
- append_newline(sm);
717
694
  append_block(sm, "<th>");
718
- append_newline(sm);
719
695
  fcall inline;
720
696
  };
721
697
 
722
698
  '[tr]' => {
723
699
  dstack_push(sm, &BLOCK_TR);
724
- append_newline(sm);
725
700
  append_block(sm, "<tr>");
726
- append_newline(sm);
727
701
  };
728
702
 
729
703
  '[/tr]' => {
730
704
  if (dstack_check(sm, BLOCK_TR)) {
731
705
  dstack_pop(sm);
732
- append_newline(sm);
733
706
  append_block(sm, "</tr>");
734
- append_newline(sm);
735
707
  } else {
736
708
  append(sm, true, "[/tr]");
737
709
  }
@@ -739,19 +711,14 @@ table := |*
739
711
 
740
712
  '[td]' => {
741
713
  dstack_push(sm, &BLOCK_TD);
742
- append_newline(sm);
743
714
  append_block(sm, "<td>");
744
- append_newline(sm);
745
715
  fcall inline;
746
716
  };
747
717
 
748
718
  '[/table]' => {
749
719
  if (dstack_check(sm, BLOCK_TABLE)) {
750
720
  dstack_pop(sm);
751
- append_newline(sm);
752
721
  append_block(sm, "</table>");
753
- append_newline(sm);
754
- append_newline(sm);
755
722
  fret;
756
723
  } else {
757
724
  append(sm, true, "[/table]");
@@ -769,8 +736,8 @@ table := |*
769
736
  list := |*
770
737
  list_item => {
771
738
  int prev_nest = sm->list_nest;
739
+ append_closing_p_if(sm);
772
740
  g_debug("list start");
773
-
774
741
  sm->list_mode = true;
775
742
  sm->list_nest = sm->a2 - sm->a1;
776
743
  fexec sm->b1;
@@ -781,7 +748,6 @@ list := |*
781
748
  g_debug(" dstack push ul");
782
749
  g_debug(" print <ul>");
783
750
  append_block(sm, "<ul>");
784
- append_newline(sm);
785
751
  dstack_push(sm, &BLOCK_UL);
786
752
  }
787
753
  } else if (sm->list_nest < prev_nest) {
@@ -792,7 +758,6 @@ list := |*
792
758
  g_debug(" print </ul>");
793
759
  dstack_pop(sm);
794
760
  append_block(sm, "</ul>");
795
- append_newline(sm);
796
761
  }
797
762
  }
798
763
  }
@@ -809,7 +774,7 @@ list := |*
809
774
 
810
775
  # exit list
811
776
  (newline{2,} | '\0') => {
812
- dstack_rewind(sm);
777
+ dstack_close_list(sm);
813
778
  fexec sm->ts;
814
779
  fret;
815
780
  };
@@ -831,135 +796,128 @@ main := |*
831
796
  header = '6';
832
797
  }
833
798
 
834
- append_newline(sm);
835
- append_newline(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
799
  if (!sm->f_strip) {
843
- append(sm, true, "</h");
844
- append_c(sm, header);
845
- append_c(sm, '>');
800
+ switch (header) {
801
+ case '1':
802
+ dstack_push(sm, &BLOCK_H1);
803
+ append_block(sm, "<h1>");
804
+ break;
805
+
806
+ case '2':
807
+ dstack_push(sm, &BLOCK_H2);
808
+ append_block(sm, "<h2>");
809
+ break;
810
+
811
+ case '3':
812
+ dstack_push(sm, &BLOCK_H3);
813
+ append_block(sm, "<h3>");
814
+ break;
815
+
816
+ case '4':
817
+ dstack_push(sm, &BLOCK_H4);
818
+ append_block(sm, "<h4>");
819
+ break;
820
+
821
+ case '5':
822
+ dstack_push(sm, &BLOCK_H5);
823
+ append_block(sm, "<h5>");
824
+ break;
825
+
826
+ case '6':
827
+ dstack_push(sm, &BLOCK_H6);
828
+ append_block(sm, "<h6>");
829
+ break;
830
+ }
846
831
  }
847
- append_newline(sm);
848
- append_newline(sm);
832
+
833
+ sm->header_mode = true;
834
+ fcall inline;
849
835
  };
850
836
 
851
837
  '[quote]' space* => {
852
838
  g_debug("block [quote]");
853
839
  g_debug(" push quote");
854
- g_debug(" push p");
855
840
  g_debug(" print <blockquote>");
856
- g_debug(" print <p>");
857
- g_debug(" call inline");
858
-
841
+ dstack_close_before_block(sm);
859
842
  dstack_push(sm, &BLOCK_QUOTE);
860
- dstack_push(sm, &BLOCK_P);
861
- append_newline(sm);
862
- append_newline(sm);
863
- append_block(sm, "<blockquote><p>");
864
- append_newline(sm);
865
- fcall inline;
843
+ append_block(sm, "<blockquote>");
866
844
  };
867
845
 
868
846
  '[spoiler]' space* => {
869
847
  g_debug("block [spoiler]");
870
848
  g_debug(" push spoiler");
871
- g_debug(" push p");
872
849
  g_debug(" print <div>");
873
- g_debug(" print <p>");
874
- g_debug(" call inline");
850
+ dstack_close_before_block(sm);
875
851
  dstack_push(sm, &BLOCK_SPOILER);
876
- dstack_push(sm, &BLOCK_P);
877
- append_newline(sm);
878
- append_newline(sm);
879
- append_block(sm, "<div class=\"spoiler\"><p>");
880
- append_newline(sm);
881
- fcall inline;
852
+ append_block(sm, "<div class=\"spoiler\">");
882
853
  };
883
854
 
884
855
  '[/spoiler]' => {
885
- if (dstack_check(sm, BLOCK_P)) {
886
- dstack_rewind(sm);
887
- }
888
-
856
+ g_debug("block [/spoiler]");
857
+ dstack_close_before_block(sm);
889
858
  if (dstack_check(sm, BLOCK_SPOILER)) {
859
+ g_debug(" rewind");
890
860
  dstack_rewind(sm);
891
861
  }
892
862
  };
893
863
 
894
864
  '[code]' space* => {
865
+ g_debug("block [code]");
866
+ dstack_close_before_block(sm);
895
867
  dstack_push(sm, &BLOCK_CODE);
896
- append_newline(sm);
897
- append_newline(sm);
898
868
  append_block(sm, "<pre>");
899
- append_newline(sm);
900
869
  fcall code;
901
870
  };
902
871
 
903
872
  '[expand]' space* => {
873
+ g_debug("block [expand]");
874
+ dstack_close_before_block(sm);
904
875
  dstack_push(sm, &BLOCK_EXPAND);
905
- dstack_push(sm, &BLOCK_P);
906
- append_newline(sm);
907
- append_newline(sm);
908
876
  append_block(sm, "<div class=\"expandable\"><div class=\"expandable-header\">");
909
877
  append_block(sm, "<input type=\"button\" value=\"Show\" class=\"expandable-button\"/></div>");
910
878
  append_block(sm, "<div class=\"expandable-content\">");
911
- append_block(sm, "<p>");
912
- append_newline(sm);
913
- fcall inline;
914
879
  };
915
880
 
916
881
  aliased_expand space* => {
882
+ g_debug("block [expand=]");
883
+ dstack_close_before_block(sm);
917
884
  dstack_push(sm, &BLOCK_EXPAND);
918
- dstack_push(sm, &BLOCK_P);
919
- append_newline(sm);
920
- append_newline(sm);
921
885
  append_block(sm, "<div class=\"expandable\"><div class=\"expandable-header\">");
922
886
  append(sm, true, "<span>");
923
- append_segment_html_escaped(sm, sm->a1, sm->a2);
887
+ append_segment_html_escaped(sm, sm->a1, sm->a2 - 1);
924
888
  append(sm, true, "</span>");
925
889
  append_block(sm, "<input type=\"button\" value=\"Show\" class=\"expandable-button\"/></div>");
926
890
  append_block(sm, "<div class=\"expandable-content\">");
927
- append_newline(sm);
928
- fcall inline;
929
891
  };
930
892
 
931
893
  '[nodtext]' space* => {
894
+ g_debug("block [nodtext]");
895
+ dstack_close_before_block(sm);
932
896
  dstack_push(sm, &BLOCK_NODTEXT);
933
- append_newline(sm);
897
+ dstack_push(sm, &BLOCK_P);
934
898
  append_block(sm, "<p>");
935
899
  fcall nodtext;
936
900
  };
937
901
 
938
902
  '[table]' => {
903
+ dstack_close_before_block(sm);
939
904
  dstack_push(sm, &BLOCK_TABLE);
940
- append_newline(sm);
941
- append_newline(sm);
942
905
  append_block(sm, "<table class=\"striped\">");
943
906
  fcall table;
944
907
  };
945
908
 
946
909
  '[tn]' => {
947
910
  dstack_push(sm, &BLOCK_TN);
948
- append_newline(sm);
949
- append_newline(sm);
950
911
  append_block(sm, "<p class=\"tn\">");
951
912
  fcall inline;
952
913
  };
953
914
 
954
915
  list_item => {
955
- g_debug("inline list");
916
+ g_debug("block list");
917
+ g_debug(" call list");
956
918
  sm->list_nest = 0;
957
919
  sm->list_mode = true;
958
- if (dstack_check(sm, BLOCK_P)) {
959
- g_debug(" pop dstack");
960
- dstack_rewind(sm);
961
- }
962
- g_debug(" call list");
920
+ append_closing_p_if(sm);
963
921
  fexec sm->ts;
964
922
  fcall list;
965
923
  };
@@ -972,9 +930,12 @@ main := |*
972
930
 
973
931
  newline{2,} => {
974
932
  g_debug("block newline2");
975
- if (dstack_check(sm, BLOCK_P)) {
976
- g_debug(" pop p");
933
+
934
+ if (sm->header_mode) {
935
+ sm->header_mode = false;
977
936
  dstack_rewind(sm);
937
+ } else {
938
+ dstack_close_before_block(sm);
978
939
  }
979
940
  };
980
941
 
@@ -983,14 +944,13 @@ main := |*
983
944
  };
984
945
 
985
946
  any => {
986
- g_debug("block c: %c", fc);
947
+ g_debug("block char: %c", fc);
987
948
  fhold;
988
949
 
989
950
  if (g_queue_is_empty(sm->dstack) || dstack_check(sm, BLOCK_QUOTE) || dstack_check(sm, BLOCK_SPOILER) || dstack_check(sm, BLOCK_EXPAND)) {
990
951
  g_debug(" push p");
991
952
  g_debug(" print <p>");
992
953
  dstack_push(sm, &BLOCK_P);
993
- append_newline(sm);
994
954
  append_block(sm, "<p>");
995
955
  }
996
956
 
@@ -1010,18 +970,44 @@ static inline void underscore_string(char * str, size_t len) {
1010
970
  }
1011
971
  }
1012
972
 
973
+ static inline void dstack_push(StateMachine * sm, const int * element) {
974
+ g_queue_push_tail(sm->dstack, (gpointer)element);
975
+ }
976
+
977
+ static inline int * dstack_pop(StateMachine * sm) {
978
+ return g_queue_pop_tail(sm->dstack);
979
+ }
980
+
981
+ static inline int * dstack_peek(StateMachine * sm) {
982
+ return g_queue_peek_tail(sm->dstack);
983
+ }
984
+
985
+ static inline bool dstack_search(StateMachine * sm, const int * element) {
986
+ return g_queue_find(sm->dstack, (gconstpointer)element);
987
+ }
988
+
989
+ static inline bool dstack_check(StateMachine * sm, int expected_element) {
990
+ int * top = dstack_peek(sm);
991
+ return top && *top == expected_element;
992
+ }
993
+
994
+ static inline bool dstack_check2(StateMachine * sm, int expected_element) {
995
+ int * top2 = NULL;
996
+
997
+ if (sm->dstack->length < 2) {
998
+ return false;
999
+ }
1000
+
1001
+ top2 = g_queue_peek_nth(sm->dstack, sm->dstack->length - 2);
1002
+ return top2 && *top2 == expected_element;
1003
+ }
1004
+
1013
1005
  static inline void append(StateMachine * sm, bool is_markup, const char * s) {
1014
1006
  if (!(is_markup && sm->f_strip)) {
1015
1007
  sm->output = g_string_append(sm->output, s);
1016
1008
  }
1017
1009
  }
1018
1010
 
1019
- static inline void append_newline(StateMachine * sm) {
1020
- #if (PRETTY_PRINT)
1021
- g_string_append_c(sm->output, '\n');
1022
- #endif
1023
- }
1024
-
1025
1011
  static inline void append_c(StateMachine * sm, char s) {
1026
1012
  sm->output = g_string_append_c(sm->output, s);
1027
1013
  }
@@ -1040,6 +1026,10 @@ static inline void append_c_html_escaped(StateMachine * sm, char s) {
1040
1026
  sm->output = g_string_append(sm->output, "&amp;");
1041
1027
  break;
1042
1028
 
1029
+ // case '"':
1030
+ // sm->output = g_string_append(sm->output, "&quot;");
1031
+ // break;
1032
+
1043
1033
  default:
1044
1034
  sm->output = g_string_append_c(sm->output, s);
1045
1035
  break;
@@ -1057,11 +1047,16 @@ static inline void append_segment_uri_escaped(StateMachine * sm, const char * a,
1057
1047
  return;
1058
1048
  }
1059
1049
 
1050
+ char * segment1 = NULL;
1051
+ char * segment2 = NULL;
1060
1052
  GString * segment_string = g_string_new_len(a, b - a + 1);
1061
- char * segment = g_uri_escape_string(segment_string->str, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH "#%?", TRUE);
1062
- sm->output = g_string_append(sm->output, segment);
1053
+
1054
+ segment1 = g_uri_escape_string(segment_string->str, NULL, TRUE);
1055
+ segment2 = g_markup_escape_text(segment1, -1);
1056
+ sm->output = g_string_append(sm->output, segment2);
1063
1057
  g_string_free(segment_string, TRUE);
1064
- g_free(segment);
1058
+ g_free(segment1);
1059
+ g_free(segment2);
1065
1060
  }
1066
1061
 
1067
1062
  static inline void append_segment_html_escaped(StateMachine * sm, const char * a, const char * b) {
@@ -1080,46 +1075,28 @@ static inline void append_block(StateMachine * sm, const char * s) {
1080
1075
  }
1081
1076
  }
1082
1077
 
1083
- static inline void append_closing_p(StateMachine * sm) {
1078
+ static void append_closing_p(StateMachine * sm) {
1084
1079
  size_t i = sm->output->len;
1085
1080
 
1086
1081
  if (i > 4 && !strncmp(sm->output->str + i - 4, "<br>", 4)) {
1087
1082
  sm->output = g_string_truncate(sm->output, sm->output->len - 4);
1088
1083
  }
1089
1084
 
1090
- append_block(sm, "</p>");
1091
- }
1092
-
1093
- static inline void dstack_push(StateMachine * sm, const int * element) {
1094
- g_queue_push_tail(sm->dstack, (gpointer)element);
1095
- }
1096
-
1097
- static inline int * dstack_pop(StateMachine * sm) {
1098
- return g_queue_pop_tail(sm->dstack);
1099
- }
1100
-
1101
- static inline int * dstack_peek(StateMachine * sm) {
1102
- return g_queue_peek_tail(sm->dstack);
1103
- }
1104
-
1105
- static inline bool dstack_search(StateMachine * sm, const int * element) {
1106
- return g_queue_find(sm->dstack, (gconstpointer)element);
1107
- }
1085
+ if (i > 3 && !strncmp(sm->output->str + i - 3, "<p>", 3)) {
1086
+ sm->output = g_string_truncate(sm->output, sm->output->len - 3);
1087
+ return;
1088
+ }
1108
1089
 
1109
- static inline bool dstack_check(StateMachine * sm, int expected_element) {
1110
- int * top = dstack_peek(sm);
1111
- return top && *top == expected_element;
1090
+ append_block(sm, "</p>");
1112
1091
  }
1113
1092
 
1114
- static inline bool dstack_check2(StateMachine * sm, int expected_element) {
1115
- int * top2 = NULL;
1116
-
1117
- if (sm->dstack->length < 2) {
1118
- return false;
1093
+ static void append_closing_p_if(StateMachine * sm) {
1094
+ if (!dstack_check(sm, BLOCK_P)) {
1095
+ return;
1119
1096
  }
1120
1097
 
1121
- top2 = g_queue_peek_nth(sm->dstack, sm->dstack->length - 2);
1122
- return top2 && *top2 == expected_element;
1098
+ dstack_pop(sm);
1099
+ append_closing_p(sm);
1123
1100
  }
1124
1101
 
1125
1102
  static void dstack_rewind(StateMachine * sm) {
@@ -1131,7 +1108,6 @@ static void dstack_rewind(StateMachine * sm) {
1131
1108
 
1132
1109
  if (*element == BLOCK_P) {
1133
1110
  append_closing_p(sm);
1134
- append_newline(sm);
1135
1111
 
1136
1112
  } else if (*element == INLINE_SPOILER) {
1137
1113
  append(sm, true, "</span>");
@@ -1147,7 +1123,6 @@ static void dstack_rewind(StateMachine * sm) {
1147
1123
 
1148
1124
  } else if (*element == BLOCK_NODTEXT) {
1149
1125
  append_closing_p(sm);
1150
- append_newline(sm);
1151
1126
 
1152
1127
  } else if (*element == BLOCK_CODE) {
1153
1128
  append_block(sm, "</pre>");
@@ -1174,7 +1149,6 @@ static void dstack_rewind(StateMachine * sm) {
1174
1149
 
1175
1150
  } else if (*element == BLOCK_TN) {
1176
1151
  append_closing_p(sm);
1177
- append_newline(sm);
1178
1152
 
1179
1153
  } else if (*element == BLOCK_TABLE) {
1180
1154
  append_block(sm, "</table>");
@@ -1190,11 +1164,40 @@ static void dstack_rewind(StateMachine * sm) {
1190
1164
 
1191
1165
  } else if (*element == BLOCK_UL) {
1192
1166
  append_block(sm, "</ul>");
1193
- append_newline(sm);
1194
1167
 
1195
1168
  } else if (*element == BLOCK_LI) {
1196
1169
  append_block(sm, "</li>");
1197
- append_newline(sm);
1170
+
1171
+ } else if (*element == BLOCK_H6) {
1172
+ append_block(sm, "</h6>");
1173
+
1174
+ } else if (*element == BLOCK_H5) {
1175
+ append_block(sm, "</h5>");
1176
+
1177
+ } else if (*element == BLOCK_H4) {
1178
+ append_block(sm, "</h4>");
1179
+
1180
+ } else if (*element == BLOCK_H3) {
1181
+ append_block(sm, "</h3>");
1182
+
1183
+ } else if (*element == BLOCK_H2) {
1184
+ append_block(sm, "</h2>");
1185
+
1186
+ } else if (*element == BLOCK_H1) {
1187
+ append_block(sm, "</h1>");
1188
+ }
1189
+ }
1190
+
1191
+ static void dstack_close_before_block(StateMachine * sm) {
1192
+ while (1) {
1193
+ if (dstack_check(sm, BLOCK_P)) {
1194
+ dstack_pop(sm);
1195
+ append_closing_p(sm);
1196
+ } else if (dstack_check(sm, BLOCK_LI) || dstack_check(sm, BLOCK_UL)) {
1197
+ dstack_rewind(sm);
1198
+ } else {
1199
+ return;
1200
+ }
1198
1201
  }
1199
1202
  }
1200
1203
 
@@ -1204,6 +1207,12 @@ static void dstack_close(StateMachine * sm) {
1204
1207
  }
1205
1208
  }
1206
1209
 
1210
+ static void dstack_close_list(StateMachine * sm) {
1211
+ while (dstack_check(sm, BLOCK_LI) || dstack_check(sm, BLOCK_UL)) {
1212
+ dstack_rewind(sm);
1213
+ }
1214
+ }
1215
+
1207
1216
  static inline bool is_boundary_c(char c) {
1208
1217
  switch (c) {
1209
1218
  case ':':
@@ -1222,9 +1231,15 @@ static inline bool is_boundary_c(char c) {
1222
1231
  return false;
1223
1232
  }
1224
1233
 
1234
+ static bool print_machine(StateMachine * sm) {
1235
+ printf("p=%c\n", *sm->p);
1236
+ return true;
1237
+ }
1238
+
1225
1239
  static void init_machine(StateMachine * sm, VALUE input) {
1226
1240
  size_t output_length = 0;
1227
1241
  sm->p = RSTRING_PTR(input);
1242
+ sm->pb = sm->p;
1228
1243
  sm->pe = sm->p + RSTRING_LEN(input);
1229
1244
  sm->eof = sm->pe;
1230
1245
  sm->ts = NULL;
@@ -1247,6 +1262,9 @@ static void init_machine(StateMachine * sm, VALUE input) {
1247
1262
  sm->dstack = g_queue_new();
1248
1263
  sm->list_nest = 0;
1249
1264
  sm->list_mode = false;
1265
+ sm->header_mode = false;
1266
+ sm->d = 0;
1267
+ sm->b = 0;
1250
1268
  }
1251
1269
 
1252
1270
  static void free_machine(StateMachine * sm) {