xref: /dokuwiki/_test/tests/Parsing/ParserMode/PreformattedTest.php (revision c2248fdabf88ebc41fb7cdff1ab9df02279eed2b)
1<?php
2
3namespace dokuwiki\test\Parsing\ParserMode;
4
5use dokuwiki\Parsing\ParserMode\Code;
6use dokuwiki\Parsing\ParserMode\Eol;
7use dokuwiki\Parsing\ParserMode\File;
8use dokuwiki\Parsing\ParserMode\Header;
9use dokuwiki\Parsing\ParserMode\Listblock;
10use dokuwiki\Parsing\ParserMode\Preformatted;
11
12class PreformattedTest extends ParserTestBase
13{
14
15    function testFile() {
16        $this->P->addMode('file',new File());
17        $this->P->parse('Foo <file>testing</file> Bar');
18        $calls = [
19            ['document_start',[]],
20            ['p_open',[]],
21            ['cdata',["\n".'Foo ']],
22            ['p_close',[]],
23            ['file',['testing',null,null]],
24            ['p_open',[]],
25            ['cdata',['Bar']],
26            ['p_close',[]],
27            ['document_end',[]],
28        ];
29
30        $this->assertCalls($calls, $this->H->calls);
31    }
32
33    function testCode() {
34        $this->P->addMode('code',new Code());
35        $this->P->parse('Foo <code>testing</code> Bar');
36        $calls = [
37            ['document_start',[]],
38            ['p_open',[]],
39            ['cdata',["\n".'Foo ']],
40            ['p_close',[]],
41            ['code',['testing', null, null]],
42            ['p_open',[]],
43            ['cdata',['Bar']],
44            ['p_close',[]],
45            ['document_end',[]],
46        ];
47        $this->assertCalls($calls, $this->H->calls);
48    }
49
50    function testCodeWhitespace() {
51        $this->P->addMode('code',new Code());
52        $this->P->parse("Foo <code \n>testing</code> Bar");
53        $calls = [
54            ['document_start',[]],
55            ['p_open',[]],
56            ['cdata',["\n".'Foo ']],
57            ['p_close',[]],
58            ['code',['testing', null, null]],
59            ['p_open',[]],
60            ['cdata',['Bar']],
61            ['p_close',[]],
62            ['document_end',[]],
63        ];
64        $this->assertCalls($calls, $this->H->calls);
65    }
66
67    function testCodeLang() {
68        $this->P->addMode('code',new Code());
69        $this->P->parse("Foo <code php>testing</code> Bar");
70        $calls = [
71            ['document_start',[]],
72            ['p_open',[]],
73            ['cdata',["\n".'Foo ']],
74            ['p_close',[]],
75            ['code',['testing', 'php', null]],
76            ['p_open',[]],
77            ['cdata',['Bar']],
78            ['p_close',[]],
79            ['document_end',[]],
80        ];
81        $this->assertCalls($calls, $this->H->calls);
82    }
83
84    function testPreformatted() {
85        $this->P->addMode('preformatted',new Preformatted());
86        $this->P->parse("F  oo\n  x  \n    y  \nBar\n");
87        $calls = [
88            ['document_start',[]],
89            ['p_open',[]],
90            ['cdata',["\nF  oo"]],
91            ['p_close',[]],
92            ['preformatted',["x  \n  y  "]],
93            ['p_open',[]],
94            ['cdata',["\nBar"]],
95            ['p_close',[]],
96            ['document_end',[]],
97        ];
98        $this->assertCalls($calls, $this->H->calls);
99    }
100
101    function testPreformattedWinEOL() {
102        $this->P->addMode('preformatted',new Preformatted());
103        $this->P->parse("F  oo\r\n  x  \r\n    y  \r\nBar\r\n");
104        $calls = [
105            ['document_start',[]],
106            ['p_open',[]],
107            ['cdata',["\nF  oo"]],
108            ['p_close',[]],
109            ['preformatted',["x  \n  y  "]],
110            ['p_open',[]],
111            ['cdata',["\nBar"]],
112            ['p_close',[]],
113            ['document_end',[]],
114        ];
115        $this->assertCalls($calls, $this->H->calls);
116    }
117
118    function testPreformattedTab() {
119        $this->P->addMode('preformatted',new Preformatted());
120        $this->P->parse("F  oo\n\tx\t\n\t\ty\t\nBar\n");
121        $calls = [
122            ['document_start',[]],
123            ['p_open',[]],
124            ['cdata',["\nF  oo"]],
125            ['p_close',[]],
126            ['preformatted',["x\t\n\ty\t"]],
127            ['p_open',[]],
128            ['cdata',["\nBar"]],
129            ['p_close',[]],
130            ['document_end',[]],
131        ];
132        $this->assertCalls($calls, $this->H->calls);
133    }
134
135    function testPreformattedTabWinEOL() {
136        $this->P->addMode('preformatted',new Preformatted());
137        $this->P->parse("F  oo\r\n\tx\t\r\n\t\ty\t\r\nBar\r\n");
138        $calls = [
139            ['document_start',[]],
140            ['p_open',[]],
141            ['cdata',["\nF  oo"]],
142            ['p_close',[]],
143            ['preformatted',["x\t\n\ty\t"]],
144            ['p_open',[]],
145            ['cdata',["\nBar"]],
146            ['p_close',[]],
147            ['document_end',[]],
148        ];
149        $this->assertCalls($calls, $this->H->calls);
150    }
151
152    function testPreformattedList() {
153        // Listblock (sort 10) must be added before Preformatted (sort 20) so
154        // the resulting PCRE alternation matches the canonical mode order.
155        // PCRE picks the first alternative that matches at a given position,
156        // and an indented bullet line like "  - x" matches both modes at the
157        // same offset; Listblock has to come first to win the tie.
158        $this->P->addMode('listblock',new Listblock());
159        $this->P->addMode('preformatted',new Preformatted());
160        $this->P->parse("  - x \n  * y \nF  oo\n  x  \n    y  \n  -X\n  *Y\nBar\n");
161        $calls = [
162            ['document_start',[]],
163            ['listo_open',[]],
164            ['listitem_open',[1]],
165            ['listcontent_open',[]],
166            ['cdata',[" x "]],
167            ['listcontent_close',[]],
168            ['listitem_close',[]],
169            ['listo_close',[]],
170            ['listu_open',[]],
171            ['listitem_open',[1]],
172            ['listcontent_open',[]],
173            ['cdata',[" y "]],
174            ['listcontent_close',[]],
175            ['listitem_close',[]],
176            ['listu_close',[]],
177            ['p_open',[]],
178            ['cdata',["F  oo"]],
179            ['p_close',[]],
180            ['preformatted',["x  \n  y  \n-X\n*Y"]],
181            ['p_open',[]],
182            ['cdata',["\nBar"]],
183            ['p_close',[]],
184            ['document_end',[]],
185        ];
186        $this->assertCalls($calls, $this->H->calls);
187    }
188
189
190    function testMarkdownPreferredUsesFourSpaces() {
191        // In `md` and `md+dw` settings the indent threshold is 4,
192        // matching GFM's indented code block rule. Lines with only 2-3
193        // leading spaces stay as paragraph text.
194        global $conf;
195        $conf['syntax'] = 'md';
196        $this->P->addMode('preformatted', new Preformatted());
197        $this->P->parse("F  oo\n    x  \n      y  \nBar\n");
198        $calls = [
199            ['document_start', []],
200            ['p_open', []],
201            ['cdata', ["\nF  oo"]],
202            ['p_close', []],
203            ['preformatted', ["x  \n  y  "]],
204            ['p_open', []],
205            ['cdata', ["\nBar"]],
206            ['p_close', []],
207            ['document_end', []],
208        ];
209        $this->assertCalls($calls, $this->H->calls);
210    }
211
212    function testMarkdownPreferredRejectsTwoSpaces() {
213        // 2-space indent in MD-preferred mode does NOT trigger preformatted.
214        global $conf;
215        $conf['syntax'] = 'md';
216        $this->P->addMode('preformatted', new Preformatted());
217        $this->P->parse("F  oo\n  x\nBar\n");
218        $modes = array_column($this->H->calls, 0);
219        $this->assertNotContains('preformatted', $modes,
220            '2-space indent must not trigger preformatted when Markdown is preferred');
221    }
222
223    function testMarkdownPreferredTabStillTriggers() {
224        // Tab is a trigger regardless of the space threshold.
225        global $conf;
226        $conf['syntax'] = 'md';
227        $this->P->addMode('preformatted', new Preformatted());
228        $this->P->parse("F  oo\n\tx\nBar\n");
229        $modes = array_column($this->H->calls, 0);
230        $this->assertContains('preformatted', $modes,
231            'A single tab must still trigger preformatted in MD-preferred mode');
232    }
233
234    function testPreformattedPlusHeaderAndEol() {
235        // Note that EOL must come after preformatted!
236        $this->P->addMode('preformatted',new Preformatted());
237        $this->P->addMode('header',new Header());
238        $this->P->addMode('eol',new Eol());
239        $this->P->parse("F  oo\n  ==Test==\n    y  \nBar\n");
240        $calls = [
241            ['document_start',[]],
242            ['p_open',[]],
243            ['cdata',["F  oo"]],
244            ['p_close',[]],
245            ['preformatted',["==Test==\n  y  "]],
246            ['p_open',[]],
247            ['cdata',['Bar']],
248            ['p_close',[]],
249            ['document_end',[]],
250        ];
251        $this->assertCalls($calls, $this->H->calls);
252    }
253}
254