18ed75a23SAndreas Gohr<?php 28ed75a23SAndreas Gohr 38ed75a23SAndreas Gohrnamespace dokuwiki\test\Parsing\ParserMode; 48ed75a23SAndreas Gohr 58ed75a23SAndreas Gohruse dokuwiki\Parsing\ParserMode\GfmBacktickDouble; 68ed75a23SAndreas Gohr 78ed75a23SAndreas Gohr/** 88ed75a23SAndreas Gohr * Tests for the GFM double-backtick code-span mode. 98ed75a23SAndreas Gohr * 108ed75a23SAndreas Gohr * The whole point of this length is being able to embed a lone 118ed75a23SAndreas Gohr * backtick in inline code — input ``foo`bar`` renders as 128ed75a23SAndreas Gohr * <code>foo`bar</code>. Combined with the edge-space strip rule, 138ed75a23SAndreas Gohr * the boundaries can hold backticks too: input `` `foo` `` 148ed75a23SAndreas Gohr * renders as <code>`foo`</code>. 158ed75a23SAndreas Gohr */ 168ed75a23SAndreas Gohrclass GfmBacktickDoubleTest extends ParserTestBase 178ed75a23SAndreas Gohr{ 188ed75a23SAndreas Gohr public function setUp(): void 198ed75a23SAndreas Gohr { 208ed75a23SAndreas Gohr parent::setUp(); 21*47a02a10SAndreas Gohr $this->setSyntax('md'); 228ed75a23SAndreas Gohr } 238ed75a23SAndreas Gohr 248ed75a23SAndreas Gohr function testBasicSpan() 258ed75a23SAndreas Gohr { 268ed75a23SAndreas Gohr $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble()); 278ed75a23SAndreas Gohr $this->P->parse('foo ``bar`` baz'); 288ed75a23SAndreas Gohr $calls = [ 298ed75a23SAndreas Gohr ['document_start', []], 308ed75a23SAndreas Gohr ['p_open', []], 318ed75a23SAndreas Gohr ['cdata', ["\nfoo "]], 328ed75a23SAndreas Gohr ['monospace_open', []], 338ed75a23SAndreas Gohr ['unformatted', ['bar']], 348ed75a23SAndreas Gohr ['monospace_close', []], 358ed75a23SAndreas Gohr ['cdata', [' baz']], 368ed75a23SAndreas Gohr ['p_close', []], 378ed75a23SAndreas Gohr ['document_end', []], 388ed75a23SAndreas Gohr ]; 398ed75a23SAndreas Gohr $this->assertCalls($calls, $this->H->calls); 408ed75a23SAndreas Gohr } 418ed75a23SAndreas Gohr 428ed75a23SAndreas Gohr function testAllowsInteriorSingleBacktick() 438ed75a23SAndreas Gohr { 448ed75a23SAndreas Gohr // GFM example 349. Input ``foo`bar`` — a lone backtick in the 458ed75a23SAndreas Gohr // body cannot be a valid n=2 closer, so it stays as content. 468ed75a23SAndreas Gohr $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble()); 478ed75a23SAndreas Gohr $this->P->parse('``foo`bar``'); 488ed75a23SAndreas Gohr $calls = [ 498ed75a23SAndreas Gohr ['document_start', []], 508ed75a23SAndreas Gohr ['p_open', []], 518ed75a23SAndreas Gohr ['cdata', ["\n"]], 528ed75a23SAndreas Gohr ['monospace_open', []], 538ed75a23SAndreas Gohr ['unformatted', ['foo`bar']], 548ed75a23SAndreas Gohr ['monospace_close', []], 558ed75a23SAndreas Gohr ['cdata', ['']], 568ed75a23SAndreas Gohr ['p_close', []], 578ed75a23SAndreas Gohr ['document_end', []], 588ed75a23SAndreas Gohr ]; 598ed75a23SAndreas Gohr $this->assertCalls($calls, $this->H->calls); 608ed75a23SAndreas Gohr } 618ed75a23SAndreas Gohr 628ed75a23SAndreas Gohr function testStripsEdgeSpaces() 638ed75a23SAndreas Gohr { 648ed75a23SAndreas Gohr // GFM example 339. Input `` foo ` bar `` — one leading and one 658ed75a23SAndreas Gohr // trailing space stripped; the interior lone backtick stays. 668ed75a23SAndreas Gohr $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble()); 678ed75a23SAndreas Gohr $this->P->parse('`` foo ` bar ``'); 688ed75a23SAndreas Gohr $calls = [ 698ed75a23SAndreas Gohr ['document_start', []], 708ed75a23SAndreas Gohr ['p_open', []], 718ed75a23SAndreas Gohr ['cdata', ["\n"]], 728ed75a23SAndreas Gohr ['monospace_open', []], 738ed75a23SAndreas Gohr ['unformatted', ['foo ` bar']], 748ed75a23SAndreas Gohr ['monospace_close', []], 758ed75a23SAndreas Gohr ['cdata', ['']], 768ed75a23SAndreas Gohr ['p_close', []], 778ed75a23SAndreas Gohr ['document_end', []], 788ed75a23SAndreas Gohr ]; 798ed75a23SAndreas Gohr $this->assertCalls($calls, $this->H->calls); 808ed75a23SAndreas Gohr } 818ed75a23SAndreas Gohr 828ed75a23SAndreas Gohr function testConvertsNewlinesToSpaces() 838ed75a23SAndreas Gohr { 848ed75a23SAndreas Gohr // GFM example 345: newlines inside a span become single spaces, 858ed75a23SAndreas Gohr // then edge-space stripping applies to the normalized body. 868ed75a23SAndreas Gohr $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble()); 878ed75a23SAndreas Gohr $this->P->parse("``\nfoo\nbar \nbaz\n``"); 888ed75a23SAndreas Gohr $modes = array_column($this->H->calls, 0); 898ed75a23SAndreas Gohr $this->assertContains('monospace_open', $modes); 908ed75a23SAndreas Gohr 918ed75a23SAndreas Gohr $unformatted = array_values(array_filter( 928ed75a23SAndreas Gohr $this->H->calls, 938ed75a23SAndreas Gohr static fn($c) => $c[0] === 'unformatted' 948ed75a23SAndreas Gohr )); 958ed75a23SAndreas Gohr $this->assertCount(1, $unformatted); 968ed75a23SAndreas Gohr $this->assertSame('foo bar baz', $unformatted[0][1][0]); 978ed75a23SAndreas Gohr } 988ed75a23SAndreas Gohr 998ed75a23SAndreas Gohr function testAllWhitespaceBodyIsPreserved() 1008ed75a23SAndreas Gohr { 1018ed75a23SAndreas Gohr $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble()); 1028ed75a23SAndreas Gohr $this->P->parse('a `` `` b'); 1038ed75a23SAndreas Gohr $calls = [ 1048ed75a23SAndreas Gohr ['document_start', []], 1058ed75a23SAndreas Gohr ['p_open', []], 1068ed75a23SAndreas Gohr ['cdata', ["\na "]], 1078ed75a23SAndreas Gohr ['monospace_open', []], 1088ed75a23SAndreas Gohr ['unformatted', [' ']], 1098ed75a23SAndreas Gohr ['monospace_close', []], 1108ed75a23SAndreas Gohr ['cdata', [' b']], 1118ed75a23SAndreas Gohr ['p_close', []], 1128ed75a23SAndreas Gohr ['document_end', []], 1138ed75a23SAndreas Gohr ]; 1148ed75a23SAndreas Gohr $this->assertCalls($calls, $this->H->calls); 1158ed75a23SAndreas Gohr } 1168ed75a23SAndreas Gohr 1178ed75a23SAndreas Gohr function testEmptyDelimiterDoesNotMatch() 1188ed75a23SAndreas Gohr { 1198ed75a23SAndreas Gohr // A run of four backticks — the length-boundary guards reject it 1208ed75a23SAndreas Gohr // as an n=2 opener followed immediately by an n=2 closer with 1218ed75a23SAndreas Gohr // empty body. 1228ed75a23SAndreas Gohr $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble()); 1238ed75a23SAndreas Gohr $this->P->parse('foo ```` bar'); 1248ed75a23SAndreas Gohr $modes = array_column($this->H->calls, 0); 1258ed75a23SAndreas Gohr $this->assertNotContains('monospace_open', $modes, 1268ed75a23SAndreas Gohr 'Run of 4 backticks must stay literal'); 1278ed75a23SAndreas Gohr } 1288ed75a23SAndreas Gohr 1298ed75a23SAndreas Gohr function testSortValue() 1308ed75a23SAndreas Gohr { 1318ed75a23SAndreas Gohr // Shares the n=1 sort — the length-boundary guards on both modes 1328ed75a23SAndreas Gohr // mean they never compete for the same input anyway. 1338ed75a23SAndreas Gohr $mode = new GfmBacktickDouble(); 1348ed75a23SAndreas Gohr $this->assertSame(165, $mode->getSort()); 1358ed75a23SAndreas Gohr } 1368ed75a23SAndreas Gohr} 137