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 SUBSTITUTION patterns never see 21 * the inner text — same mechanism that exempts GfmEscape from 22 * code spans. 23 * 24 * Coexists with DokuWiki's Linebreak mode (also at sort 140). The two 25 * delimiter shapes are disjoint: GfmLinebreak takes a single `\` (or 26 * two+ spaces) before a non-final newline, DW Linebreak takes `\\` 27 * before a space, tab, or newline. 28 */ 29class GfmLinebreak extends AbstractMode 30{ 31 /** @inheritdoc */ 32 public function getSort() 33 { 34 return 140; 35 } 36 37 /** @inheritdoc */ 38 public function connectTo($mode) 39 { 40 // (?:[ ]{2,}|\\) two+ spaces OR one backslash 41 // \n the line ending 42 // (?![ \t]*(?:\n|\z)) not at a paragraph break or EOF 43 // [ \t]* swallow leading WS of the next line 44 $this->Lexer->addSpecialPattern( 45 '(?:[ ]{2,}|\\\\)\n(?![ \t]*(?:\n|\z))[ \t]*', 46 $mode, 47 'gfm_linebreak' 48 ); 49 } 50 51 /** @inheritdoc */ 52 public function handle($match, $state, $pos, Handler $handler) 53 { 54 $handler->addCall('linebreak', [], $pos); 55 return true; 56 } 57} 58