xref: /dokuwiki/inc/Parsing/ParserMode/Preformatted.php (revision b1c59bed2e3645a1f5f11438cdbe7d1596f4a3a4)
1be906b56SAndreas Gohr<?php
2be906b56SAndreas Gohr
3be906b56SAndreas Gohrnamespace dokuwiki\Parsing\ParserMode;
4be906b56SAndreas Gohr
571096e46SAndreas Gohruse dokuwiki\Parsing\Handler;
671096e46SAndreas Gohruse dokuwiki\Parsing\Handler\Preformatted as PreformattedHandler;
77958e698SAndreas Gohruse dokuwiki\Parsing\ModeRegistry;
87958e698SAndreas Gohr
9be906b56SAndreas Gohrclass Preformatted extends AbstractMode
10be906b56SAndreas Gohr{
11be906b56SAndreas Gohr    /** @inheritdoc */
1271096e46SAndreas Gohr    public function getSort()
1371096e46SAndreas Gohr    {
1471096e46SAndreas Gohr        return 20;
1571096e46SAndreas Gohr    }
1671096e46SAndreas Gohr
17*b1c59bedSAndreas Gohr    /**
18*b1c59bedSAndreas Gohr     * Number of leading spaces that trigger a preformatted block.
19*b1c59bedSAndreas Gohr     *
20*b1c59bedSAndreas Gohr     * DokuWiki's historical value is 2 spaces; Markdown uses 4. When
21*b1c59bedSAndreas Gohr     * `$conf['syntax']` is `markdown` or `md+dw` (Markdown preferred),
22*b1c59bedSAndreas Gohr     * we flip to 4 so indented code blocks match GFM. A single tab is
23*b1c59bedSAndreas Gohr     * always a trigger regardless of the space threshold.
24*b1c59bedSAndreas Gohr     */
25*b1c59bedSAndreas Gohr    protected function getIndentWidth(): int
26*b1c59bedSAndreas Gohr    {
27*b1c59bedSAndreas Gohr        global $conf;
28*b1c59bedSAndreas Gohr        $syntax = $conf['syntax'] ?? 'dokuwiki';
29*b1c59bedSAndreas Gohr        return in_array($syntax, ['markdown', 'md+dw'], true) ? 4 : 2;
30*b1c59bedSAndreas Gohr    }
31*b1c59bedSAndreas Gohr
3271096e46SAndreas Gohr    /** @inheritdoc */
33be906b56SAndreas Gohr    public function connectTo($mode)
34be906b56SAndreas Gohr    {
357958e698SAndreas Gohr        $markers = ModeRegistry::getInstance()->getLineStartMarkers();
367958e698SAndreas Gohr        $lookahead = $markers ? '(?![' . implode('', $markers) . '])' : '';
377958e698SAndreas Gohr
38*b1c59bedSAndreas Gohr        $indent = str_repeat(' ', $this->getIndentWidth());
39*b1c59bedSAndreas Gohr
40*b1c59bedSAndreas Gohr        $this->Lexer->addEntryPattern('\n' . $indent . $lookahead, $mode, 'preformatted');
417958e698SAndreas Gohr        $this->Lexer->addEntryPattern('\n\t' . $lookahead, $mode, 'preformatted');
42be906b56SAndreas Gohr
43259e91d9SAndreas Gohr        // match continuation lines inside the preformatted block
44*b1c59bedSAndreas Gohr        $this->Lexer->addPattern('\n' . $indent, 'preformatted');
45be906b56SAndreas Gohr        $this->Lexer->addPattern('\n\t', 'preformatted');
46be906b56SAndreas Gohr    }
47be906b56SAndreas Gohr
48be906b56SAndreas Gohr    /** @inheritdoc */
49be906b56SAndreas Gohr    public function postConnect()
50be906b56SAndreas Gohr    {
51be906b56SAndreas Gohr        $this->Lexer->addExitPattern('\n', 'preformatted');
52be906b56SAndreas Gohr    }
53be906b56SAndreas Gohr
54be906b56SAndreas Gohr    /** @inheritdoc */
5571096e46SAndreas Gohr    public function handle($match, $state, $pos, Handler $handler)
56be906b56SAndreas Gohr    {
5771096e46SAndreas Gohr        switch ($state) {
5871096e46SAndreas Gohr            case DOKU_LEXER_ENTER:
5971096e46SAndreas Gohr                $handler->setCallWriter(new PreformattedHandler($handler->getCallWriter()));
6071096e46SAndreas Gohr                $handler->addCall('preformatted_start', [], $pos);
6171096e46SAndreas Gohr                break;
6271096e46SAndreas Gohr            case DOKU_LEXER_EXIT:
6371096e46SAndreas Gohr                $handler->addCall('preformatted_end', [], $pos);
6471096e46SAndreas Gohr                /** @var PreformattedHandler $reWriter */
6571096e46SAndreas Gohr                $reWriter = $handler->getCallWriter();
6671096e46SAndreas Gohr                $handler->setCallWriter($reWriter->process());
6771096e46SAndreas Gohr                break;
6871096e46SAndreas Gohr            case DOKU_LEXER_MATCHED:
6971096e46SAndreas Gohr                $handler->addCall('preformatted_newline', [], $pos);
7071096e46SAndreas Gohr                break;
7171096e46SAndreas Gohr            case DOKU_LEXER_UNMATCHED:
7271096e46SAndreas Gohr                $handler->addCall('preformatted_content', [$match], $pos);
7371096e46SAndreas Gohr                break;
7471096e46SAndreas Gohr        }
7571096e46SAndreas Gohr
7671096e46SAndreas Gohr        return true;
77be906b56SAndreas Gohr    }
78be906b56SAndreas Gohr}
79