1<?php 2 3namespace dokuwiki\Parsing\ParserMode; 4 5use dokuwiki\Parsing\Handler; 6use dokuwiki\Parsing\Handler\Preformatted as PreformattedHandler; 7use dokuwiki\Parsing\ModeRegistry; 8 9class Preformatted extends AbstractMode 10{ 11 /** @inheritdoc */ 12 public function getSort() 13 { 14 return 20; 15 } 16 17 /** 18 * Number of leading spaces that trigger a preformatted block. 19 * 20 * DokuWiki's historical value is 2 spaces; Markdown uses 4. When 21 * `$conf['syntax']` is `markdown` or `md+dw` (Markdown preferred), 22 * we flip to 4 so indented code blocks match GFM. A single tab is 23 * always a trigger regardless of the space threshold. 24 */ 25 protected function getIndentWidth(): int 26 { 27 global $conf; 28 $syntax = $conf['syntax'] ?? 'dokuwiki'; 29 return in_array($syntax, ['markdown', 'md+dw'], true) ? 4 : 2; 30 } 31 32 /** @inheritdoc */ 33 public function connectTo($mode) 34 { 35 $markers = ModeRegistry::getInstance()->getLineStartMarkers(); 36 $lookahead = $markers ? '(?![' . implode('', $markers) . '])' : ''; 37 38 $indent = str_repeat(' ', $this->getIndentWidth()); 39 40 $this->Lexer->addEntryPattern('\n' . $indent . $lookahead, $mode, 'preformatted'); 41 $this->Lexer->addEntryPattern('\n\t' . $lookahead, $mode, 'preformatted'); 42 43 // match continuation lines inside the preformatted block 44 $this->Lexer->addPattern('\n' . $indent, 'preformatted'); 45 $this->Lexer->addPattern('\n\t', 'preformatted'); 46 } 47 48 /** @inheritdoc */ 49 public function postConnect() 50 { 51 $this->Lexer->addExitPattern('\n', 'preformatted'); 52 } 53 54 /** @inheritdoc */ 55 public function handle($match, $state, $pos, Handler $handler) 56 { 57 switch ($state) { 58 case DOKU_LEXER_ENTER: 59 $handler->setCallWriter(new PreformattedHandler($handler->getCallWriter())); 60 $handler->addCall('preformatted_start', [], $pos); 61 break; 62 case DOKU_LEXER_EXIT: 63 $handler->addCall('preformatted_end', [], $pos); 64 /** @var PreformattedHandler $reWriter */ 65 $reWriter = $handler->getCallWriter(); 66 $handler->setCallWriter($reWriter->process()); 67 break; 68 case DOKU_LEXER_MATCHED: 69 $handler->addCall('preformatted_newline', [], $pos); 70 break; 71 case DOKU_LEXER_UNMATCHED: 72 $handler->addCall('preformatted_content', [$match], $pos); 73 break; 74 } 75 76 return true; 77 } 78} 79