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