phpmarkuppmwiki

Multi-line markup in PmWiki


Let's say that I want to create markup to convert this:

Some text. SHOUTY Hello. Some more text.

into this:

Some text. HELLO! Some more text.

I would do this with the following PHP:

Markup('SHOUTY', 'directives',
  '/SHOUTY\\s*(.+?)\\./gs',
  'MarkupSHOUTY');

function MarkupSHOUTY($matches) {
  return mb_strtoupper($matches[1]) . '!';
}

This works for the naive test case above, but fails in actual use:

This is SHOUTY Sparta.

SHOUTY He took his vorpal sword in hand:
Long time the manxome foe he sought --
So rested he by the Tumtum tree,
And stood awhile in thought.

Don't press the button. SHOUTY Don't press it.

becomes

This is SPARTA!

SHOUTY He took his vorpal sword in hand:
Long time the manxome foe he sought --
So rested he by the Tumtum tree,
And stood awhile in thought.

Don't press the button. DON'T PRESS IT!

How can I create multi-line markup in PmWiki?


Solution

  • As you already guessed, the PmWiki's markup to html transformation is a several stages process, consisting in applying an ordered set of regular expressions matches and text replacements.

    Some Theoretical considerations

    The Markup($name, $when, $pattern, $replace) function (in pmwiki.php) is responsible to define the transformation pipeline itself and to populate it with both predefined rules (in stdmarkup.php) and your own rules you may provide in Local Configuration Files.

    The Custom Markup documentation page is describing the predefined phases as:

    _begin      start of translation
      {$var}    Page Text Variables happen here.
    fulltext    translations to be performed on the full text            
    split       conversion of the full markup text into lines to be processed
    directives  directive processing
    inline      inline markups
    links       conversion of links, url-links, and WikiWords     
    block       block markups
    style       style handling       
    _end        end of translation
    

    According to the function documentation, the Markup() parameters are defined as:

    $name
    

    The string names the rule that is inserted. If a rule of the same name already exists, then this rule is ignored.

    $when
    

    This string is used to control when a rule is to be applied relative to other rules. A specification of "<xyz" says to apply this rule prior to the rule named "xyz", while ">xyz" says to apply this rule after the rule "xyz". See CustomMarkup for more details on the order of rules.

    $pattern
    

    This string is a regular expression that is used by the translation engine to look for occurences of this rule in the markup source.

    $replace
    

    This string will replace the matched text when a match occurs, or the function name that will return the replacement text.

    Applying this to your case

    Specifying "directives" as $when placeholder leads the markup rule to be applied on the text after it already has been split into lines.

    Therefore, in order to occur on multiple lines, it should be instructed to work before the line splitting, such as:

    Markup('SHOUTY', '<split',
      '/SHOUTY\\s*(.+?)\\./gs',
      'MarkupSHOUTY');