1<?php 2 3namespace dokuwiki\test\Parsing\ParserMode; 4 5use dokuwiki\Parsing\ParserMode\Eol; 6use dokuwiki\Parsing\ParserMode\GfmHr; 7 8/** 9 * Tests for the unified horizontal-rule mode. 10 * 11 * Covers both pattern flavors: pure `dw` (4-or-more dashes only) 12 * and the wider GFM flavor that loads in `md`, `dw+md`, `md+dw` 13 * (3-or-more of `-` / `*` / `_`). No leading, trailing, or internal 14 * whitespace tolerance in either flavor. 15 */ 16class GfmHrTest extends ParserTestBase 17{ 18 /** 19 * Whether at least one `hr` call was emitted for the given input 20 * under the given syntax. Returns the call count for richer 21 * assertion messages. 22 */ 23 protected function countHrCalls(string $syntax, string $input): int 24 { 25 $this->setUp(); 26 $this->setSyntax($syntax); 27 $this->P->addMode('gfm_hr', new GfmHr()); 28 $this->P->parse($input); 29 return count(array_filter($this->H->calls, static fn($c) => $c[0] === 'hr')); 30 } 31 32 // ------------------------------------------------------------------ 33 // DW flavor (`$conf['syntax'] = 'dw'`) 34 // ------------------------------------------------------------------ 35 36 public function testDwFourDashes() 37 { 38 $this->assertSame(1, $this->countHrCalls('dw', "\n----\n")); 39 } 40 41 public function testDwManyDashes() 42 { 43 $this->assertSame(1, $this->countHrCalls('dw', "\n--------\n")); 44 } 45 46 public function testDwThreeDashesNotHr() 47 { 48 $this->assertSame(0, $this->countHrCalls('dw', "\n---\n")); 49 } 50 51 public function testDwAsterisksNotHr() 52 { 53 $this->assertSame(0, $this->countHrCalls('dw', "\n***\n")); 54 $this->assertSame(0, $this->countHrCalls('dw', "\n********\n")); 55 } 56 57 public function testDwUnderscoresNotHr() 58 { 59 $this->assertSame(0, $this->countHrCalls('dw', "\n___\n")); 60 $this->assertSame(0, $this->countHrCalls('dw', "\n_____\n")); 61 } 62 63 public function testDwLeadingSpaceNotHr() 64 { 65 $this->assertSame(0, $this->countHrCalls('dw', "\n ----\n")); 66 } 67 68 public function testDwTrailingSpaceNotHr() 69 { 70 $this->assertSame(0, $this->countHrCalls('dw', "\n---- \n")); 71 } 72 73 public function testDwInterruptsParagraph() 74 { 75 $this->setSyntax('dw'); 76 $this->P->addMode('gfm_hr', new GfmHr()); 77 $this->P->parse("Foo\n----\nBar"); 78 $calls = [ 79 ['document_start', []], 80 ['p_open', []], 81 ['cdata', ["\nFoo"]], 82 ['p_close', []], 83 ['hr', []], 84 ['p_open', []], 85 ['cdata', ["\nBar"]], 86 ['p_close', []], 87 ['document_end', []], 88 ]; 89 $this->assertCalls($calls, $this->H->calls); 90 } 91 92 // ------------------------------------------------------------------ 93 // GFM flavor (any non-`dw` syntax setting) 94 // ------------------------------------------------------------------ 95 96 public function testMdDashes() 97 { 98 foreach (['md', 'dw+md', 'md+dw'] as $syntax) { 99 $this->assertSame(1, $this->countHrCalls($syntax, "\n---\n"), 100 "syntax=$syntax: bare `---` must produce hr"); 101 } 102 } 103 104 public function testMdAsterisks() 105 { 106 foreach (['md', 'dw+md', 'md+dw'] as $syntax) { 107 $this->assertSame(1, $this->countHrCalls($syntax, "\n***\n"), 108 "syntax=$syntax: bare `***` must produce hr"); 109 } 110 } 111 112 public function testMdUnderscores() 113 { 114 foreach (['md', 'dw+md', 'md+dw'] as $syntax) { 115 $this->assertSame(1, $this->countHrCalls($syntax, "\n___\n"), 116 "syntax=$syntax: bare `___` must produce hr"); 117 } 118 } 119 120 public function testMdManyChars() 121 { 122 $this->assertSame(1, $this->countHrCalls('md', "\n--------\n")); 123 $this->assertSame(1, $this->countHrCalls('md', "\n********\n")); 124 $this->assertSame(1, $this->countHrCalls('md', "\n________\n")); 125 } 126 127 public function testMdTooFew() 128 { 129 $this->assertSame(0, $this->countHrCalls('md', "\n--\n")); 130 $this->assertSame(0, $this->countHrCalls('md', "\n**\n")); 131 $this->assertSame(0, $this->countHrCalls('md', "\n__\n")); 132 } 133 134 public function testMdInternalSpacesNotSupported() 135 { 136 $this->assertSame(0, $this->countHrCalls('md', "\n- - -\n")); 137 $this->assertSame(0, $this->countHrCalls('md', "\n* * *\n")); 138 $this->assertSame(0, $this->countHrCalls('md', "\n_ _ _\n")); 139 } 140 141 public function testMdLeadingSpaceNotSupported() 142 { 143 $this->assertSame(0, $this->countHrCalls('md', "\n ***\n")); 144 $this->assertSame(0, $this->countHrCalls('md', "\n ---\n")); 145 } 146 147 public function testMdTrailingSpaceNotSupported() 148 { 149 $this->assertSame(0, $this->countHrCalls('md', "\n--- \n")); 150 } 151 152 public function testMdMixedChars() 153 { 154 $this->assertSame(0, $this->countHrCalls('md', "\n-*-\n")); 155 $this->assertSame(0, $this->countHrCalls('md', "\n***---\n")); 156 } 157 158 public function testMdLetterMixed() 159 { 160 $this->assertSame(0, $this->countHrCalls('md', "\n---a\n")); 161 $this->assertSame(0, $this->countHrCalls('md', "\na---\n")); 162 $this->assertSame(0, $this->countHrCalls('md', "\n---a---\n")); 163 } 164 165 public function testMdInterruptsParagraph() 166 { 167 $this->setSyntax('md'); 168 $this->P->addMode('gfm_hr', new GfmHr()); 169 $this->P->addMode('eol', new Eol()); 170 $this->P->parse("Foo\n***\nbar"); 171 $modes = array_column($this->H->calls, 0); 172 $this->assertContains('hr', $modes, 173 'thematic break interrupts paragraph without blank line (spec 28)'); 174 } 175 176 // ------------------------------------------------------------------ 177 // Common 178 // ------------------------------------------------------------------ 179 180 public function testSortValue() 181 { 182 $mode = new GfmHr(); 183 $this->assertSame(160, $mode->getSort()); 184 } 185} 186