xref: /dokuwiki/_test/tests/Parsing/ParserMode/GfmBacktickDoubleTest.php (revision 8ed75a23932353c18b43f67323808e9a662f532a)
1*8ed75a23SAndreas Gohr<?php
2*8ed75a23SAndreas Gohr
3*8ed75a23SAndreas Gohrnamespace dokuwiki\test\Parsing\ParserMode;
4*8ed75a23SAndreas Gohr
5*8ed75a23SAndreas Gohruse dokuwiki\Parsing\ModeRegistry;
6*8ed75a23SAndreas Gohruse dokuwiki\Parsing\ParserMode\GfmBacktickDouble;
7*8ed75a23SAndreas Gohr
8*8ed75a23SAndreas Gohr/**
9*8ed75a23SAndreas Gohr * Tests for the GFM double-backtick code-span mode.
10*8ed75a23SAndreas Gohr *
11*8ed75a23SAndreas Gohr * The whole point of this length is being able to embed a lone
12*8ed75a23SAndreas Gohr * backtick in inline code — input ``foo`bar`` renders as
13*8ed75a23SAndreas Gohr * <code>foo`bar</code>. Combined with the edge-space strip rule,
14*8ed75a23SAndreas Gohr * the boundaries can hold backticks too: input `` `foo` ``
15*8ed75a23SAndreas Gohr * renders as <code>`foo`</code>.
16*8ed75a23SAndreas Gohr */
17*8ed75a23SAndreas Gohrclass GfmBacktickDoubleTest extends ParserTestBase
18*8ed75a23SAndreas Gohr{
19*8ed75a23SAndreas Gohr    public function setUp(): void
20*8ed75a23SAndreas Gohr    {
21*8ed75a23SAndreas Gohr        parent::setUp();
22*8ed75a23SAndreas Gohr        global $conf;
23*8ed75a23SAndreas Gohr        $conf['syntax'] = 'markdown';
24*8ed75a23SAndreas Gohr        ModeRegistry::reset();
25*8ed75a23SAndreas Gohr    }
26*8ed75a23SAndreas Gohr
27*8ed75a23SAndreas Gohr    public function tearDown(): void
28*8ed75a23SAndreas Gohr    {
29*8ed75a23SAndreas Gohr        ModeRegistry::reset();
30*8ed75a23SAndreas Gohr        parent::tearDown();
31*8ed75a23SAndreas Gohr    }
32*8ed75a23SAndreas Gohr
33*8ed75a23SAndreas Gohr    function testBasicSpan()
34*8ed75a23SAndreas Gohr    {
35*8ed75a23SAndreas Gohr        $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble());
36*8ed75a23SAndreas Gohr        $this->P->parse('foo ``bar`` baz');
37*8ed75a23SAndreas Gohr        $calls = [
38*8ed75a23SAndreas Gohr            ['document_start', []],
39*8ed75a23SAndreas Gohr            ['p_open', []],
40*8ed75a23SAndreas Gohr            ['cdata', ["\nfoo "]],
41*8ed75a23SAndreas Gohr            ['monospace_open', []],
42*8ed75a23SAndreas Gohr            ['unformatted', ['bar']],
43*8ed75a23SAndreas Gohr            ['monospace_close', []],
44*8ed75a23SAndreas Gohr            ['cdata', [' baz']],
45*8ed75a23SAndreas Gohr            ['p_close', []],
46*8ed75a23SAndreas Gohr            ['document_end', []],
47*8ed75a23SAndreas Gohr        ];
48*8ed75a23SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
49*8ed75a23SAndreas Gohr    }
50*8ed75a23SAndreas Gohr
51*8ed75a23SAndreas Gohr    function testAllowsInteriorSingleBacktick()
52*8ed75a23SAndreas Gohr    {
53*8ed75a23SAndreas Gohr        // GFM example 349. Input ``foo`bar`` — a lone backtick in the
54*8ed75a23SAndreas Gohr        // body cannot be a valid n=2 closer, so it stays as content.
55*8ed75a23SAndreas Gohr        $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble());
56*8ed75a23SAndreas Gohr        $this->P->parse('``foo`bar``');
57*8ed75a23SAndreas Gohr        $calls = [
58*8ed75a23SAndreas Gohr            ['document_start', []],
59*8ed75a23SAndreas Gohr            ['p_open', []],
60*8ed75a23SAndreas Gohr            ['cdata', ["\n"]],
61*8ed75a23SAndreas Gohr            ['monospace_open', []],
62*8ed75a23SAndreas Gohr            ['unformatted', ['foo`bar']],
63*8ed75a23SAndreas Gohr            ['monospace_close', []],
64*8ed75a23SAndreas Gohr            ['cdata', ['']],
65*8ed75a23SAndreas Gohr            ['p_close', []],
66*8ed75a23SAndreas Gohr            ['document_end', []],
67*8ed75a23SAndreas Gohr        ];
68*8ed75a23SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
69*8ed75a23SAndreas Gohr    }
70*8ed75a23SAndreas Gohr
71*8ed75a23SAndreas Gohr    function testStripsEdgeSpaces()
72*8ed75a23SAndreas Gohr    {
73*8ed75a23SAndreas Gohr        // GFM example 339. Input `` foo ` bar `` — one leading and one
74*8ed75a23SAndreas Gohr        // trailing space stripped; the interior lone backtick stays.
75*8ed75a23SAndreas Gohr        $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble());
76*8ed75a23SAndreas Gohr        $this->P->parse('`` foo ` bar ``');
77*8ed75a23SAndreas Gohr        $calls = [
78*8ed75a23SAndreas Gohr            ['document_start', []],
79*8ed75a23SAndreas Gohr            ['p_open', []],
80*8ed75a23SAndreas Gohr            ['cdata', ["\n"]],
81*8ed75a23SAndreas Gohr            ['monospace_open', []],
82*8ed75a23SAndreas Gohr            ['unformatted', ['foo ` bar']],
83*8ed75a23SAndreas Gohr            ['monospace_close', []],
84*8ed75a23SAndreas Gohr            ['cdata', ['']],
85*8ed75a23SAndreas Gohr            ['p_close', []],
86*8ed75a23SAndreas Gohr            ['document_end', []],
87*8ed75a23SAndreas Gohr        ];
88*8ed75a23SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
89*8ed75a23SAndreas Gohr    }
90*8ed75a23SAndreas Gohr
91*8ed75a23SAndreas Gohr    function testConvertsNewlinesToSpaces()
92*8ed75a23SAndreas Gohr    {
93*8ed75a23SAndreas Gohr        // GFM example 345: newlines inside a span become single spaces,
94*8ed75a23SAndreas Gohr        // then edge-space stripping applies to the normalized body.
95*8ed75a23SAndreas Gohr        $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble());
96*8ed75a23SAndreas Gohr        $this->P->parse("``\nfoo\nbar  \nbaz\n``");
97*8ed75a23SAndreas Gohr        $modes = array_column($this->H->calls, 0);
98*8ed75a23SAndreas Gohr        $this->assertContains('monospace_open', $modes);
99*8ed75a23SAndreas Gohr
100*8ed75a23SAndreas Gohr        $unformatted = array_values(array_filter(
101*8ed75a23SAndreas Gohr            $this->H->calls,
102*8ed75a23SAndreas Gohr            static fn($c) => $c[0] === 'unformatted'
103*8ed75a23SAndreas Gohr        ));
104*8ed75a23SAndreas Gohr        $this->assertCount(1, $unformatted);
105*8ed75a23SAndreas Gohr        $this->assertSame('foo bar   baz', $unformatted[0][1][0]);
106*8ed75a23SAndreas Gohr    }
107*8ed75a23SAndreas Gohr
108*8ed75a23SAndreas Gohr    function testAllWhitespaceBodyIsPreserved()
109*8ed75a23SAndreas Gohr    {
110*8ed75a23SAndreas Gohr        $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble());
111*8ed75a23SAndreas Gohr        $this->P->parse('a ``   `` b');
112*8ed75a23SAndreas Gohr        $calls = [
113*8ed75a23SAndreas Gohr            ['document_start', []],
114*8ed75a23SAndreas Gohr            ['p_open', []],
115*8ed75a23SAndreas Gohr            ['cdata', ["\na "]],
116*8ed75a23SAndreas Gohr            ['monospace_open', []],
117*8ed75a23SAndreas Gohr            ['unformatted', ['   ']],
118*8ed75a23SAndreas Gohr            ['monospace_close', []],
119*8ed75a23SAndreas Gohr            ['cdata', [' b']],
120*8ed75a23SAndreas Gohr            ['p_close', []],
121*8ed75a23SAndreas Gohr            ['document_end', []],
122*8ed75a23SAndreas Gohr        ];
123*8ed75a23SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
124*8ed75a23SAndreas Gohr    }
125*8ed75a23SAndreas Gohr
126*8ed75a23SAndreas Gohr    function testEmptyDelimiterDoesNotMatch()
127*8ed75a23SAndreas Gohr    {
128*8ed75a23SAndreas Gohr        // A run of four backticks — the length-boundary guards reject it
129*8ed75a23SAndreas Gohr        // as an n=2 opener followed immediately by an n=2 closer with
130*8ed75a23SAndreas Gohr        // empty body.
131*8ed75a23SAndreas Gohr        $this->P->addMode('gfm_backtick_double', new GfmBacktickDouble());
132*8ed75a23SAndreas Gohr        $this->P->parse('foo ```` bar');
133*8ed75a23SAndreas Gohr        $modes = array_column($this->H->calls, 0);
134*8ed75a23SAndreas Gohr        $this->assertNotContains('monospace_open', $modes,
135*8ed75a23SAndreas Gohr            'Run of 4 backticks must stay literal');
136*8ed75a23SAndreas Gohr    }
137*8ed75a23SAndreas Gohr
138*8ed75a23SAndreas Gohr    function testSortValue()
139*8ed75a23SAndreas Gohr    {
140*8ed75a23SAndreas Gohr        // Shares the n=1 sort — the length-boundary guards on both modes
141*8ed75a23SAndreas Gohr        // mean they never compete for the same input anyway.
142*8ed75a23SAndreas Gohr        $mode = new GfmBacktickDouble();
143*8ed75a23SAndreas Gohr        $this->assertSame(165, $mode->getSort());
144*8ed75a23SAndreas Gohr    }
145*8ed75a23SAndreas Gohr}
146