0, // # --> $levels['#'] + $top = 0 + 1 = 1 -->

...

'*' => 1, '=' => 2, '-' => 3, ); /** @var array used ID's */ private $usedID; public function __construct($texy) { $this->texy = $texy; $texy->addHandler('heading', array($this, 'solve')); $texy->addHandler('beforeParse', array($this, 'beforeParse')); $texy->addHandler('afterParse', array($this, 'afterParse')); $texy->registerBlockPattern( array($this, 'patternUnderline'), '#^(\S.*)'.TEXY_MODIFIER_H.'?\n' . '(\#{3,}|\*{3,}|={3,}|-{3,})$#mU', 'heading/underlined' ); $texy->registerBlockPattern( array($this, 'patternSurround'), '#^(\#{2,}+|={2,}+)(.+)'.TEXY_MODIFIER_H.'?()$#mU', 'heading/surrounded' ); } public function beforeParse() { $this->title = NULL; $this->usedID = array(); $this->TOC = array(); } /** * @param Texy * @param TexyHtml * @param bool * @return void */ public function afterParse($texy, $DOM, $isSingleLine) { if ($isSingleLine) return; if ($this->balancing === self::DYNAMIC) { $top = $this->top; $map = array(); $min = 100; foreach ($this->TOC as $item) { $level = $item['level']; if ($item['type'] === 'surrounded') { $min = min($level, $min); $top = $this->top - $min; } elseif ($item['type'] === 'underlined') { $map[$level] = $level; } } asort($map); $map = array_flip(array_values($map)); } foreach ($this->TOC as $key => $item) { if ($this->balancing === self::DYNAMIC) { if ($item['type'] === 'surrounded') { $level = $item['level'] + $top; } elseif ($item['type'] === 'underlined') { $level = $map[$item['level']] + $this->top; } else { $level = $item['level']; } $item['el']->setName('h' . min(6, max(1, $level))); $this->TOC[$key]['level'] = $level; } if ($this->generateID && empty($item['el']->attrs['id'])) { $title = trim($item['el']->toText($this->texy)); if ($title !== '') { $this->TOC[$key]['title'] = $title; $id = $this->idPrefix . Texy::webalize($title); $counter = ''; if (isset($this->usedID[$id . $counter])) { $counter = 2; while (isset($this->usedID[$id . '-' . $counter])) $counter++; $id .= '-' . $counter; } $this->usedID[$id] = TRUE; $item['el']->attrs['id'] = $id; } } } // document title if ($this->title === NULL && count($this->TOC)) { $item = reset($this->TOC); $this->title = isset($item['title']) ? $item['title'] : trim($item['el']->toText($this->texy)); } } /** * Callback for underlined heading. * * Heading .(title)[class]{style}> * ------------------------------- * * @param TexyBlockParser * @param array regexp matches * @param string pattern name * @return TexyHtml|string|FALSE */ public function patternUnderline($parser, $matches) { list(, $mContent, $mMod, $mLine) = $matches; // $matches: // [1] => ... // [2] => .(title)[class]{style}<> // [3] => ... $mod = new TexyModifier($mMod); $level = $this->levels[$mLine[0]]; return $this->texy->invokeAroundHandlers('heading', $parser, array($level, $mContent, $mod, FALSE)); } /** * Callback for surrounded heading. * * ### Heading .(title)[class]{style}> * * @param TexyBlockParser * @param array regexp matches * @param string pattern name * @return TexyHtml|string|FALSE */ public function patternSurround($parser, $matches) { list(, $mLine, $mContent, $mMod) = $matches; // [1] => ### // [2] => ... // [3] => .(title)[class]{style}<> $mod = new TexyModifier($mMod); $level = min(7, max(2, strlen($mLine))); $level = $this->moreMeansHigher ? 7 - $level : $level - 2; $mContent = rtrim($mContent, $mLine[0] . ' '); return $this->texy->invokeAroundHandlers('heading', $parser, array($level, $mContent, $mod, TRUE)); } /** * Finish invocation. * * @param TexyHandlerInvocation handler invocation * @param int 0..5 * @param string * @param TexyModifier * @param bool * @return TexyHtml */ public function solve($invocation, $level, $content, $mod, $isSurrounded) { // as fixed balancing, for block/texysource & correct decorating $el = TexyHtml::el('h' . min(6, max(1, $level + $this->top))); $mod->decorate($this->texy, $el); $el->parseLine($this->texy, trim($content)); $this->TOC[] = array( 'el' => $el, 'level' => $level, 'type' => $isSurrounded ? 'surrounded' : 'underlined', ); return $el; } }