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 Gohr 8be906b56SAndreas Gohrclass Preformatted extends AbstractMode 9be906b56SAndreas Gohr{ 10be906b56SAndreas Gohr /** @inheritdoc */ 1171096e46SAndreas Gohr public function getSort() 1271096e46SAndreas Gohr { 1371096e46SAndreas Gohr return 20; 1471096e46SAndreas Gohr } 1571096e46SAndreas Gohr 16b1c59bedSAndreas Gohr /** 17b1c59bedSAndreas Gohr * Number of leading spaces that trigger a preformatted block. 18b1c59bedSAndreas Gohr * 19b1c59bedSAndreas Gohr * DokuWiki's historical value is 2 spaces; Markdown uses 4. When 2013a62f81SAndreas Gohr * `$conf['syntax']` is `md` or `md+dw` (Markdown preferred), 21b1c59bedSAndreas Gohr * we flip to 4 so indented code blocks match GFM. A single tab is 22b1c59bedSAndreas Gohr * always a trigger regardless of the space threshold. 23b1c59bedSAndreas Gohr */ 24b1c59bedSAndreas Gohr protected function getIndentWidth(): int 25b1c59bedSAndreas Gohr { 26b1c59bedSAndreas Gohr global $conf; 2713a62f81SAndreas Gohr return in_array($conf['syntax'], ['md', 'md+dw'], true) ? 4 : 2; 28b1c59bedSAndreas Gohr } 29b1c59bedSAndreas Gohr 3071096e46SAndreas Gohr /** @inheritdoc */ 31be906b56SAndreas Gohr public function connectTo($mode) 32be906b56SAndreas Gohr { 33b1c59bedSAndreas Gohr $indent = str_repeat(' ', $this->getIndentWidth()); 34b1c59bedSAndreas Gohr 3596d096f1SAndreas Gohr $this->Lexer->addEntryPattern('\n' . $indent, $mode, 'preformatted'); 3696d096f1SAndreas Gohr $this->Lexer->addEntryPattern('\n\t', $mode, 'preformatted'); 37be906b56SAndreas Gohr 38259e91d9SAndreas Gohr // match continuation lines inside the preformatted block 39b1c59bedSAndreas Gohr $this->Lexer->addPattern('\n' . $indent, 'preformatted'); 40be906b56SAndreas Gohr $this->Lexer->addPattern('\n\t', 'preformatted'); 41be906b56SAndreas Gohr } 42be906b56SAndreas Gohr 43be906b56SAndreas Gohr /** @inheritdoc */ 44be906b56SAndreas Gohr public function postConnect() 45be906b56SAndreas Gohr { 46*f57da51cSAndreas Gohr // Two exits: a zero-width lookahead when the next line starts with 47*f57da51cSAndreas Gohr // non-whitespace content (so the boundary \n stays in the stream 48*f57da51cSAndreas Gohr // and downstream block-level modes like GfmHr or GfmHeader can 49*f57da51cSAndreas Gohr // anchor on it), and a consuming \n fall-through for blank lines 50*f57da51cSAndreas Gohr // and end-of-input. The lookahead-only branch is registered first 51*f57da51cSAndreas Gohr // so PCRE's leftmost-first alternation prefers it whenever it 52*f57da51cSAndreas Gohr // applies; the consuming branch handles the cases where it cannot. 53*f57da51cSAndreas Gohr $this->Lexer->addExitPattern('(?=\n[^ \t\n])', 'preformatted'); 54be906b56SAndreas Gohr $this->Lexer->addExitPattern('\n', 'preformatted'); 55be906b56SAndreas Gohr } 56be906b56SAndreas Gohr 57be906b56SAndreas Gohr /** @inheritdoc */ 5871096e46SAndreas Gohr public function handle($match, $state, $pos, Handler $handler) 59be906b56SAndreas Gohr { 6071096e46SAndreas Gohr switch ($state) { 6171096e46SAndreas Gohr case DOKU_LEXER_ENTER: 6271096e46SAndreas Gohr $handler->setCallWriter(new PreformattedHandler($handler->getCallWriter())); 6371096e46SAndreas Gohr $handler->addCall('preformatted_start', [], $pos); 6471096e46SAndreas Gohr break; 6571096e46SAndreas Gohr case DOKU_LEXER_EXIT: 6671096e46SAndreas Gohr $handler->addCall('preformatted_end', [], $pos); 6771096e46SAndreas Gohr /** @var PreformattedHandler $reWriter */ 6871096e46SAndreas Gohr $reWriter = $handler->getCallWriter(); 6971096e46SAndreas Gohr $handler->setCallWriter($reWriter->process()); 7071096e46SAndreas Gohr break; 7171096e46SAndreas Gohr case DOKU_LEXER_MATCHED: 7271096e46SAndreas Gohr $handler->addCall('preformatted_newline', [], $pos); 7371096e46SAndreas Gohr break; 7471096e46SAndreas Gohr case DOKU_LEXER_UNMATCHED: 7571096e46SAndreas Gohr $handler->addCall('preformatted_content', [$match], $pos); 7671096e46SAndreas Gohr break; 7771096e46SAndreas Gohr } 7871096e46SAndreas Gohr 7971096e46SAndreas Gohr return true; 80be906b56SAndreas Gohr } 81be906b56SAndreas Gohr} 82