|
CustomMarkupadministrators (intermediate)
IntroductionPmWiki's markup translation engine is handled by a set of rules; each rule searches for a specific pattern in the markup text and replaces it with some replacement text. Internally, this is accomplished by using PHP's "preg_replace" function. Rules are added to the translation engine via PmWiki's Markup() or Markup_e() functions, which look like Markup($name, $when, $pattern, $replace); # OR Markup_e($name, $when, $pattern, $replace); where For example, here's the code that creates the rule for Markup("em", "inline", "/''(.*?)''/", "<em>$1</em>");
Basically this statement says to create a rule called "em" to be performed with the other "inline" markups, and the rule replaces any text inside two pairs of single quotes with the same text ($1) surrounded by The first two parameters to Markup() are used to specify the sequence in which rules should be applied. The first parameter provides a name for a rule -- " The second parameter says that this rule is to be done along with the other "inline" markups. PmWiki divides the translation process into a number of phases: _begin start of translation 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 This argument is normally specified as a left-angle bracket ("before") or a right-angle bracket ("after") followed by the name of another rule. Thus, specifying "inline" for the second parameter says that this rule should be applied when the other "inline" rules are being performed. If we want a rule to be performed with the directives -- i.e., before inline rules are processed, we would specify "directives" or "<inline" for the second parameter. A significant rule in terms of ordering is "{$var}" which substitutes variables -- if you say "<{$var}" then your markup will be processed before variables are substituted whereas if you say ">{$var}" then your markup will be processed after variables are substituted.
The third parameter is a Perl-compatible regular expression. Basically, it is a slash, a regular expression, another slash, and a set of optional modifiers. The example uses the pattern string The fourth parameter is the replacement text that should be inserted instead of the marked-up wikitext. You can use In the example, we have Here's a rule for Markup("@@", "inline", "/@@(.*?)@@/", "<code>$1</code>");
and for a Markup("comment", "directives", "/\\[:comment .*?:\\]/", '');
Okay, now how about the rule for Markup("strong", "<em", "/'''(.*?)'''/", "<strong>$1</strong>");
This creates a rule called "strong", and the second parameter "<em" says to be sure that this rule is processed before the "em" rule we defined above. If we wanted to do something after the "em" rule, we would use ">em" instead. Thus, it's possible to add rules at any point in PmWiki's markup translation process in an extensible manner. (In fact, the "inline", "block", "directives", etc., phases above are just placeholder rules used to provide an overall sequence for other rules. Thus one can use "<inline" to specify rules that should be handled before any other inline rules.) If you want to disable available markup just call e.g.: DisableMarkup("strong");
PmWiki's default markup rules are defined in the scripts/stdmarkup.php file. To see the entire translation table as the program is running, the scripts/diag.php module adds " Other common examplesDefine a custom markup to produce a specific HTML or Javascript sequenceSuppose an admin wants to have a simple " Markup('example', 'directives', '/\\(:example:\\)/', Keep("<div class='example'><p>Here is a <a target='_blank' href='http://www.example.com'>link</a> to <em>example.com</em></p></div>") );
Define a markup to call a custom function that returns contentAn 'e' option on the Markup('random', 'directives', '/\\(:random:\\)/e', "rand(1, 100)"); This calls the PHP built-in rand() function and substitutes the directive with the result. Any function can be called, including functions defined in a local customization file. Arguments can also be passed by using regular expression capturing parentheses, thus Markup('randomargs', 'directives', '/\\(:random (\\d+) (\\d+):\\)/e', "rand('$1', '$2')"); will cause the markup Note: Be very careful with the /e modifier in regular expressions; malicious authors may be able to pass strings that cause arbitrary and undesirable PHP functions to be executed.
For a PmWiki function to help with parsing arbitrary sequences of arguments and key=value pairs, see Cookbook:ParseArgs. Migration to PHP 5.5 and Markup_e()Since PHP version 5.5, the /e evaluation modifier is deprecated and some hosting providers don't allow its use. Recent versions of the PmWiki core (2.2.58 and newer) allow new ways to define markup rules without being dependent on the /e eval modifier. The historical ways to define markup rules are not removed and work, but may be incompatible with PHP 5.5 installations. Note: if your replacement pattern doesn't need evaluation, you must use Markup() like before and not Markup_e(). The following is acceptable for PHP 5.5+ (compatible with PmWiki 2.2.58+, will also work in PHP 5.4 and older)
Examples:
Other example:
The above may seem complicated, but it is actually simpler to use your own callback function: Markup('mykey', 'directives', '/\\(:mydirective (.*?) (.*?):\\)/i', 'MyFunction' ); function MyFunction($matches) { extract($GLOBALS["MarkupToHTML"]); # ... do stuff with $matches ... return $out; # or return Keep($html); } Markup for both new and old versions of PmWikiIf you want your recipe to work with PmWiki 2.2.58 and newer on PHP 5.5 and with older PmWiki+PHP versions, you can use something like this: if(function_exists('Markup_e')) { # new format, no /e Markup_e('rnd', 'directives', '/\\(:random (\\d+) (\\d+):\\)/', "rand(\$m[1], \$m[2])"); } else { # old format Markup('rnd', 'directives', '/\\(:random (\\d+) (\\d+):\\)/e', "rand($1, $2)"); } If you have any questions about the new way to define custom markup, you can ask us at the talk page? or on the mailing lists. FAQHow can I embed JavaScript into a page's output? There are several ways to do this. The Cookbook:JavaScript recipe describes a simple means for embedding static JavaScript into web pages using custom markup. For editing JavaScript directly in wiki pages (which can pose various security risks), see the JavaScript-Editable recipe. For JavaScript that is to appear in headers or footers of pages, the skin template can be modified directly, or <script> statements can be inserted using the How would I create a markup ((:nodiscussion:)) that will set a page variable ({$HideDiscussion}) which can be used by (:if enabled HideDiscussion:) in .PageActions? Add the following section of code to your config.php SDV($HideDiscussion, 0); #define var name Markup('hideDiscussion', '<{$var}', '/\\(:nodiscussion:\\)/e', 'setHideDiscussion(true)'); function setHideDiscussion($val) { global $HideDiscussion; $HideDiscussion = $val; } This will enable the It appears that (.*?) does not match newlines in these functions, making the above example inoperable if the text to be wrappen in <em> contains new lines. If you include the "s" modifier on the regular expression then the dot (.) will match newlines. Thus your regular expression will be "/STUFF(.*?)/s". That s at the very end is what you are looking for. If you start getting into multi-line regexes you may be forced to look at the m option as well - let's anchors (^ and $) match not begin/end of strings but also begin/end of lines (i.e., right before/after a newline). How can the text returned by my markup function be re-processed by the markup engine? If the result of your markup contains more markup that should be processed, you have two options. First is to select a "when" argument that is processed earlier than the markup in your result. For example, if your markup may return [[links]], your "when" argument could be How do I get started writing recipes and creating my own custom markup? (alternate) Introduction to custom markup for Beginners How do I make a rule that runs once at the end of all other rule processing? Use this statement instead of the usual
This page may have a more recent version on pmwiki.org: PmWiki:CustomMarkup, and a talk page: PmWiki:CustomMarkup-Talk. |