xref: /dokuwiki/_test/tests/Parsing/ParserMode/GfmEmphasisTest.php (revision 13a62f810fbd091d15ab734b467eaec0a6bf829a)
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'] = 'md';
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 with DokuWiki's underline syntax;
149        // GfmEmphasisUnderscore handles `_` separately when MD-preferred.
150        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
151        $this->P->parse('foo _bar_ baz');
152        $calls = [
153            ['document_start', []],
154            ['p_open', []],
155            ['cdata', ["\nfoo _bar_ baz"]],
156            ['p_close', []],
157            ['document_end', []],
158        ];
159        $this->assertCalls($calls, $this->H->calls);
160    }
161
162    function testMultilineEmphasis()
163    {
164        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
165        $this->P->parse("*line\nline\nline*");
166        $calls = [
167            ['document_start', []],
168            ['p_open', []],
169            ['cdata', ["\n"]],
170            ['emphasis_open', []],
171            ['cdata', ["line\nline\nline"]],
172            ['emphasis_close', []],
173            ['cdata', ['']],
174            ['p_close', []],
175            ['document_end', []],
176        ];
177        $this->assertCalls($calls, $this->H->calls);
178    }
179
180    function testModeNameIsDistinctFromInstructionName()
181    {
182        // The lexer mode is registered as 'gfm_emphasis' (to avoid collision
183        // with DW Emphasis), but instructions are 'emphasis_open/close'
184        // so the existing XHTML renderer emits <em>.
185        $mode = new GfmEmphasis();
186        $this->assertSame(80, $mode->getSort());
187    }
188
189    function testDoesNotSpanParagraphBoundary()
190    {
191        // An unclosed `*` followed by a blank line must stay literal — the
192        // entry pattern's lookahead is paragraph-boundary-safe.
193        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
194        $this->P->parse("*open\n\nclose*");
195        $modes = array_column($this->H->calls, 0);
196        $this->assertNotContains('emphasis_open', $modes,
197            'GfmEmphasis must not open when the closing `*` is past a blank line');
198    }
199
200    function testAllowsSingleNewline()
201    {
202        // Single newlines are fine inside emphasis (multi-line emphasis).
203        $this->P->addMode('gfm_emphasis', new GfmEmphasis());
204        $this->P->parse("*open\nclose*");
205        $modes = array_column($this->H->calls, 0);
206        $this->assertContains('emphasis_open', $modes,
207            'GfmEmphasis must still match across a single newline');
208    }
209}
210