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