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