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',['Bar']], 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',['Bar']], 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',["Bar"]], 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',["Bar"]], 146 ['p_close',[]], 147 ['document_end',[]], 148 ]; 149 $this->assertCalls($calls, $this->H->calls); 150 } 151 152 function testPreformattedList() { 153 $this->P->addMode('preformatted',new Preformatted()); 154 $this->P->addMode('listblock',new Listblock()); 155 $this->P->parse(" - x \n * y \nF oo\n x \n y \n -X\n *Y\nBar\n"); 156 $calls = [ 157 ['document_start',[]], 158 ['listo_open',[]], 159 ['listitem_open',[1]], 160 ['listcontent_open',[]], 161 ['cdata',[" x "]], 162 ['listcontent_close',[]], 163 ['listitem_close',[]], 164 ['listo_close',[]], 165 ['listu_open',[]], 166 ['listitem_open',[1]], 167 ['listcontent_open',[]], 168 ['cdata',[" y "]], 169 ['listcontent_close',[]], 170 ['listitem_close',[]], 171 ['listu_close',[]], 172 ['p_open',[]], 173 ['cdata',["F oo"]], 174 ['p_close',[]], 175 ['preformatted',["x \n y \n-X\n*Y"]], 176 ['p_open',[]], 177 ['cdata',["Bar"]], 178 ['p_close',[]], 179 ['document_end',[]], 180 ]; 181 $this->assertCalls($calls, $this->H->calls); 182 } 183 184 185 function testMarkdownPreferredUsesFourSpaces() { 186 // In `markdown` and `md+dw` settings the indent threshold is 4, 187 // matching GFM's indented code block rule. Lines with only 2-3 188 // leading spaces stay as paragraph text. 189 global $conf; 190 $conf['syntax'] = 'markdown'; 191 $this->P->addMode('preformatted', new Preformatted()); 192 $this->P->parse("F oo\n x \n y \nBar\n"); 193 $calls = [ 194 ['document_start', []], 195 ['p_open', []], 196 ['cdata', ["\nF oo"]], 197 ['p_close', []], 198 ['preformatted', ["x \n y "]], 199 ['p_open', []], 200 ['cdata', ['Bar']], 201 ['p_close', []], 202 ['document_end', []], 203 ]; 204 $this->assertCalls($calls, $this->H->calls); 205 } 206 207 function testMarkdownPreferredRejectsTwoSpaces() { 208 // 2-space indent in MD-preferred mode does NOT trigger preformatted. 209 global $conf; 210 $conf['syntax'] = 'markdown'; 211 $this->P->addMode('preformatted', new Preformatted()); 212 $this->P->parse("F oo\n x\nBar\n"); 213 $modes = array_column($this->H->calls, 0); 214 $this->assertNotContains('preformatted', $modes, 215 '2-space indent must not trigger preformatted when Markdown is preferred'); 216 } 217 218 function testMarkdownPreferredTabStillTriggers() { 219 // Tab is a trigger regardless of the space threshold. 220 global $conf; 221 $conf['syntax'] = 'markdown'; 222 $this->P->addMode('preformatted', new Preformatted()); 223 $this->P->parse("F oo\n\tx\nBar\n"); 224 $modes = array_column($this->H->calls, 0); 225 $this->assertContains('preformatted', $modes, 226 'A single tab must still trigger preformatted in MD-preferred mode'); 227 } 228 229 function testPreformattedPlusHeaderAndEol() { 230 // Note that EOL must come after preformatted! 231 $this->P->addMode('preformatted',new Preformatted()); 232 $this->P->addMode('header',new Header()); 233 $this->P->addMode('eol',new Eol()); 234 $this->P->parse("F oo\n ==Test==\n y \nBar\n"); 235 $calls = [ 236 ['document_start',[]], 237 ['p_open',[]], 238 ['cdata',["F oo"]], 239 ['p_close',[]], 240 ['preformatted',["==Test==\n y "]], 241 ['p_open',[]], 242 ['cdata',['Bar']], 243 ['p_close',[]], 244 ['document_end',[]], 245 ]; 246 $this->assertCalls($calls, $this->H->calls); 247 } 248} 249