xref: /dokuwiki/inc/Parsing/ParserMode/Header.php (revision 884caed926ca0aa0af6ce3f34ae3aa7317a3361a)
1<?php
2
3namespace dokuwiki\Parsing\ParserMode;
4
5use dokuwiki\Parsing\Handler;
6
7class Header extends AbstractMode
8{
9    /** @inheritdoc */
10    public function getSort()
11    {
12        return 50;
13    }
14
15    /** @inheritdoc */
16    public function connectTo($mode)
17    {
18        // The leading (?<=\n) anchors the heading to the start of a line (the
19        // Parser prepends a newline, so the first line matches too). It is a
20        // lookbehind, so the newline stays out of the match and the reported
21        // position lands on the heading's first character — keeping any blank
22        // line above it in the previous section. The heading must occupy its
23        // own line: only whitespace may surround the `=…=` run, so a
24        // `== foo ==` sequence that follows other text mid-line stays plain
25        // text. We're not picky about the closing `=`, two are enough.
26        $this->Lexer->addSpecialPattern(
27            '(?<=\n)[ \t]*={2,}[^\n]+={2,}[ \t]*(?=\n)',
28            $mode,
29            'header'
30        );
31    }
32
33    /** @inheritdoc */
34    public function handle($match, $state, $pos, Handler $handler)
35    {
36        // get level and title
37        $title = trim($match);
38        $level = 7 - strspn($title, '=');
39        if ($level < 1) $level = 1;
40        $title = trim($title, '=');
41        $title = trim($title);
42
43        if ($handler->getStatus('section')) $handler->addCall('section_close', [], $pos);
44
45        $handler->addCall('header', [$title, $level, $pos], $pos);
46
47        $handler->addCall('section_open', [$level], $pos);
48        $handler->setStatus('section', true);
49        return true;
50    }
51}
52