1<?php 2 3namespace dokuwiki\Parsing\ParserMode; 4 5use dokuwiki\Parsing\Handler; 6 7/** 8 * GFM hard line break: two-or-more trailing spaces, or a single 9 * backslash, immediately before a non-final newline. 10 * 11 * Both delimiter forms land in one mode because they share semantics 12 * (emit linebreak), share the block-boundary rule (no break at the 13 * end of a paragraph or other block), and share the next-line 14 * leading-whitespace consumption (GFM strips it). Keeping all hard- 15 * break logic in one pattern is cheaper than two and matches GFM 16 * spec section 6.7 directly. 17 * 18 * Bypass inside code spans and fenced blocks falls out for free: 19 * those are whole-span PROTECTED / FORMATTING modes that capture 20 * their body in one regex match, so SUBSTITION patterns never see 21 * the inner text — same mechanism that exempts GfmEscape from 22 * code spans. 23 * 24 * No collision with the existing DokuWiki Linebreak mode (also at 25 * sort 140): DW's pattern is a literal double backslash `\\`, 26 * unrelated to either GFM delimiter form. In mixed syntax settings 27 * both modes can load and the leftmost match wins position-by- 28 * position. GfmEscape (sort 5) does not steal the backslash form 29 * either: its pattern requires the next char to be ASCII 30 * punctuation, and `\n` is not punctuation. 31 */ 32class GfmLinebreak extends AbstractMode 33{ 34 /** @inheritdoc */ 35 public function getSort() 36 { 37 return 140; 38 } 39 40 /** @inheritdoc */ 41 public function connectTo($mode) 42 { 43 // (?:[ ]{2,}|\\) two+ spaces OR one backslash 44 // \n the line ending 45 // (?![ \t]*(?:\n|\z)) not at a paragraph break or EOF 46 // [ \t]* swallow leading WS of the next line 47 $this->Lexer->addSpecialPattern( 48 '(?:[ ]{2,}|\\\\)\n(?![ \t]*(?:\n|\z))[ \t]*', 49 $mode, 50 'gfm_linebreak' 51 ); 52 } 53 54 /** @inheritdoc */ 55 public function handle($match, $state, $pos, Handler $handler) 56 { 57 $handler->addCall('linebreak', [], $pos); 58 return true; 59 } 60} 61