1<?php 2 3namespace dokuwiki\Parsing\ParserMode; 4 5use dokuwiki\Parsing\Handler; 6 7/** 8 * GFM / CommonMark em-wrapping-strong via triple asterisks: `***text***`. 9 * 10 * Renders as <em><strong>text</strong></em>. Only the exact 3+3 symmetric 11 * variant is supported. Longer symmetric runs (`****foo****`, 12 * `******foo******`) or asymmetric runs (`***foo**`) require CommonMark's 13 * full delimiter-pairing algorithm and are out of scope. 14 * 15 * Sort 65 is below Strong (70) so this mode wins the lexer race for 16 * `***...***` patterns. 17 */ 18class GfmEmphasisStrong extends AbstractFormatting 19{ 20 /** @inheritdoc */ 21 public function getSort() 22 { 23 return 65; 24 } 25 26 /** @inheritdoc */ 27 protected function getModeName(): string 28 { 29 return 'gfm_emphasis_strong'; 30 } 31 32 /** @inheritdoc */ 33 protected function getEntryPattern(): string 34 { 35 // Broken down: 36 // (?<!\*) — opener not preceded by `*` (so we 37 // don't match inside `****...` runs) 38 // \*\*\* — exactly three opening `*` 39 // (?=[^\s*]) — next body char: not whitespace, not `*` 40 // (flanking-opener rule) 41 return '(?<!\*)\*\*\*(?=[^\s*])'; 42 } 43 44 /** @inheritdoc */ 45 protected function getExitPattern(): string 46 { 47 return '(?<=[^\s])\*\*\*(?!\*)'; 48 } 49 50 /** 51 * Emit em wrapping strong (and their closers in reverse order). 52 * Overridden because AbstractFormatting's default emits a single 53 * open/close pair — we need two each. 54 * 55 * @inheritdoc 56 */ 57 public function handle($match, $state, $pos, Handler $handler) 58 { 59 switch ($state) { 60 case DOKU_LEXER_ENTER: 61 $handler->addCall('emphasis_open', [], $pos); 62 $handler->addCall('strong_open', [], $pos); 63 break; 64 case DOKU_LEXER_EXIT: 65 $handler->addCall('strong_close', [], $pos); 66 $handler->addCall('emphasis_close', [], $pos); 67 break; 68 case DOKU_LEXER_UNMATCHED: 69 $handler->addCall('cdata', [$match], $pos); 70 break; 71 } 72 return true; 73 } 74} 75