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