2 # ====================[ creole.pl ]====================
6 creole - An Oddmuse module for marking up Oddmuse Wiki pages according to the
7 Wiki Creole standard, a Wiki-agnostic syntax scheme.
11 creole is easily installable; move this file into the B<wiki/modules/>
12 directory for your Oddmuse Wiki.
17 $ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/creole.pl">creole.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Creole_Markup_Extension">Creole Markup Extension</a></p>';
19 # ....................{ CONFIGURATION }....................
23 creole is easily configurable; set these variables in the B<wiki/config.pl>
24 file for your Oddmuse Wiki.
27 use vars
qw($CreoleLineBreaks
28 $CreoleTildeAlternative
29 $CreoleTableCellsContainBlockLevelElements
30 $CreoleDashStyleUnorderedLists);
32 =head2 $CreoleLineBreaks
34 A boolean that, if true, causes this extension to convert single newlines in
35 page text to genuine linebreaks (i.e., the <br> tag) in the HTML for that
36 page. (If false, this extension consumes single newlines without actually
37 converting them into anything; they will be ignored, wherever found.)
39 Irregardless of this booleans setting, this extension always converts two
40 newlines to a paragraph break (i.e., the <p> tag).
43 $CreoleLineBreaks = 0;
45 =head2 $CreoleTildeAlternative
47 A boolean that, if true, prevents this extension from consuming the tilde ~
48 character, when that character appears in front of an a-z, A-Z, or 0-9
49 character. (If false, this extension consumes such tilde ~ characters.)
52 $CreoleTildeAlternative = 0;
54 =head2 $CreoleTableCellsContainBlockLevelElements
56 A boolean that, if true, permits table cell markup to embed block level
57 elements in table cells. (By default, this boolean is false.)
59 You are encouraged to enable this boolean, as it significantly improves the
60 "stuff" you can do with Wiki Creole table syntax. For example, enabling this
61 boolean permits you to embed nested lists in tables.
63 Block level elements are such "high-level" entities as paragraphs, blockquotes,
64 list items, and so on. Thus, enabling this boolean permits you to embed multiple
65 paragraphs, blockquotes, and so on in individual table cells.
67 Please note: enabling this boolean permits non-conformant syntax -- that is,
68 syntax which no longer conforms to the Wiki Creole standard. (In general,
69 unless you have significant amounts of Wiki Creole table markup strictly
70 conforming to the Wiki Creole standard, this shouldn't be an issue.)
72 Please note: enabling this boolean also requires you explicitly close the last
73 table cell of a cell with a "|" character. (This character is optional under
74 the Wiki Creole standard, but not under this non-conformant alteration.)
77 $CreoleTableCellsContainBlockLevelElements = 0;
79 =head2 $CreoleDashStyleUnorderedLists
81 A boolean that, if true, permits unordered list items to be prefixed with either
82 a '-' dash or an '*' asterisk or, if false, requires unordered list items to be
83 prefixed with an '*' asterisk, only. (By default, this boolean is false.)
85 Please note: enabling this boolean permits non-conformant syntax -- that is,
86 syntax which no longer conforms to the Wiki Creole standard. Unless your Wiki
87 requires it, you are encouraged not to set this boolean.
90 $CreoleDashStyleUnorderedLists = 0;
92 # ....................{ INITIALIZATION }....................
93 push(@MyInitVariables, \&CreoleInit);
95 # A boolean that is true if the "creoleaddition.pl" module is also installed.
96 my $CreoleIsCreoleAddition;
98 # A boolean set by CreoleRule() to true, if a new table cell has just been
99 # started. This allows testing, elsewhere, of whether we are at the start of a
100 # a new table cell. Why test that? Because. If we are indeed at the start of a
101 # a new table cell, we should behave as if the "$bol" boolean is true: we should
102 # allow block level elements at the start of this new table cell.
104 # Of course, we have to set this to false immediately after matching past the
105 # start of that table cell. This is what RunMyRulesCreole() does.
106 my $CreoleIsTableCellBol;
108 # A regular expression matching Wiki Creole-style table cells.
109 my $CreoleTableCellPattern = '[ \t]*(\|+)(=)?\n?([ \t]*)';
111 # A regular expression matching Wiki Creole-style pipe delimiters in links.
112 my $CreoleLinkPipePattern = '[ \t]*\|[ \t]*';
114 # A regular expression matching Wiki Creole-style link text. This expression
115 # takes into account the fact that such text is always optional.
116 my $CreoleLinkTextPattern = "($CreoleLinkPipePattern(.+?))?";
118 # The html tag and string of html tag attributes for the current Creole header.
119 # This prevents an otherwise necessary, costly evaluation of test statements
122 # if (InElement('h1') or InElement('h2') or InElement('h3') or
123 # InElement('h4') or InElement('h5') or InElement('h6')) { ... }
125 # As Creole headers cannot span blocks or lines, this should be a safe caching.
126 my ($CreoleHeaderHtmlTag, $CreoleHeaderHtmlTagAttr);
129 $CreoleIsCreoleAddition = defined &CreoleAdditionRule;
131 $CreoleIsTableCellBol =
132 $CreoleHeaderHtmlTag =
133 $CreoleHeaderHtmlTagAttr = '';
135 # This is the "code magic" enabling block-level elements in multi-line
137 if ($CreoleTableCellsContainBlockLevelElements) {
138 SetHtmlEnvironmentContainer('td');
139 SetHtmlEnvironmentContainer('th');
142 # FIXME: The following changes interfere with the bbcode extension.
143 # To achieve something similar, we often see sites with an InterMap
144 # entry called Self, eg. from http://emacswiki.org/InterMap: Self
145 # /cgi-bin/emacs? -- which allows you to link to Self:action=index.
147 # Permit page authors to link to URLs resembling:
148 # "See [[/?action=index|the site map]]."
150 # Which Oddmuse converts to HTML resembling:
151 # "See <a href="/?action=index">the site map</a>."
153 # When not using this extension, authors must add this Wiki's base URL:
154 # "See [[http://www.oddmuse.com/cgi-bin/oddmuse?action=index|the site map]]."
155 # my $UrlChars = '[-a-zA-Z0-9/@=+$_~*.,;:?!\'"()&#%]'; # see RFC 2396
156 # $FullUrlPattern = "((?:$UrlProtocols:|/)$UrlChars+)";
158 # Permit page authors to link to other pages having semicolons in their names.
159 # my $LinkCharsSansZero = "-;,.()' _1-9A-Za-z\x{0080}-\x{fffd}";
160 # my $LinkChars = $LinkCharsSansZero.'0';
161 # $FreeLinkPattern = "([$LinkCharsSansZero]|[$LinkChars][$LinkChars]+)";
164 # ....................{ MARKUP }....................
168 \&CreoleListAndNewLineRule);
170 # Creole link rules conflict with Oddmuse's default LinkRule.
171 $RuleOrder{\&CreoleRule} = -10;
172 # Creole heading rules must come after the TocRule.
173 $RuleOrder{\&CreoleHeadingRule} = 100;
174 # List items must come later than MarkupRule because *foo* at the
175 # beginning of a line should be bold, not the list item foo*. Also,
176 # newlines must come after list items, otherwise this will add a lot
177 # of useless "</br>" tags.
178 $RuleOrder{\&CreoleListAndNewLineRule} = 180;
179 # Oddmuse's built-in ListRule conflicts with above CreoleListAndNewLineRule.
180 # Thus, we ensure the latter is applied before the former.
181 $RuleOrder{\&ListRule} = 190;
185 Handles the large part of Wiki Creole syntax.
187 Technically, as Oddmuse's default C<LinkRules> function also conflicts with
188 this extension's link rules and does not comply, in any case, with the Wiki
189 Creole rules for links, we should also nullify Oddmuse's default C<LinkRules>
190 function. Sadly, we don't. Why? Since existing Oddmuse Wikis using this
191 extension depend on Oddmuse's default C<LinkRules> function, and as it's no
192 terrible harm to let that function be, we have to let it be. Bah!
196 # "$is_interlinking" is a boolean that, if true, indicates this rule should
197 # make interlinks (i.e., links to Wiki pages on other, external Wikis) and,
198 # and, if false, should not. (Typically, Oddmuse sets this to false when
199 # including external HTML pages into local Wiki pages.)
200 my ($is_interlinking, $is_intraanchoring) = @_;
204 if ($bol && m/\G[ \t]*----[ \t]*(\n|$)/cg) {
205 return CloseHtmlEnvironments().$q->hr().AddHtmlEnvironment('p');
210 elsif ($bol && m/\G\{\{\{[ \t]*\n(.*?)\n\}\}\}[ \t]*(\n|$)/cgs) {
212 return CloseHtmlEnvironments()
213 .$q->pre({-class=> 'real'}, $str)
214 .AddHtmlEnvironment('p');
216 # escape next char (and prevent // in URLs from enabling italics)
218 elsif (m/\G(~($FullUrlPattern|\S))/cgo) {
220 ($CreoleTildeAlternative and
221 index( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
222 .'abcdefghijklmnopqrstuvwxyz'
223 .'0123456789', $2) != -1)
225 : $2; # tilde disappears
228 elsif (m/\G\*\*/cg) { return AddOrCloseHtmlEnvironment('strong'); }
230 elsif (m/\G\/\//cg) { return AddOrCloseHtmlEnvironment('em'); }
231 # {{{preformatted code}}}
232 elsif (m/\G\{\{\{(.*?}*)\}\}\}/cg) { return $q->code($1); }
233 # download: {{pic}} and {{pic|text}}
234 elsif (m/\G(\{\{$FreeLinkPattern$CreoleLinkTextPattern\}\})/cgos) {
236 return GetCreoleLinkHtml($1, GetDownloadLink(FreeToNormal($2), 1, undef, $text), $text);
238 # image link: {{url}} and {{url|text}}
239 elsif (m/\G\{\{$FullUrlPattern$CreoleLinkTextPattern\}\}/cgos) {
240 return GetCreoleImageHtml(
241 $q->a({-href=> UnquoteHtml($1),
242 -class=> 'image outside'},
243 $q->img({-src=> UnquoteHtml($1),
244 -alt=> UnquoteHtml($3),
245 -class=> 'url outside'})));
247 # image link: [[link|{{pic}}]] and [[link|{{pic|text}}]]
248 elsif (m/\G(\[\[$FreeLinkPattern$CreoleLinkPipePattern
249 \{\{$FreeLinkPattern$CreoleLinkTextPattern\}\}\]\])/cgosx) {
251 return GetCreoleLinkHtml($1, GetCreoleImageHtml(
252 ScriptLink(UrlEncode(FreeToNormal($2)),
253 $q->img({-src=> GetDownloadLink(FreeToNormal($3), 2),
254 -alt=> UnquoteHtml($text),
255 -class=> 'upload'}), 'image')), $text);
257 # image link: [[link|{{url}}]] and [[link|{{url|text}}]]
258 elsif (m/\G(\[\[$FreeLinkPattern$CreoleLinkPipePattern
259 \{\{$FullUrlPattern$CreoleLinkTextPattern\}\}\]\])/cgosx) {
261 return GetCreoleLinkHtml($1, GetCreoleImageHtml(
262 ScriptLink(UrlEncode(FreeToNormal($2)),
263 $q->img({-src=> UnquoteHtml($3),
264 -alt=> UnquoteHtml($text),
265 -class=> 'url outside'}), 'image')), $text);
267 # image link: [[url|{{pic}}]] and [[url|{{pic|text}}]]
268 elsif (m/\G(\[\[$FullUrlPattern$CreoleLinkPipePattern
269 \{\{$FreeLinkPattern$CreoleLinkTextPattern\}\}\]\])/cgosx) {
271 return GetCreoleLinkHtml($1, GetCreoleImageHtml(
272 $q->a({-href=> UnquoteHtml($2), -class=> 'image outside'},
273 $q->img({-src=> GetDownloadLink(FreeToNormal($3), 2),
274 -alt=> UnquoteHtml($text),
275 -class=> 'upload'}))), $text);
277 # image link: [[url|{{url}}]] and [[url|{{url|text}}]]
278 elsif (m/\G\[\[$FullUrlPattern$CreoleLinkPipePattern
279 \{\{$FullUrlPattern$CreoleLinkTextPattern\}\}\]\]/cgosx) {
280 return GetCreoleImageHtml(
281 $q->a({-href=> UnquoteHtml($1), -class=> 'image outside'},
282 $q->img({-src=> UnquoteHtml($2),
283 -alt=> UnquoteHtml($4),
284 -class=> 'url outside'})));
286 # link: [[url]] and [[url|text]]
287 elsif (m/\G\[\[$FullUrlPattern$CreoleLinkTextPattern\]\]/cgos) {
288 # Permit embedding of Creole syntax within link text. (Rather complicated,
289 # but it does the job remarkably.)
291 my $link_text = $3 ? CreoleRuleRecursive($3, @_) : $link_url;
293 # GetUrl() takes parameters resembling:
295 # ~ the link's text (to be displayed for that URL).
296 # ~ a boolean (to be used Gods' know how).
297 return GetUrl($link_url, $link_text, 1);
299 # link: [[page]] and [[page|text]]
300 elsif (m/\G(\[\[$FreeLinkPattern$CreoleLinkTextPattern\]\])/cgos) {
303 my $link_text = $4 ? CreoleRuleRecursive($4, @_) : $page_name;
305 return GetCreoleLinkHtml($markup,
306 GetPageOrEditLink($page_name, $link_text, 0, 1), $link_text);
308 # interlink: [[Wiki:page]] and [[Wiki:page|text]]
309 elsif ($is_interlinking and
310 m/\G(\[\[$FreeInterLinkPattern$CreoleLinkTextPattern\]\])/cgos) {
313 my $interlink_text = $4;
314 my ($site_name, $page_name) = $interlink =~ m~^($InterSitePattern):(.*)$~;
316 # Permit embedding of Creole syntax within interlink text. We operate on
317 # "$interlink_text", rather than "$4", since that ordinal has already been
318 # overridden by the above regular expression match.
319 $interlink_text = $interlink_text
320 ? CreoleRuleRecursive($interlink_text, @_)
321 : $q->span({-class=> 'site'}, $site_name)
322 .$q->span({-class=> 'separator'}, ':')
323 .$q->span({-class=> 'page'}, $page_name);
325 # If the Wiki for this interlink is a registered Wiki (that is, it appears
326 # in this Wiki's "$InterMap" page), then produce an interlink to it;
327 # otherwise, produce a normal intralink to a page on this Wiki.
328 return GetCreoleLinkHtml($markup,
329 $InterSite{$site_name}
330 ? GetInterLink ($interlink, $interlink_text, 0, 1)
331 : GetPageOrEditLink($page_name, $interlink_text, 0, 1), $interlink_text);
334 # Table syntax is matched last (or nearly last), so as to allow other Creole-
335 # specific syntax within tables.
337 # tables using | -- end of the table (two newlines) or row (one newline)
338 elsif (InElement('table')) {
339 # We know that this is the end of this table row, if we match:
340 # * an explicit "|" character followed by: a newline character and
341 # another "|" character; or
342 # * an explicit newline character followed by: a "|" character.
344 # That is to say, the "|" character terminating a table row is optional.
346 # In either case, the newline character signifies the end of this table
347 # row and the "|" character that follows it signifies the start of a new
348 # row. We avoid consuming the "|" character by matching it with a lookahead.
349 if (m/\G([ \t]*\|)?[ \t]*\n(?=$CreoleTableCellPattern)/cg) {
350 return CloseHtmlEnvironmentUntil('table').AddHtmlEnvironment('tr');
352 # If block level elements are allowed in table cells, we know that this is
353 # the end of the table, if we match:
354 # * an explicit "|" character followed by: a newline character not
355 # followed by another "|" character, or an implicit end-of-page.
357 # Otherwise, we know that this is the end of the table, if we match:
358 # * an explicit "|" character followed by: a newline character not
359 # followed by another "|" character, or an implicit end-of-page; or
360 # * two newline characters.
362 # This condition should appear after the end-of-row test, above.
363 elsif (m/\G[ \t]*\|[ \t]*(\n|$)/cg or
364 (!$CreoleTableCellsContainBlockLevelElements and m/\G[ \t]*\n\n/cg)) {
365 # Note: we do not call "CloseHtmlEnvironmentsCreoleOld", as that function
366 # refers to the Oddmuse built-in. If another module with name
367 # lexically following "creole.pl" also redefines the built-in
368 # "CloseHtmlEnvironments" function, then calling the
369 # "CloseHtmlEnvironmentsCreoleOld" function causes that other
370 # module's redefinition to not be called. (Yes; an entangling mess
371 # we've made for ourselves, here. Clearly, this needs a rethink in
372 # some later Oddmuse refactoring.)
373 return CloseHtmlEnvironment('table').AddHtmlEnvironment('p');
375 # Lastly, we know this this is start of a new table cell (and possibly also
376 # the end of the last table cell), if we match:
377 # * an explicit "|" character.
379 # This condition should appear after the end-of-table test, above.
380 elsif (m/\G$CreoleTableCellPattern/cg) {
381 # This is the start of a new table cell. However, we only consider that
382 # equivalent to the "$bol" variable when the
383 # "$CreoleTableCellsContainBlockLevelElements" variable is enabled. (In
384 # other words, we only declare that we may insert block level elements at
385 # the start of this new table cell, when we allow block level elements in
387 $CreoleIsTableCellBol = $CreoleTableCellsContainBlockLevelElements;
389 my $tag = $2 ? 'th' : 'td';
390 my $column_span = length($1);
391 my $is_right_justified = $3;
393 # Now that we've retrieved all numbered matches, match another lookahead.
394 my $is_left_justified = m/\G(?=[^\n|]*?[ \t]+\|)/;
395 my $attributes = $column_span == 1 ? '' : qq{colspan="$column_span"};
397 if ($is_left_justified and
398 $is_right_justified) { $attributes .= 'align="center"' }
399 elsif ($is_right_justified) { $attributes .= 'align="right"' }
400 # this is the default:
401 # elsif ($is_left_justified) { $attributes .= 'align="left"' }
404 (InElement('td') || InElement('th') ? CloseHtmlEnvironmentUntil('tr') : '')
405 .AddHtmlEnvironment($tag, $attributes);
408 # tables using | -- an ordinary table cell
410 # Please note that order is important, here; this should appear after all
411 # markup dependent on being in a current table.
413 # Also, the "|" character also signifies the start of a new table cell. Thus,
414 # we avoid consuming that character by matching it with a lookahead.
415 elsif ($bol and m/\G(?=$CreoleTableCellPattern)/cg) {
416 return OpenHtmlEnvironment('table', 1, 'user').AddHtmlEnvironment('tr');
422 sub CreoleHeadingRule {
423 # header opening: = to ====== for h1 to h6
425 # header opening and closing have been partitioned into two separate
426 # conditional matches rather than congealed into one conditional match. Why?
427 # Because, in so doing, we permit application of other markup rules,
428 # elsewhere, to header text. This, in turn, permits insertion and
429 # interpretation of complex markup in header text; e.g.,
430 # == //This Is a **Level-2** Header %%Having Complex Markup%%.// ==
431 if ($bol and m~\G(\s*\n)*(=+)[ \t]*~cg) {
432 my $header_depth = length($2);
433 ($CreoleHeaderHtmlTag, $CreoleHeaderHtmlTagAttr) = $header_depth <= 6
434 ? ('h'.$header_depth, '')
435 : ('h6', qq{class="h$header_depth"});
436 return CloseHtmlEnvironments()
437 . AddHtmlEnvironment($CreoleHeaderHtmlTag, $CreoleHeaderHtmlTagAttr);
439 # header closing: = to ======, newline, or EOF
441 # Note: partitioning this from the heading opening conditional, above,
442 # typically causes Oddmuse to insert an extraneous space at the end of
443 # header tags. This is non-dangerous, fortunately; and changes nothing.
444 elsif ($CreoleHeaderHtmlTag and m~\G[ \t]*=*[ \t]*(\n|$)~cg) {
446 CloseHtmlEnvironment($CreoleHeaderHtmlTag, '^'.$CreoleHeaderHtmlTagAttr.'$')
447 .AddHtmlEnvironment('p');
448 $CreoleHeaderHtmlTag = $CreoleHeaderHtmlTagAttr = '';
455 sub CreoleListAndNewLineRule {
456 my $is_in_list_item = InElement('li');
459 if (($bol and m/\G[ \t]*(#)[ \t]*/cg) or
460 ($is_in_list_item and m/\G[ \t]*\n+[ \t]*(#+)[ \t]*/cg)) {
461 # Note: the first line of this return statement is --not-- equivalent to:
462 # "return CloseHtmlEnvironmentUntil('li')", as that line does not permit
463 # modules overriding the CloseHtmlEnvironments() function to "have a say."
464 return ($is_in_list_item ? CloseHtmlEnvironmentUntil('li') : CloseHtmlEnvironments())
465 # Use `list' tag to establish equivalence between the `ul' and
466 # `ol' tag for the purpose of depth calculation. The `list' tag
467 # will be replaced with `ol' (or `ul') later in OpenHtmlTag and
469 .OpenHtmlEnvironment('list', length($1),
470 StashAttributeValue('', 'type', 'numbered'))
471 .AddHtmlEnvironment ('li');
473 # * bullet list (nestable; needs space when nested to disambiguate from bold)
474 elsif (($bol and m/\G[ \t]*(\*)[ \t]*/cg) or
475 ($is_in_list_item and m/\G[ \t]*\n+[ \t]*(\*+)[ \t]+/cg)) {
476 return ($is_in_list_item ? CloseHtmlEnvironmentUntil('li') : CloseHtmlEnvironments())
477 # Apropos `list' tag below, see note in the previous conditional.
478 .OpenHtmlEnvironment('list', length($1),
479 StashAttributeValue('', 'type', 'bulleted'))
480 .AddHtmlEnvironment ('li');
482 # - bullet list (not nestable; always needs space)
483 elsif ($CreoleDashStyleUnorderedLists and (
484 ($bol and m/\G[ \t]*(-)[ \t]+/cg) or
485 ($is_in_list_item and m/\G[ \t]*\n+[ \t]*(-)[ \t]+/cg))) {
486 return ($is_in_list_item ? CloseHtmlEnvironmentUntil('li') : CloseHtmlEnvironments())
487 # Apropos `list' tag below, see note in the previous conditional.
488 .OpenHtmlEnvironment('list', length($1),
489 StashAttributeValue('', 'type', 'bulleted'))
490 .AddHtmlEnvironment ('li');
492 # paragraphs: at least two newlines
493 elsif (m/\G\s*\n(\s*\n)+/cg) {
494 return CloseHtmlEnvironments().AddHtmlEnvironment('p');
496 # line break: one newline or explicit "\\"
498 # Note, single newlines not matched by this conditional will be converted into
499 # a single space. (In general, this is what you want.)
500 elsif (($CreoleLineBreaks and m/\G\s*\n/cg) or m/\G\\\\(\s*\n?)/cg) {
507 # ....................{ HTML }....................
509 =head2 GetCreoleImageHtml
511 Returns the passed HTML image, conditionally wrapped within an HTML paragraph
512 tag having an necessary image class when the passed HTML also represents such a
513 new paragraph. Difficult to explain, isn't she?
516 sub GetCreoleImageHtml {
517 my $image_html = shift;
519 ($bol ? CloseHtmlEnvironments().AddHtmlEnvironment('p', 'class="image"') : '')
523 =head2 GetCreoleLinkHtml
525 Marks the passed HTML as a dirty block, unless this HTML belongs to an HTML
526 header tag. Such tags may not contain dirty blocks! Most Oddmuse modules using
527 header tags (e.g., "sidebar.pl", "toc.pl") require, as a caching efficiency,
528 header text to be clean. This is a nearly necessary efficiency, since
529 regeneration of markup for those modules is an often costly operation. (We
530 certainly don't want to regenerate the Table of Contents for each page having at
531 least one header having at least one dirty link whenever an external user browses
534 Thus, if in a header, this function cleans links out of the passed HTML and
535 returns the resultant HTML (to the current clean block). Otherwise, this
536 function appends the resultant HTML to a new dirty block, prints it, and returns
537 it. (This does not print the resultant HTML when clean, since clean blocks are
538 printed, automatically, by the next call to C<Dirty>.)
540 This function, lastly, accepts three function parameters. These are:
544 =item C<$markup>. (This is the Wiki markup string to be marked as dirty when it
545 is not embedded in a Creole header.)
547 =item C<$html>. (This is the HTML string to be marked as dirty when this HTML
548 is not embedded in a Creole header.)
550 =item C<$text>. (This is the text string to be marked as clean when this HTML
551 is embedded within a Creole header.)
555 Creole functions, above, should **not** call the C<Dirty> function directly.
556 Rather, they should always call this function...with appropriate parameters.
559 sub GetCreoleLinkHtml {
560 my ($markup, $html, $link_text) = @_;
562 if ($CreoleHeaderHtmlTag) { return $link_text; }
570 # ....................{ FUNCTIONS }....................
571 *RunMyRulesCreoleOld = *RunMyRules;
572 *RunMyRules = *RunMyRulesCreole;
574 =head2 RunMyRulesCreole
576 Runs all markup rules for the current block of page markup. This redefinition
577 ensures that the beginning of a table cell is considered the beginning of a
578 block-level element -- that, in other words, the C<$bol> global be set to 1.
580 If the C<$CreoleTableCellsContainBlockLevelElements> option is set to 0 (the
581 default), then this function is, effectively, a no-op - and just calls the
582 default C<RunMyRules> function.
585 sub RunMyRulesCreole {
586 # See documentation for the "$CreoleIsTableCellBol" variable, above.
587 my $creole_is_table_cell_bol_last = $CreoleIsTableCellBol;
588 $bol = 1 if $CreoleIsTableCellBol;
589 my $html = RunMyRulesCreoleOld(@_);
590 $CreoleIsTableCellBol = '' if $creole_is_table_cell_bol_last;
595 =head2 CreoleRuleRecursive
597 Calls C<CreoleRule> on the passed string, from within some existing call to
598 C<CreoleRule>. This function ensures, among other safeties, that the
599 C<CreoleRule> function is not recursed into more than once.
602 sub CreoleRuleRecursive {
604 return $markup if $CreoleRuleRecursing; # avoid infinite loops
605 local $CreoleRuleRecursing = 1;
606 local $bol = 0; # prevent block level element handling
608 # Preserve global variables.
609 my ($oldpos, $old_) = (pos, $_);
610 my @oldHtmlStack = @HtmlStack;
611 my @oldHtmlAttrStack = @HtmlAttrStack;
613 # Reset global variables.
615 @HtmlStack = @HtmlAttrStack = ();
617 my ($html, $html_creole) = ('', '');
619 # The contents of this loop are, in part, hacked from the guts of Oddmuse's
620 # ApplyRules() function. We cannot simply call that function, as it "cleans"
621 # the HTML converted from the text passed to it, rather than returns that
624 if ($html_creole = CreoleRule(@_) or
625 ($CreoleIsCreoleAddition and # try "creoleaddition.pl", too.
626 $html_creole = CreoleAdditionRule(@_))) {
627 $html .= $html_creole;
629 elsif (m/\G&([a-z]+|#[0-9]+|#x[a-fA-F0-9]+);/cg) { # entity references
635 elsif ( m/\G([A-Za-z\x{0080}-\x{fffd}]+([ \t]+[a-z\x{0080}-\x{fffd}]+)*[ \t]+)/cg
636 or m/\G([A-Za-z\x{0080}-\x{fffd}]+)/cg
638 $html .= $1; # multiple words but do not match http://foo
643 # Restore global variables, in reverse order.
644 @HtmlAttrStack = @oldHtmlAttrStack;
645 @HtmlStack = @oldHtmlStack;
646 ($_, pos) = ($old_, $oldpos);
648 # Allow entrance into this function, again.
649 $CreoleRuleRecursing = 0;
654 =head1 COPYRIGHT AND LICENSE
656 The information below applies to everything in this distribution,
659 Copyleft 2008 by Brian Curry <http://raiazome.com>.
660 Copyright 2008 by Weakish Jiang <weakish@gmail.com>.
661 Copyright 2006, 2007 by Alex Schroeder <alex@gnu.org>.
663 This program is free software; you can redistribute it and/or modify
664 it under the terms of the GNU General Public License as published by
665 the Free Software Foundation; either version 3 of the License, or
666 (at your option) any later version.
668 This program is distributed in the hope that it will be useful,
669 but WITHOUT ANY WARRANTY; without even the implied warranty of
670 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
671 GNU General Public License for more details.
673 You should have received a copy of the GNU General Public License
674 along with this program. If not, see L<http://www.gnu.org/licenses/>.