moin.pl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # Copyright (C) 2005 Alex Schroeder <alex@emacswiki.org>
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 3 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. use strict;
  16. use v5.10;
  17. AddModuleDescription('moin.pl', 'Moin Markup Extension');
  18. our ($q, $bol, @HtmlStack, %RuleOrder, @MyRules);
  19. push(@MyRules, \&MoinRule);
  20. $RuleOrder{\&MoinRule} = -10; # run before default rules because of [[BR]]
  21. my %moin_level; # mapping length of whitespace to indentation level
  22. my $moin_current; # the current length of whitespace (not indentation level!)
  23. sub MoinLength {
  24. my $str = shift;
  25. my $oldpos = pos;
  26. $str =~ s/\t/ /g;
  27. die if pos != $oldpos;
  28. return length($str); # the length of whitespace
  29. }
  30. sub MoinListLevel {
  31. my $oldpos = pos;
  32. my $length = MoinLength(shift);
  33. if (not InElement('li') and not InElement('dd')) { # problematic mixing!
  34. %moin_level = ($length => 1);
  35. $moin_current = $length;
  36. } elsif ($moin_level{$length}) {
  37. # return from a sublist or continuing the current list
  38. foreach my $ln (keys %moin_level) {
  39. delete $moin_level{$ln} if $moin_level{$ln} > $moin_level{$length};
  40. }
  41. $moin_current = $length;
  42. } elsif ($length > $moin_current) {
  43. # or entering a new sublist
  44. $moin_level{$length} = $moin_level{$moin_current} + 1;
  45. $moin_current = $length;
  46. } else {
  47. # else we've returned to an invalid level - but we know that there is a higher level!
  48. $length++ until $moin_level{$length};
  49. $moin_current = $length;
  50. }
  51. pos = $oldpos;
  52. return $moin_level{$moin_current}
  53. }
  54. sub MoinRule {
  55. # ["free link"]
  56. if (m/\G(\["(.*?)"\])/cgs) {
  57. Dirty($1);
  58. print GetPageOrEditLink($2);
  59. return '';
  60. }
  61. # [[BR]]
  62. elsif (m/\G\[\[BR\]\]/cg) {
  63. return $q->br();
  64. }
  65. # {{{
  66. # block
  67. # }}}
  68. elsif ($bol && m/\G\{\{\{\n?(.*?\n)\}\}\}[ \t]*\n?/cgs) {
  69. return CloseHtmlEnvironments()
  70. . $q->pre({-class=>'real'}, $1)
  71. . AddHtmlEnvironment('p');
  72. }
  73. # * list item
  74. # * nested item
  75. elsif ($bol && m/\G(\s*\n)*([ \t]+)\*[ \t]*/cg
  76. or InElement('li') && (m/\G(\s*\n)+([ \t]+)\*[ \t]*/cg)) {
  77. return CloseHtmlEnvironmentUntil('li')
  78. . OpenHtmlEnvironment('ul', MoinListLevel($2))
  79. . AddHtmlEnvironment('li');
  80. }
  81. # 1. list item
  82. # 1. nested item
  83. elsif ($bol && m/\G(\s*\n)*([ \t]+)1\.[ \t]*/cg
  84. or InElement('li') && m/\G(\s*\n)+([ \t]+)1\.[ \t]*/cg) {
  85. return CloseHtmlEnvironmentUntil('li')
  86. . OpenHtmlEnvironment('ol', MoinListLevel($2))
  87. . AddHtmlEnvironment('li');
  88. }
  89. # indented text using whitespace
  90. elsif ($bol && m/\G(\s*\n)*([ \t]+)/cg) {
  91. my $str = $2;
  92. if (MoinLength($str) == $moin_current
  93. and (InElement('li') or InElement('dd'))) {
  94. return ' ';
  95. } else {
  96. return CloseHtmlEnvironmentUntil('dd')
  97. . OpenHtmlEnvironment('dl', MoinListLevel($str), 'quote')
  98. . $q->dt()
  99. . AddHtmlEnvironment('dd');
  100. }
  101. }
  102. # emphasis and strong emphasis using '' and '''
  103. elsif (defined $HtmlStack[0] && $HtmlStack[1] && $HtmlStack[0] eq 'em'
  104. && $HtmlStack[1] eq 'strong' and m/\G'''''/cg) {
  105. # close either of the two
  106. return CloseHtmlEnvironment() . CloseHtmlEnvironment();
  107. }
  108. # traditional wiki syntax for '''strong'''
  109. elsif (m/\G'''/cg) {
  110. return (defined $HtmlStack[0] && $HtmlStack[0] eq 'strong')
  111. ? CloseHtmlEnvironment() : AddHtmlEnvironment('strong');
  112. }
  113. # traditional wiki syntax for ''emph''
  114. elsif (m/\G''/cg) {
  115. return (defined $HtmlStack[0] && $HtmlStack[0] eq 'em')
  116. ? CloseHtmlEnvironment() : AddHtmlEnvironment('em');
  117. }
  118. # moin syntax for __underline__
  119. elsif (m/\G__/cg) {
  120. return (defined $HtmlStack[0] && $HtmlStack[0] eq 'em')
  121. ? CloseHtmlEnvironment() : AddHtmlEnvironment('em', 'style="text-decoration: underline; font-style: normal;"');
  122. }
  123. # don't automatically fuse lines
  124. elsif (m/\G([ \t]+|[ \t]*\n)/cg) {
  125. return ' ';
  126. }
  127. return;
  128. }