Replace on save and Replace on edit

Summary: How to use $ROSPatterns and $ROEPatterns?
Version: N/A
Categories: Markup, PHP55
Discussion: ROSPatterns-Talk

Question

How do I use $ROSPatterns and $ROEPatterns? What can I use them for? Show me some examples that work please?

Answer

The ROS (Replace On Save) array defines a pattern as key and a text which should replace it when saving an edited text. The $ROSPatterns are enabled by placing them in the local/config.php file.

The ROE (Replace On Edit) array defines a pattern as key and a text which should replace it both when opening a page for editing and when saving an edited text. The $ROEPatterns are enabled by placing them in the local/config.php file. $ROEPatterns uses the same syntax as $ROSPatterns, in the examples below you can use one or the other.

In general
$ROSPatterns ["text to search for"] = "text to replace with";

The "text to search for" is searched and replaced using the PHP preg_replace function, thus the pattern has to use the preg_replace syntax.

Note about PHP 5.5

In PHP 5.5 the /e evaluation flag with the function preg_replace() was deprecated. PmWiki 2.2.56 and later allow you to place a callback function name as a replacement; this function will be called with the array of matches as argument and will return the replacement text:

Example for PHP < 5.5 and with /e flag:

  $ROSPatterns['/\\(:rand (\\d+) (\\d+):\\)/e'] = 'rand($1, $2)';

Example for PHP 5.5+ without an /e flag:

  $ROSPatterns['/\\(:rand (\\d+) (\\d+):\\)/'] = 'myrand';
  function myrand($m) { return rand($m[1], $m[2]); }

Examples

Here is an example of how you could change the author signature time format:

 $ROSPatterns['/(?<!~)~~~~(?!~)/']
    = "[[~$Author]] ".strftime('%Y-%m-%d %H:%M',$Now); # ~~~~  creates "[[~JaneDoe]] 2013-12-31 12:55"

(To change the time format everywhere on the wiki - RecentChanges and footers - see $TimeFmt.)

You can use a replace on save pattern to assist you when converting HTML to wiki. The following patterns work

# replace both <i> and </i>, upper and lower case
$ROSPatterns ["/<\\/?i>/i"]    = "''";  

# replace both <b> and </b>, upper and lower case
$ROSPatterns ["/<\\/?b>/i"]    = "'''";  

# replace <em>, upper and lower case, markup must be enabled in config.php
$ROSPatterns ["/<em>/i"]       = "'~";   

# replace </em>, upper and lower case, markup must be enabled in config.php
$ROSPatterns ["/<\\/em>/i"]    = "~'";  

# replace <strong>, upper and lower case, markup must be enabled in config.php
$ROSPatterns ["/<strong>/i"]   = "'*";  

# replace </strong>, upper and lower case, markup must be enabled in config.php
$ROSPatterns ["/<\\/strong>/i"] = "*'"; 

# replace <sup>, upper and lower case
$ROSPatterns ["/<sup>/i"]      = "'^";   

# replace </sup>, upper and lower case
$ROSPatterns ["/<\\/sup>/i"]   = "^'";   

# replace <sub>, upper and lower case
$ROSPatterns ["/<sub>/i"]      = "'_";   

# replace </sub>, upper and lower case
$ROSPatterns ["/<\\/sub>/i"]   = "_'";   

# replace both <br> and <br />, upper and lower case
$ROSPatterns ["/<br\\s*\\/?>/i"] = "[[<]]"; 

# replace both <p> and </p>, upper and lower case
$ROSPatterns ["/<\\/?p>/i"]    = "\n\n";   

# replace html links with the [[link|text]] markup
$ROSPatterns ['/<\\s*?a.+?href\\s*?=\\s*?["\'](.*?)["\'].*?>(.*?)<\/a>/sim'] = '[[$1|$2]]';   

# extract the image link from the <img ...> tag
$ROSPatterns ['/<\\s*?img.+?src\\s*?=\\s*?["\'](.*?)["\'].*?>/sim'] = '$1'; 

# replace <h1> and </h1>, upper and lower case
$ROSPatterns["/<h1\\s*>/i"] = "\n!"; 
$ROSPatterns["/<\\/h1\\s*>/i"] = "";

Replace Curly Quotes

Use this to replace curly quotation marks:

$ROSPatterns ['/\x{201C}/u'] = '"';
$ROSPatterns ['/\x{201D}/u'] = '"';
$ROSPatterns ['/\x{2018}/u'] = "'";
$ROSPatterns ['/\x{2019}/u'] = "'";

Useful for templates

Suppose you had a page named Site.NewPageTemplate and wanted to have the page creation date auto-filled when creating a new page. One way to do this is to add something like monthdayyear to the template and add the following to a local configuration file:

## ROEPattern to replace text when editing a page
if($pagename != 'Site.NewPageTemplate') # not if editing a template
  $ROEPatterns['/\\[-monthdayyear-\\]/'] = strftime('[-%B %e, %Y-]');

When editing a new page that was populated with the content from Site.NewPageTemplate, the monthdayyear will be replaced with the current date in the form of April 15, 2010. This keeps the user from having to add the current date to a page and doesn't affect future edits of that page.

From an answer given by Petko on the user mailing list. Ian MacGregor

Turning off ROS patterns

PmWiki comes with two author signature patterns built in to the core: ~~~ (link to Author's profile) and ~~~~ (link to Author's profile followed by posting time). To turn these off, for example so you can put them literally on a template page, you can put this in a configuration file:

 
if (strncmp($pagename,"New-",4)==0 ) # if editing a page whose name begins with "New-"
  $EnableAuthorSignature = 0;

Turning off other ROS patterns should be done by unsetting them after they have been defined (later in config.php or in Group.Page.php), e.g.:

  unset($ROSPatterns['/pattern/i']); # -OR-
  unset($ROSPatterns);

The only other ROS pattern defined in the core is the one that replaces (:encrypt password:) with $1$4K4zTCCH$AHvCbktIMUMdmMf/fOu400.

To show the literal text that is used as an ROS pattern on a page such as this one, that hasn't turned off ROS patterns, you can disrupt the pattern by inserting [==] in the text. For example, show ~~~ using this markup: ~[==]~~

Notes

More patterns will be added to cater for other simple HTML constructs.

  • This recipe was last tested on PmWiki version: 2.11

Releases

Add these patterns to the bottom of your local/config.php

Comments

The following test cases were used

<i>italic</i> <I>ITALIC</I>

bre<br>ak    br<br />eak    BRE<BR>AK    BR<BR />EAK    BRE<BR  />EAK

<b>bolD</B> <B>Bold</b>

<EM>em</em>

<sup>sup</sup>erscript <sub>sub</sub>script

<strong>strong</STRONG>

This is a simple <p>paragraph</p> sort of.

See Also

$ROEPatterns For replacing text when the edit form is loaded rather than when it is saved
Cookbook:QuickReplace Quickly define replacement texts in wiki pages, and use them as markup or during page save.
Cookbook:ConvertHTML Convert an HTML page to PmWiki markup

Contributors

Simon
Anno

Incorrect Links

 
 $ROSPatterns["/\\[{2}([^\/|\\[\\]]*?)(\/){0,1}([^\/|\\[\\]]*?)\\. 
 ([^|\\]\\[]*?)\\]{2}/i"] =
  	"[[$1$2$3 $4|$3. $4]]";

The explanation of the pattern:

  Match the character "[" literally «\[{2}»
     Exactly 2 times «{2}»
  Match the regular expression below and capture its match into 
backreference number 1 «([^/|\[\]]*?)»
     Match a single character NOT present in the list below «[^/|\[\]]*?»
        Between zero and unlimited times, as few times as possible, 
expanding as needed (lazy) «*?»
        One of the characters "/|" «/|»
        A [ character «\[»
        A ] character «\]»
  Match the regular expression below and capture its match into 
backreference number 2 «(/){0,1}»
     Between zero and one times, as many times as possible, giving back 
as needed (greedy) «{0,1}»
     Match the character "/" literally «/»
  Match the regular expression below and capture its match into 
backreference number 3 «([^/|\[\]]*?)»
     Match a single character NOT present in the list below «[^/|\[\]]*?»
        Between zero and unlimited times, as few times as possible, 
expanding as needed (lazy) «*?»
        One of the characters "/|" «/|»
        A [ character «\[»
        A ] character «\]»
  Match the character "." literally «\.»
  Match the character " " literally « »
  Match the regular expression below and capture its match into 
backreference number 4 «([^|\]\[]*?)»
     Match a single character NOT present in the list below «[^|\]\[]*?»
        Between zero and unlimited times, as few times as possible, 
expanding as needed (lazy) «*?»
        The character "|" «|»
        A ] character «\]»
        A [ character «\[»
  Match the character "]" literally «\]{2}»
     Exactly 2 times «{2}»

email from Anno

Special Characters

Beware of default encoding mismatching when trying to handle special characters. For example:

$ROSPatterns ["/\x{2026}/u"] = "&hellip;";

Should change a typed ellipsis into an html entity … -- but when I was EDITING the wiki, my browser's default encoding was WESTERN ISO-Latin-1 (no idea why!). So not only didn't the typed ellipsis character (option-: on the Mac) match the unicode, but this code would throw an error and wipe all contents from the page. Changing my browser's default encoding to UTF-8 solved the issue, but this is a USER-END problem, so using ROSPatterns on special characters can hurt, since character codes are a user-end issue. :/

And that means if I type a ™ in the pattern match /™/ (presumably to change it to &trade;) that it will only match if someone types in that character in the same encoding that I used in the PHP file.

XES August 16, 2010, at 09:21 AM

User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.