1<?php 2 3namespace dokuwiki\test\Parsing\ParserMode; 4 5use dokuwiki\Parsing\ParserMode\GfmStrongUnderscore; 6 7/** 8 * Tests for GFM strong emphasis via double underscores (`__text__`). 9 */ 10class GfmStrongUnderscoreTest extends ParserTestBase 11{ 12 public function setUp(): void 13 { 14 parent::setUp(); 15 $this->setSyntax('md'); 16 } 17 18 public function testBasic() 19 { 20 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 21 $this->P->parse('Foo __Bar__ Baz'); 22 23 $calls = [ 24 ['document_start', []], 25 ['p_open', []], 26 ['cdata', ["\nFoo "]], 27 ['strong_open', []], 28 ['cdata', ['Bar']], 29 ['strong_close', []], 30 ['cdata', [' Baz']], 31 ['p_close', []], 32 ['document_end', []], 33 ]; 34 $this->assertCalls($calls, $this->H->calls); 35 } 36 37 public function testSingleCharacter() 38 { 39 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 40 $this->P->parse('__x__'); 41 42 $modes = array_column($this->H->calls, 0); 43 $this->assertContains('strong_open', $modes); 44 $this->assertContains('strong_close', $modes); 45 } 46 47 public function testMultipleWords() 48 { 49 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 50 $this->P->parse('__one two three__'); 51 52 $modes = array_column($this->H->calls, 0); 53 $this->assertContains('strong_open', $modes); 54 } 55 56 public function testIntrawordDoesNotOpen() 57 { 58 // `foo__bar__` — opening `__` intraword (preceded by `o`). 59 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 60 $this->P->parse('foo__bar__'); 61 $this->assertNotContains('strong_open', array_column($this->H->calls, 0)); 62 } 63 64 public function testLeadingWhitespaceDoesNotOpen() 65 { 66 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 67 $this->P->parse('__ foo bar__'); 68 $this->assertNotContains('strong_open', array_column($this->H->calls, 0)); 69 } 70 71 public function testTrailingWhitespaceDoesNotClose() 72 { 73 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 74 $this->P->parse('__foo bar __'); 75 $this->assertNotContains('strong_open', array_column($this->H->calls, 0)); 76 } 77 78 public function testEmptyDelimiterDoesNotMatch() 79 { 80 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 81 $this->P->parse('____'); 82 $this->assertNotContains('strong_open', array_column($this->H->calls, 0)); 83 } 84 85 public function testMultibyteIntrawordDoesNotMatch() 86 { 87 // Cyrillic spec example: `пристаням__стремятся__` — intraword, literal. 88 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 89 $this->P->parse('пристаням__стремятся__'); 90 $this->assertNotContains('strong_open', array_column($this->H->calls, 0)); 91 } 92 93 public function testMultibyteContentInsideStrongWorks() 94 { 95 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 96 $this->P->parse('foo __für etwas__ bar'); 97 $this->assertContains('strong_open', array_column($this->H->calls, 0)); 98 $this->assertContains('strong_close', array_column($this->H->calls, 0)); 99 } 100 101 public function testDoesNotSpanParagraphBoundary() 102 { 103 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 104 $this->P->parse("__open\n\nclose__"); 105 $this->assertNotContains('strong_open', array_column($this->H->calls, 0)); 106 } 107 108 public function testSortValue() 109 { 110 $this->assertSame(70, (new GfmStrongUnderscore())->getSort()); 111 } 112 113 public function testInstructionNameIsStrong() 114 { 115 // The mode name is distinct (so it coexists with DW Strong in the 116 // lexer) but it must emit the same `strong_open`/`strong_close` 117 // instructions so the XHTML renderer outputs <strong>. 118 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 119 $this->P->parse('__x__'); 120 121 $modes = array_column($this->H->calls, 0); 122 $this->assertContains('strong_open', $modes); 123 $this->assertNotContains('gfm_strong_underscore_open', $modes); 124 } 125 126 public function testRejectedOpenerBeforeValidSpanStaysLiteral() 127 { 128 $this->P->addMode('gfm_strong_underscore', new GfmStrongUnderscore()); 129 $this->P->parse('__ foo __bar__'); 130 $this->assertContains('strong_open', array_column($this->H->calls, 0)); 131 $this->assertStringContainsString('__ foo ', $this->H->calls[2][1][0]); 132 } 133} 134