xref: /dokuwiki/inc/Parsing/ParserMode/Header.php (revision 4b31eadfd0dd82e519dd953a4cb0ad079114879d)
1be906b56SAndreas Gohr<?php
2be906b56SAndreas Gohr
3be906b56SAndreas Gohrnamespace dokuwiki\Parsing\ParserMode;
4be906b56SAndreas Gohr
571096e46SAndreas Gohruse dokuwiki\Parsing\Handler;
671096e46SAndreas Gohr
7be906b56SAndreas Gohrclass Header extends AbstractMode
8be906b56SAndreas Gohr{
9be906b56SAndreas Gohr    /** @inheritdoc */
1071096e46SAndreas Gohr    public function getSort()
1171096e46SAndreas Gohr    {
1271096e46SAndreas Gohr        return 50;
1371096e46SAndreas Gohr    }
1471096e46SAndreas Gohr
1571096e46SAndreas Gohr    /** @inheritdoc */
16be906b56SAndreas Gohr    public function connectTo($mode)
17be906b56SAndreas Gohr    {
18*4b31eadfSAndreas Gohr        // The leading (?<=\n) anchors the heading to the start of a line (the
19*4b31eadfSAndreas Gohr        // Parser prepends a newline, so the first line matches too). It is a
20*4b31eadfSAndreas Gohr        // lookbehind, so the newline stays out of the match and the reported
21*4b31eadfSAndreas Gohr        // position lands on the heading's first character — keeping any blank
22*4b31eadfSAndreas Gohr        // line above it in the previous section. The heading must occupy its
23*4b31eadfSAndreas Gohr        // own line: only whitespace may surround the `=…=` run, so a
24*4b31eadfSAndreas Gohr        // `== foo ==` sequence that follows other text mid-line stays plain
25*4b31eadfSAndreas Gohr        // text. We're not picky about the closing `=`, two are enough.
26be906b56SAndreas Gohr        $this->Lexer->addSpecialPattern(
27*4b31eadfSAndreas Gohr            '(?<=\n)[ \t]*={2,}[^\n]+={2,}[ \t]*(?=\n)',
28be906b56SAndreas Gohr            $mode,
29be906b56SAndreas Gohr            'header'
30be906b56SAndreas Gohr        );
31be906b56SAndreas Gohr    }
32be906b56SAndreas Gohr
33be906b56SAndreas Gohr    /** @inheritdoc */
3471096e46SAndreas Gohr    public function handle($match, $state, $pos, Handler $handler)
35be906b56SAndreas Gohr    {
3671096e46SAndreas Gohr        // get level and title
3771096e46SAndreas Gohr        $title = trim($match);
3871096e46SAndreas Gohr        $level = 7 - strspn($title, '=');
3971096e46SAndreas Gohr        if ($level < 1) $level = 1;
4071096e46SAndreas Gohr        $title = trim($title, '=');
4171096e46SAndreas Gohr        $title = trim($title);
4271096e46SAndreas Gohr
4371096e46SAndreas Gohr        if ($handler->getStatus('section')) $handler->addCall('section_close', [], $pos);
4471096e46SAndreas Gohr
4571096e46SAndreas Gohr        $handler->addCall('header', [$title, $level, $pos], $pos);
4671096e46SAndreas Gohr
4771096e46SAndreas Gohr        $handler->addCall('section_open', [$level], $pos);
4871096e46SAndreas Gohr        $handler->setStatus('section', true);
4971096e46SAndreas Gohr        return true;
50be906b56SAndreas Gohr    }
51be906b56SAndreas Gohr}
52