*/
class action_plugin_numberedheadings extends DokuWiki_Action_Plugin
{
/**
* Registers a callback function for a given event
*/
public function register(Doku_Event_Handler $controller)
{
$controller->register_hook(
'PARSER_HANDLER_DONE', 'BEFORE', $this, 'numbering', []
);
if ($this->getConf('fancy')) {
$controller->register_hook(
'RENDERER_CONTENT_POSTPROCESS', 'AFTER', $this, 'decorateTieredNumber'
);
}
}
/**
* PARSER_HANDLER_DONE event handler
* convert plugin instruction to header
*/
public function numbering(Doku_Event $event)
{
// load helper object
static $numbering;
isset($numbering) || $numbering = $this->loadHelper($this->getPluginName());
$instructions =& $event->data->calls;
foreach ($instructions as $k => &$ins) {
if ($ins[0] == 'plugin' && $ins[1][0] == 'numberedheadings') {
// initialise variables to be extracted from data array
// that was compacted in handle() process
unset($dash, $level, $number, $title, $format);
extract($ins[1][1]);
if (!isset($dash)) { // not numbered headings
// set tier1 only
$numbering->setTier1($level);
//unset($instructions[$k]);
continue;
}
// auto-detect the first tier (Tier1) level
$tier1 = $numbering->getTier1();
if (!$tier1) {
$tier1 = $this->getConf('tier1') ?: $level;
$numbering->setTier1($tier1);
}
$tier = $level - $tier1 +1;
// non-visible numbered headings, marked with '--'
if ($dash > 1) {
// set the heading counter only if number seems meaningful
if ($number !== '') {
$numbering->setHeadingCounter($level, $number);
}
if (isset($format)) {
// set numbering format of current tier (and subtiers) in the page
$numbering->setTierFormat($format, $tier);
} elseif ($dash > 2 || $number === '' && $title === '' && $tier == 1) {
// reset numbering feature
// the first tier (Tier1) level should be decided in next match
$numbering->setTier1();
$numbering->setTierFormat();
$numbering->setHeadingCounter();
}
//unset($instructions[$k]);
continue;
}
// set the heading counter
$numbering->setHeadingCounter($level, $number);
// build tiered numbers for hierarchical headings
$tieredNumbers = $numbering->getTieredNumbers($level);
if ($tieredNumbers) {
// append double spaces after tiered number to distinguish title
$tieredNumbers .= $this->getConf('fancy') ? ' ' : ' ';
}
$text = $tieredNumbers.$title;
// rewrite plugin call to header
$ins[0] = 'header';
$ins[1] = [$text, $level, $ins[2]];
}
}
unset($ins);
// reset numbering feature prior to process other pages
$numbering->setTier1();
$numbering->setTierFormat();
$numbering->setHeadingCounter();
}
/**
* RENDERER_CONTENT_POSTPROCESS
* enclose tiered numbers of hierarchical headings in span tag
*/
public function decorateTieredNumber(Doku_Event $event)
{
if ($event->data[0] == 'xhtml') {
$search = '#()(.+?)( )(?=.*?)#';
$replacement = '${1}${2}'."\t";
$event->data[1] = preg_replace($search, $replacement, $event->data[1]);
}
}
}