poetry.pl 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #!/usr/bin/env perl
  2. use strict;
  3. use v5.10;
  4. # ====================[ poetry.pl ]====================
  5. =head1 NAME
  6. poetry - An Oddmuse module for adding poetry to Oddmuse pages.
  7. =head1 SYNOPSIS
  8. Poetry - particularly rhymically free, "free verse" poetry - tends to depend on
  9. fanciful, often meaningful line-breaks, indentation, and whitespace, which
  10. publication of that poetry must preserve. This extension preserves that.
  11. =head1 INSTALLATION
  12. poetry is easily installable; move this file into the B<wiki/modules/>
  13. directory for your Oddmuse Wiki.
  14. =cut
  15. AddModuleDescription('poetry.pl', 'Poetry Extension');
  16. our ($q, $bol, %RuleOrder, @MyRules);
  17. # ....................{ CONFIGURATION }....................
  18. =head1 CONFIGURATION
  19. poetry is easily configurable; set these variables in the B<wiki/config.pl>
  20. file for your Oddmuse Wiki.
  21. =cut
  22. our ($PoetryIsHandlingCreoleStyleMarkup,
  23. $PoetryIsHandlingXmlStyleMarkup,
  24. $PoetryHtmlTag);
  25. =head2 $PoetryIsHandlingCreoleStyleMarkup
  26. A boolean that, if true, enables handling of Creole-style markup. See
  27. L<MARKUP> below. By default, this boolean is true.
  28. =cut
  29. $PoetryIsHandlingCreoleStyleMarkup = 1;
  30. =head2 $PoetryIsHandlingXmlStyleMarkup
  31. A boolean that, if true, enables handling of Xml-style markup. See
  32. L<MARKUP> below. By default, this boolean is true.
  33. =cut
  34. $PoetryIsHandlingXmlStyleMarkup = 1;
  35. =head2 $PoetryHtmlTag
  36. A string having the HTML tag with which to markup poetry. By default, this is a
  37. preformatted block with default class "poem", which produces HTML:
  38. <pre class="poem">
  39. Like this, a
  40. <em>poem</em> with default
  41. class <code>poem</code>.
  42. </pre>
  43. Preformatted blocks cleanly preserve paragraph whitespace. However, if
  44. preformatted blocks are not your cup of HTML, you can set this string to 'div',
  45. which produces HTML:
  46. <div class="poem">
  47. Like this, a
  48. <em>poem</em> with default
  49. class <code>poem</code>.
  50. </div>
  51. =cut
  52. $PoetryHtmlTag = 'pre';
  53. # ....................{ MARKUP }....................
  54. my $PoetryHtmlAttrPattern = '^class="poem( \S|"$)';
  55. push(@MyRules, \&PoetryRule);
  56. SetHtmlEnvironmentContainer('pre', $PoetryHtmlAttrPattern);
  57. # Stanza linebreaks conflict with Creole-style line-breaks.
  58. $RuleOrder{\&PoetryRule} = 170;
  59. =head2 MARKUP
  60. poetry handles two markup styles: Creole and Xml. The Creole style is more
  61. concise, but a bit less adjustable, than the Xml style.
  62. The Creole style is three colons:
  63. :::
  64. Like this, a
  65. //poem// with default
  66. class, ##poem##, and its last
  67. stanza
  68. indented, and linking to [[Another_Poem|another poem]].
  69. :::
  70. The Xml style is a "<poem>...</poem>" block:
  71. <poem class="haiku">
  72. Like this, a %%[[Haiku]]%% having
  73. the Html
  74. classes, ##haiku## and ##poem##.
  75. </poem>
  76. Or, more concisely:
  77. <poem>
  78. Like this, a %%[[Haiku]]%% having
  79. the default HT-
  80. ML class, ##poem##.
  81. </poem>
  82. Both markup produce a preformatted block (that is, a "<pre>...</pre>" block)
  83. having the "poem" Html class (for CSS stylization of that block). The Xml style
  84. permits customization of this Html class; the Creole style does not. Thus, use
  85. the Xml style for poetry requiring unique CSS stylization.
  86. Both markup preserve linebreaks, leading indendation, and interspersed
  87. whitespace, preserving the lyrical structure of the poetry this markup is
  88. marking up. In other words, this markup does "the right thing."
  89. Both markup permit embedding of other Wiki markup -- like Wiki links, lists,
  90. headers, and so on -- within themselves. (This permits, should you leverage it,
  91. Wiki poets to pen interactive and actively interesting, Wiki-integrated poetry.)
  92. =cut
  93. sub PoetryRule {
  94. if (InElement($PoetryHtmlTag, $PoetryHtmlAttrPattern)) {
  95. # Closure for the current poem.
  96. if ($bol and (
  97. ($PoetryIsHandlingCreoleStyleMarkup and m~\G:::(\n|$)~cg) or
  98. ($PoetryIsHandlingXmlStyleMarkup and m~\G&lt;/poem\&gt;[ \t]*(\n|$)~cg))) {
  99. return CloseHtmlEnvironment($PoetryHtmlTag, $PoetryHtmlAttrPattern).
  100. AddHtmlEnvironment('p');
  101. }
  102. # Linebreaks and paragraphs. This interprets one newline as a linebreak, two
  103. # newlines as a paragraph, and N newlines, where N is greater than two, as a
  104. # paragraph followed by N-2 linebreaks. (This produces appropriate vertical
  105. # tracking, surprisingly.)
  106. elsif (m~\G(\s*\n)+~cg) {
  107. my $number_of_newlines = ($1 =~ tr/\n//);
  108. my $html = '';
  109. if ($number_of_newlines > 1) {
  110. $number_of_newlines -= 2;
  111. $html .= CloseHtmlEnvironments().AddHtmlEnvironment('p');
  112. }
  113. $html .= $q->br() x $number_of_newlines;
  114. return $html;
  115. }
  116. # Whitespace and indentation.
  117. elsif (m~\G(\s+)~cg) { return '&nbsp;' x length($1); }
  118. }
  119. # A new poem.
  120. elsif ($bol and (
  121. ($PoetryIsHandlingCreoleStyleMarkup and m~\G:::(\n|$)~cg) or
  122. ($PoetryIsHandlingXmlStyleMarkup and
  123. m~\G\&lt;poem(\s+(?:class\s*=\s*)?"(.+?)")?\&gt;[ \t]*(\n|$)~cg))) {
  124. return CloseHtmlEnvironments()
  125. .AddHtmlEnvironment($PoetryHtmlTag, 'class="poem'.
  126. (defined $2 ? ' '.$2 : '').'"')
  127. .AddHtmlEnvironment('p');
  128. }
  129. return;
  130. }
  131. =head1 COPYRIGHT AND LICENSE
  132. The information below applies to everything in this distribution,
  133. except where noted.
  134. Copyleft 2008 by B.w.Curry <http://www.raiazome.com>.
  135. This program is free software; you can redistribute it and/or modify
  136. it under the terms of the GNU General Public License as published by
  137. the Free Software Foundation; either version 3 of the License, or
  138. (at your option) any later version.
  139. This program is distributed in the hope that it will be useful,
  140. but WITHOUT ANY WARRANTY; without even the implied warranty of
  141. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  142. GNU General Public License for more details.
  143. You should have received a copy of the GNU General Public License
  144. along with this program. If not, see L<http://www.gnu.org/licenses/>.
  145. =cut