xref: /dokuwiki/_test/tests/Parsing/ParserMode/GfmBacktickDoubleTest.php (revision 47a02a102092be9e1e6f1ddaf158bdfffdb13d4f)
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