dtext_rb 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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) {