moin.pl 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 2 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, write to the
  15. # Free Software Foundation, Inc.
  16. # 59 Temple Place, Suite 330
  17. # Boston, MA 02111-1307 USA
  18. use strict;
  19. use v5.10;
  20. AddModuleDescription('moin.pl', 'Moin Markup Extension');
  21. our ($q, $bol, @HtmlStack, %RuleOrder, @MyRules);
  22. push(@MyRules, \&MoinRule);
  23. $RuleOrder{\&MoinRule} = -10; # run before default rules because of [[BR]]
  24. my %moin_level; # mapping length of whitespace to indentation level
  25. my $moin_current; # the current length of whitespace (not indentation level!)
  26. sub MoinLength {
  27. my $str = shift;
  28. my $oldpos = pos;
  29. $str =~ s/\t/ /g;
  30. die if pos != $oldpos;
  31. return length($str); # the length of whitespace
  32. }
  33. sub MoinListLevel {
  34. my $oldpos = pos;
  35. my $length = MoinLength(shift);
  36. if (not InElement('li') and not InElement('dd')) { # problematic mixing!
  37. %moin_level = ($length => 1);
  38. $moin_current = $length;
  39. } elsif ($moin_level{$length}) {
  40. # return from a sublist or continuing the current list
  41. foreach my $ln (keys %moin_level) {
  42. delete $moin_level{$ln} if $moin_level{$ln} > $moin_level{$length};
  43. }
  44. $moin_current = $length;
  45. } elsif ($length > $moin_current) {
  46. # or entering a new sublist
  47. $moin_level{$length} = $moin_level{$moin_current} + 1;
  48. $moin_current = $length;
  49. } else {
  50. # else we've returned to an invalid level - but we know that there is a higher level!
  51. $length++ until $moin_level{$length};
  52. $moin_current = $length;
  53. }
  54. pos = $oldpos;
  55. return $moin_level{$moin_current}
  56. }
  57. sub MoinRule {
  58. # ["free link"]
  59. if (m/\G(\["(.*?)"\])/cgs) {
  60. Dirty($1);
  61. print GetPageOrEditLink($2);
  62. return '';
  63. }
  64. # [[BR]]
  65. elsif (m/\G\[\[BR\]\]/cg) {
  66. return $q->br();
  67. }
  68. # {{{
  69. # block
  70. # }}}
  71. elsif ($bol && m/\G\{\{\{\n?(.*?\n)\}\}\}[ \t]*\n?/cgs) {
  72. return CloseHtmlEnvironments()
  73. . $q->pre({-class=>'real'}, $1)
  74. . AddHtmlEnvironment('p');
  75. }
  76. # * list item
  77. # * nested item
  78. elsif ($bol && m/\G(\s*\n)*([ \t]+)\*[ \t]*/cg
  79. or InElement('li') && (m/\G(\s*\n)+([ \t]+)\*[ \t]*/cg)) {
  80. return CloseHtmlEnvironmentUntil('li')
  81. . OpenHtmlEnvironment('ul', MoinListLevel($2))
  82. . AddHtmlEnvironment('li');
  83. }
  84. # 1. list item
  85. # 1. nested item
  86. elsif ($bol && m/\G(\s*\n)*([ \t]+)1\.[ \t]*/cg
  87. or InElement('li') && m/\G(\s*\n)+([ \t]+)1\.[ \t]*/cg) {
  88. return CloseHtmlEnvironmentUntil('li')
  89. . OpenHtmlEnvironment('ol', MoinListLevel($2))
  90. . AddHtmlEnvironment('li');
  91. }
  92. # indented text using whitespace
  93. elsif ($bol && m/\G(\s*\n)*([ \t]+)/cg) {
  94. my $str = $2;
  95. if (MoinLength($str) == $moin_current
  96. and (InElement('li') or InElement('dd'))) {
  97. return ' ';
  98. } else {
  99. return CloseHtmlEnvironmentUntil('dd')
  100. . OpenHtmlEnvironment('dl', MoinListLevel($str), 'quote')
  101. . $q->dt()
  102. . AddHtmlEnvironment('dd');
  103. }
  104. }
  105. # emphasis and strong emphasis using '' and '''
  106. elsif (defined $HtmlStack[0] && $HtmlStack[1] && $HtmlStack[0] eq 'em'
  107. && $HtmlStack[1] eq 'strong' and m/\G'''''/cg) {
  108. # close either of the two
  109. return CloseHtmlEnvironment() . CloseHtmlEnvironment();
  110. }
  111. # traditional wiki syntax for '''strong'''
  112. elsif (m/\G'''/cg) {
  113. return (defined $HtmlStack[0] && $HtmlStack[0] eq 'strong')
  114. ? CloseHtmlEnvironment() : AddHtmlEnvironment('strong');
  115. }
  116. # traditional wiki syntax for ''emph''
  117. elsif (m/\G''/cg) {
  118. return (defined $HtmlStack[0] && $HtmlStack[0] eq 'em')
  119. ? CloseHtmlEnvironment() : AddHtmlEnvironment('em');
  120. }
  121. # moin syntax for __underline__
  122. elsif (m/\G__/cg) {
  123. return (defined $HtmlStack[0] && $HtmlStack[0] eq 'em')
  124. ? CloseHtmlEnvironment() : AddHtmlEnvironment('em', 'style="text-decoration: underline; font-style: normal;"');
  125. }
  126. # don't automatically fuse lines
  127. elsif (m/\G([ \t]+|[ \t]*\n)/cg) {
  128. return ' ';
  129. }
  130. return;
  131. }