As an actual example, the following class converts the CSS popup menu you get against the post name into a HTML select list that contains the same options.
class PostMenuRewriter implements MarkupRewriter {
public function process($markupText)
{
$this->postMenu = array();
// replace the hidden <div> containing the post menu and get the options
$markupText = preg_replace_callback(
'@<!-- post ([0-9]+) popup menu -->.*?<!-- / post [0-9]+ popup menu -->@s',
array(&$this, 'reworkPostMenu'),
$markupText
);
// replace the inline <script> that binds the menu to the post and replace with options
$markupText = preg_replace_callback(
'@<script\s+type="text/javascript">\s+vbmenu_register\("postmenu_([0-9]+)",\s+true\);\s+</script>@',
array(&$this, 'insertMenu'),
$markupText
);
$this->postMenu = null;
return $markupText;
}
private function reworkPostMenu($matches)
{
// called in pass 1: grab the post menu options and store them by post Id for pass 2
$postId = $matches[1];
$markupText=str_replace('rel=""nofollow"",'',$matches[0]);
$matches=array();
preg_match_all(
'@<a href=""(.*?)"\s*>(.*?)</a>@",
$markupText,
$matches
);
$content = '<select onchange="if(this.value!=\'\'){window.location=this.value;}"><option value="" selected>-- choose action --</option>';
foreach($matches[1] as $n => $url) {
$content .= '<option value="' . $url . '">' . $matches[2][$n] . '</option>';
}
$content .= '</select>';
$this->postMenu[$postId] = $content;
return '';
}
private function insertMenu($matches)
{
// called in pass 2: replace the redundant postmenu_XXX inline script with our select list menu
$postId = $matches[1];
return $this->postMenu[$postId];
}
private $postMenu = array();
}