xref: /dokuwiki/_test/tests/Parsing/ParserMode/GfmEmphasisTest.php (revision 8ed75a23932353c18b43f67323808e9a662f532a)
1<?php
2
3namespace dokuwiki\test\Parsing\ParserMode;
4
5use dokuwiki\Parsing\ModeRegistry;
6use dokuwiki\Parsing\ParserMode\GfmEmphasis;
7
8/**
9 * Tests for the GFM asterisk emphasis mode (`*text*`).
10 */
11class GfmEmphasisTest extends ParserTestBase
12{
13    public function setUp(): void
14    {
15        parent::setUp();
16        global $conf;
17        $conf['syntax'] = 'markdown';
18        ModeRegistry::reset();
19    }
20
21    public function tearDown(): void
22    {
23        ModeRegistry::reset();
24        parent::tearDown();
25    }
26
27    function testBasicAsterisk()
28    {
29        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
30        $this->P->parse('Foo *Bar* Baz');
31        $calls = [
32            ['document_start', []],
33            ['p_open', []],
34            ['cdata', ["\nFoo "]],
35            ['emphasis_open', []],
36            ['cdata', ['Bar']],
37            ['emphasis_close', []],
38            ['cdata', [' Baz']],
39            ['p_close', []],
40            ['document_end', []],
41        ];
42        $this->assertCalls($calls, $this->H->calls);
43    }
44
45    function testSingleCharacter()
46    {
47        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
48        $this->P->parse('foo *b* bar');
49        $calls = [
50            ['document_start', []],
51            ['p_open', []],
52            ['cdata', ["\nfoo "]],
53            ['emphasis_open', []],
54            ['cdata', ['b']],
55            ['emphasis_close', []],
56            ['cdata', [' bar']],
57            ['p_close', []],
58            ['document_end', []],
59        ];
60        $this->assertCalls($calls, $this->H->calls);
61    }
62
63    function testMultipleWords()
64    {
65        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
66        $this->P->parse('*three four five*');
67        $calls = [
68            ['document_start', []],
69            ['p_open', []],
70            ['cdata', ["\n"]],
71            ['emphasis_open', []],
72            ['cdata', ['three four five']],
73            ['emphasis_close', []],
74            ['cdata', ['']],
75            ['p_close', []],
76            ['document_end', []],
77        ];
78        $this->assertCalls($calls, $this->H->calls);
79    }
80
81    function testTwoSeparateEmphasisOnOneLine()
82    {
83        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
84        $this->P->parse('*one* and *two*');
85        $calls = [
86            ['document_start', []],
87            ['p_open', []],
88            ['cdata', ["\n"]],
89            ['emphasis_open', []],
90            ['cdata', ['one']],
91            ['emphasis_close', []],
92            ['cdata', [' and ']],
93            ['emphasis_open', []],
94            ['cdata', ['two']],
95            ['emphasis_close', []],
96            ['cdata', ['']],
97            ['p_close', []],
98            ['document_end', []],
99        ];
100        $this->assertCalls($calls, $this->H->calls);
101    }
102
103    function testUnmatchedOpenerDoesNotEmphasise()
104    {
105        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
106        $this->P->parse('foo *bar with no closer');
107        $calls = [
108            ['document_start', []],
109            ['p_open', []],
110            ['cdata', ["\nfoo *bar with no closer"]],
111            ['p_close', []],
112            ['document_end', []],
113        ];
114        $this->assertCalls($calls, $this->H->calls);
115    }
116
117    function testOpenerFollowedBySpaceDoesNotEmphasise()
118    {
119        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
120        $this->P->parse('foo * bar* baz');
121        $calls = [
122            ['document_start', []],
123            ['p_open', []],
124            ['cdata', ["\nfoo * bar* baz"]],
125            ['p_close', []],
126            ['document_end', []],
127        ];
128        $this->assertCalls($calls, $this->H->calls);
129    }
130
131    function testEmptyDelimiterDoesNotEmphasise()
132    {
133        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
134        $this->P->parse('foo ** bar');
135        $calls = [
136            ['document_start', []],
137            ['p_open', []],
138            ['cdata', ["\nfoo ** bar"]],
139            ['p_close', []],
140            ['document_end', []],
141        ];
142        $this->assertCalls($calls, $this->H->calls);
143    }
144
145    function testUnderscoreIsNotEmphasised()
146    {
147        // GfmEmphasis handles `*` only — `_` is reserved to avoid the
148        // `__underline__` conflict. See SPEC.md.
149        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
150        $this->P->parse('foo _bar_ baz');
151        $calls = [
152            ['document_start', []],
153            ['p_open', []],
154            ['cdata', ["\nfoo _bar_ baz"]],
155            ['p_close', []],
156            ['document_end', []],
157        ];
158        $this->assertCalls($calls, $this->H->calls);
159    }
160
161    function testMultilineEmphasis()
162    {
163        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
164        $this->P->parse("*line\nline\nline*");
165        $calls = [
166            ['document_start', []],
167            ['p_open', []],
168            ['cdata', ["\n"]],
169            ['emphasis_open', []],
170            ['cdata', ["line\nline\nline"]],
171            ['emphasis_close', []],
172            ['cdata', ['']],
173            ['p_close', []],
174            ['document_end', []],
175        ];
176        $this->assertCalls($calls, $this->H->calls);
177    }
178
179    function testModeNameIsDistinctFromInstructionName()
180    {
181        // The lexer mode is registered as 'gfm_emphasis' (to avoid collision
182        // with DW Emphasis), but instructions are 'emphasis_open/close'
183        // so the existing XHTML renderer emits <em>.
184        $mode = new GfmEmphasis();
185        $this->assertSame(80, $mode->getSort());
186    }
187
188    function testDoesNotSpanParagraphBoundary()
189    {
190        // An unclosed `*` followed by a blank line must stay literal — the
191        // entry pattern's lookahead is paragraph-boundary-safe.
192        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
193        $this->P->parse("*open\n\nclose*");
194        $modes = array_column($this->H->calls, 0);
195        $this->assertNotContains('emphasis_open', $modes,
196            'GfmEmphasis must not open when the closing `*` is past a blank line');
197    }
198
199    function testAllowsSingleNewline()
200    {
201        // Single newlines are fine inside emphasis (multi-line emphasis).
202        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
203        $this->P->parse("*open\nclose*");
204        $modes = array_column($this->H->calls, 0);
205        $this->assertContains('emphasis_open', $modes,
206            'GfmEmphasis must still match across a single newline');
207    }
208}
209