‪TYPO3CMS  10.4
RteHtmlParserTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
22 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
23 
27 class ‪RteHtmlParserTest extends UnitTestCase
28 {
32  protected ‪$resetSingletonInstances = true;
33 
34  protected ‪$procOptions = ['overruleMode' => 'default'];
35 
40  {
41  return [
42  'Single hr' => [
43  '<hr />',
44  '<hr />',
45  ],
46  'Non-xhtml single hr' => [
47  '<hr/>',
48  '<hr />',
49  ],
50  'Double hr' => [
51  '<hr /><hr />',
52  '<hr />' . CRLF . '<hr />',
53  ],
54  'Linebreak followed by hr' => [
55  CRLF . '<hr />',
56  '<hr />',
57  ],
58  'White space followed by hr' => [
59  ' <hr />',
60  ' ' . CRLF . '<hr />',
61  ],
62  'White space followed linebreak and hr' => [
63  ' ' . CRLF . '<hr />',
64  ' ' . CRLF . '<hr />',
65  ],
66  'br followed by hr' => [
67  '<br /><hr />',
68  '<br />' . CRLF . '<hr />',
69  ],
70  'br followed by linebreak and hr' => [
71  '<br />' . CRLF . '<hr />',
72  '<br />' . CRLF . '<hr />',
73  ],
74  'Preserved div followed by hr' => [
75  '<div>Some text</div><hr />',
76  '<div>Some text</div>' . CRLF . '<hr />',
77  ],
78  'Preserved div followed by linebreak and hr' => [
79  '<div>Some text</div>' . CRLF . '<hr />',
80  '<div>Some text</div>' . CRLF . '<hr />',
81  ],
82  'h1 followed by linebreak and hr' => [
83  '<h1>Some text</h1>' . CRLF . '<hr />',
84  '<h1>Some text</h1>' . CRLF . '<hr />',
85  ],
86  'Paragraph followed by linebreak and hr' => [
87  '<p>Some text</p>' . CRLF . '<hr />',
88  '<p>Some text</p>' . CRLF . '<hr />',
89  ],
90  'Some text without HTML tags' => [
91  'Some text',
92  'Some text',
93  ],
94  'Some text followed by hr' => [
95  'Some text<hr />',
96  'Some text' . CRLF . '<hr />',
97  ],
98  'Some text followed by linebreak and hr' => [
99  'Some text' . CRLF . '<hr />',
100  'Some text' . CRLF . '<hr />',
101  ],
102  ];
103  }
104 
109  public function ‪hrTagCorrectlyTransformedOnWayToDataBase($content, $expectedResult)
110  {
111  // @todo Explicitly disabled HTML Sanitizer (since it is based on HTML5)
112  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = false;
113  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
114  $subject = new ‪RteHtmlParser($eventDispatcher);
115  self::assertEquals($expectedResult, $subject->transformTextForPersistence($content, $this->procOptions));
116  }
117 
122  {
123  return [
124  'Single hr' => [
125  '<hr />',
126  '<hr />',
127  ],
128  'Non-xhtml single hr' => [
129  '<hr/>',
130  '<hr />',
131  ],
132  'Double hr' => [
133  '<hr /><hr />',
134  '<hr />' . CRLF . '<hr />',
135  ],
136  'Linebreak followed by hr' => [
137  CRLF . '<hr />',
138  '<hr />',
139  ],
140  'White space followed by hr' => [
141  ' <hr />',
142  '<p>&nbsp;</p>' . CRLF . '<hr />',
143  ],
144  'White space followed by linebreak and hr' => [
145  ' ' . CRLF . '<hr />',
146  '<p>&nbsp;</p>' . CRLF . '<hr />',
147  ],
148  'br followed by hr' => [
149  '<br /><hr />',
150  '<p><br /></p>' . CRLF . '<hr />',
151  ],
152  'br followed by linebreak and hr' => [
153  '<br />' . CRLF . '<hr />',
154  '<p><br /></p>' . CRLF . '<hr />',
155  ],
156  'Preserved div followed by hr' => [
157  '<div>Some text</div><hr />',
158  '<div><p>Some text</p></div>' . CRLF . '<hr />',
159  ],
160  'Preserved div followed by linebreak and hr' => [
161  '<div>Some text</div>' . CRLF . '<hr />',
162  '<div><p>Some text</p></div>' . CRLF . '<hr />',
163  ],
164  'h1 followed by linebreak and hr' => [
165  '<h1>Some text</h1>' . CRLF . '<hr />',
166  '<h1>Some text</h1>' . CRLF . '<hr />',
167  ],
168  'Paragraph followed by linebreak and hr' => [
169  '<p>Some text</p>' . CRLF . '<hr />',
170  '<p>Some text</p>' . CRLF . '<hr />',
171  ],
172  'Some text followed by hr' => [
173  'Some text<hr />',
174  '<p>Some text</p>' . CRLF . '<hr />',
175  ],
176  'Some text followed by linebreak and hr' => [
177  'Some text' . CRLF . '<hr />',
178  '<p>Some text</p>' . CRLF . '<hr />',
179  ],
180  ];
181  }
182 
187  public function ‪hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRte($content, $expectedResult)
188  {
189  // @todo Explicitly disabled HTML Sanitizer (since it is based on HTML5)
190  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = false;
191  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
192  $subject = new RteHtmlParser($eventDispatcher);
193  self::assertEquals($expectedResult, $subject->transformTextForRichTextEditor($subject->transformTextForPersistence($content, $this->procOptions), $this->procOptions));
194  }
195 
200  {
201  return [
202  '<br>' => [
203  '<p>foo<br>bar</p>',
204  '<p>foo<br />bar</p>',
205  ],
206  '<br/> without white space' => [
207  '<p>foo<br/>bar</p>',
208  '<p>foo<br />bar</p>',
209  ],
210  '<br /> with whitespace' => [
211  '<p>foo<br />bar</p>',
212  '<p>foo<br />bar</p>',
213  ],
214  ];
215  }
216 
221  public function ‪brTagCorrectlyTransformedOnWayToDatabaseAndBackToRte($content, $expectedResult): void
222  {
223  // @todo Explicitly disabled HTML Sanitizer (since it is based on HTML5)
224  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = false;
225  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
226  $subject = new RteHtmlParser($eventDispatcher);
227  self::assertEquals($expectedResult, $subject->transformTextForRichTextEditor($subject->transformTextForPersistence($content, $this->procOptions), $this->procOptions));
228  }
229 
234  {
235  return [
236  'Empty string' => [
237  '',
238  '',
239  ],
240  'Linebreak' => [
241  CRLF,
242  '',
243  ],
244  'Double linebreak' => [
245  CRLF . CRLF,
246  '',
247  ],
248  'Empty paragraph' => [
249  '<p></p>',
250  CRLF,
251  ],
252  'Double empty paragraph' => [
253  '<p></p><p></p>',
254  CRLF . CRLF,
255  ],
256  'Spacing paragraph' => [
257  '<p>&nbsp;</p>',
258  CRLF,
259  ],
260  'Double spacing paragraph' => [
261  '<p>&nbsp;</p><p>&nbsp;</p>',
262  CRLF . CRLF,
263  ],
264  'Plain text' => [
265  'plain text',
266  'plain text',
267  ],
268  'Plain text followed by linebreak' => [
269  'plain text' . CRLF,
270  'plain text ',
271  ],
272  'Paragraph' => [
273  '<p>paragraph</p>',
274  '<p>paragraph</p>',
275  ],
276  'Paragraph followed by paragraph' => [
277  '<p>paragraph1</p><p>paragraph2</p>',
278  '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
279  ],
280  'Paragraph followed by paragraph, linebreak-separated' => [
281  '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
282  '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
283  ],
284  'Double spacing paragraph with text' => [
285  '<p>&nbsp;</p><p>&nbsp;</p><p>paragraph1</p>',
286  CRLF . CRLF . '<p>paragraph1</p>',
287  ],
288  'Paragraph followed by linebreak' => [
289  '<p>paragraph</p>' . CRLF,
290  '<p>paragraph</p>',
291  ],
292  'Paragraph followed by spacing paragraph' => [
293  '<p>paragraph</p><p>&nbsp;</p>',
294  '<p>paragraph</p>' . CRLF . CRLF,
295  ],
296  'Paragraph followed by spacing paragraph, linebreak-separated' => [
297  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>',
298  '<p>paragraph</p>' . CRLF . CRLF,
299  ],
300  'Paragraph followed by double spacing paragraph' => [
301  '<p>paragraph</p><p>&nbsp;</p><p>&nbsp;</p>',
302  '<p>paragraph</p>' . CRLF . CRLF . CRLF,
303  ],
304  'Paragraph followed by double spacing paragraph, linebreak-separated' => [
305  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
306  '<p>paragraph</p>' . CRLF . CRLF . CRLF,
307  ],
308  'Paragraph followed by spacing paragraph and by paragraph' => [
309  '<p>paragraph1</p><p>&nbsp;</p><p>paragraph2</p>',
310  '<p>paragraph1</p>' . CRLF . CRLF . '<p>paragraph2</p>',
311  ],
312  'Paragraph followed by spacing paragraph and by paragraph, linebreak-separated' => [
313  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
314  '<p>paragraph1</p>' . CRLF . CRLF . '<p>paragraph2</p>',
315  ],
316  'Paragraph followed by double spacing paragraph and by paragraph' => [
317  '<p>paragraph1</p><p>&nbsp;</p><p>&nbsp;</p><p>paragraph2</p>',
318  '<p>paragraph1</p>' . CRLF . CRLF . CRLF . '<p>paragraph2</p>',
319  ],
320  'Paragraph followed by double spacing paragraph and by paragraph, linebreak-separated' => [
321  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
322  '<p>paragraph1</p>' . CRLF . CRLF . CRLF . '<p>paragraph2</p>',
323  ],
324  'Paragraph followed by block' => [
325  '<p>paragraph</p><h1>block</h1>',
326  '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
327  ],
328  'Paragraph followed by block, linebreak-separated' => [
329  '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
330  '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
331  ],
332  'Paragraph followed by spacing paragraph and block' => [
333  '<p>paragraph</p><p>&nbsp;</p><h1>block</h1>',
334  '<p>paragraph</p>' . CRLF . CRLF . '<h1>block</h1>',
335  ],
336  'Paragraph followed by spacing paragraph and block, linebreak-separated' => [
337  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
338  '<p>paragraph</p>' . CRLF . CRLF . '<h1>block</h1>',
339  ],
340  'Paragraph followed by double spacing paragraph and block' => [
341  '<p>paragraph</p><p>&nbsp;</p><p>&nbsp;</p><h1>block</h1>',
342  '<p>paragraph</p>' . CRLF . CRLF . CRLF . '<h1>block</h1>',
343  ],
344  'Paragraph followed by double spacing paragraph and block, linebreak-separated' => [
345  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
346  '<p>paragraph</p>' . CRLF . CRLF . CRLF . '<h1>block</h1>',
347  ],
348  'Block followed by block' => [
349  '<h1>block1</h1><h1>block2</h1>',
350  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
351  ],
352  'Block followed by block, linebreak-separated' => [
353  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
354  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
355  ],
356  'Block followed by empty paragraph and block' => [
357  '<h1>block1</h1><p></p><h1>block2</h1>',
358  '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
359  ],
360  'Block followed by empty paragraph and block, linebreak-separated' => [
361  '<h1>block1</h1>' . CRLF . '<p></p>' . CRLF . '<h1>block2</h1>',
362  '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
363  ],
364  'Block followed by spacing paragraph' => [
365  '<h1>block1</h1><p>&nbsp;</p>',
366  '<h1>block1</h1>' . CRLF . CRLF,
367  ],
368  'Block followed by spacing paragraph, linebreak-separated' => [
369  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>',
370  '<h1>block1</h1>' . CRLF . CRLF,
371  ],
372  'Block followed by spacing paragraph and block' => [
373  '<h1>block1</h1><p>&nbsp;</p><h1>block2</h1>',
374  '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
375  ],
376  'Block followed by spacing paragraph and block, linebreak-separated' => [
377  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
378  '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
379  ],
380  'Block followed by double spacing paragraph and by block' => [
381  '<h1>block1</h1><p>&nbsp;</p><p>&nbsp;</p><h1>block2</h1>',
382  '<h1>block1</h1>' . CRLF . CRLF . CRLF . '<h1>block2</h1>',
383  ],
384  'Block followed by double spacing paragraph and by block, linebreak-separated' => [
385  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
386  '<h1>block1</h1>' . CRLF . CRLF . CRLF . '<h1>block2</h1>',
387  ],
388  'Block followed by paragraph and block' => [
389  '<h1>block1</h1><p>paragraph</p><h1>block2</h1>',
390  '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . '<h1>block2</h1>',
391  ],
392  'Block followed by paragraph and block, linebreak-separated' => [
393  '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . '<h1>block2</h1>',
394  '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . '<h1>block2</h1>',
395  ],
396  'Block followed by paragraph, spacing paragraph and block' => [
397  '<h1>block1</h1><p>paragraph</p><p>&nbsp;</p><h1>block2</h1>',
398  '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . CRLF . '<h1>block2</h1>',
399  ],
400  'Block followed by paragraph, spacing paragraph and block, linebreak-separated' => [
401  '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
402  '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . CRLF . '<h1>block2</h1>',
403  ],
404  ];
405  }
406 
411  public function ‪paragraphCorrectlyTransformedOnWayToDatabase($content, $expectedResult)
412  {
413  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
414  $subject = new RteHtmlParser($eventDispatcher);
415  self::assertEquals($expectedResult, $subject->transformTextForPersistence($content, $this->procOptions));
416  }
417 
422  {
423  return [
424  'Empty string' => [
425  '',
426  '',
427  ],
428  'Single linebreak' => [
429  CRLF,
430  '<p>&nbsp;</p>',
431  ],
432  'Double linebreak' => [
433  CRLF . CRLF,
434  '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
435  ],
436  'Triple linebreak' => [
437  CRLF . CRLF . CRLF,
438  '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
439  ],
440  'Paragraph' => [
441  'paragraph',
442  '<p>paragraph</p>',
443  ],
444  'Paragraph followed by single linebreak' => [
445  'paragraph' . CRLF,
446  '<p>paragraph</p>',
447  ],
448  'Paragraph followed by double linebreak' => [
449  'paragraph' . CRLF . CRLF,
450  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>',
451  ],
452  'Paragraph followed by triple linebreak' => [
453  'paragraph' . CRLF . CRLF . CRLF,
454  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
455  ],
456  'Paragraph followed by paragraph' => [
457  'paragraph1' . CRLF . 'paragraph2',
458  '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
459  ],
460  'Paragraph followed by double linebreak and paragraph' => [
461  'paragraph1' . CRLF . CRLF . 'paragraph2',
462  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
463  ],
464  'Paragraph followed by triple linebreak and paragraph' => [
465  'paragraph1' . CRLF . CRLF . CRLF . 'paragraph2',
466  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
467  ],
468  'Paragraph followed by block' => [
469  'paragraph<h1>block</h1>',
470  '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
471  ],
472  'Paragraph followed by linebreak and block' => [
473  'paragraph' . CRLF . '<h1>block</h1>',
474  '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
475  ],
476  'Paragraph followed by double linebreak and block' => [
477  'paragraph' . CRLF . CRLF . '<h1>block</h1>',
478  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
479  ],
480  'Paragraph followed by triple linebreak and block' => [
481  'paragraph' . CRLF . CRLF . CRLF . '<h1>block</h1>',
482  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
483  ],
484  'Block followed by block' => [
485  '<h1>block1</h1><h1>block2</h1>',
486  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
487  ],
488  'Block followed by single linebreak and block' => [
489  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
490  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
491  ],
492  'Block followed by double linebreak and block' => [
493  '<h1>block1</h1>' . CRLF . CRLF . '<h1>block2</h1>',
494  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
495  ],
496  'Block followed by triple linebreak and block' => [
497  '<h1>block1</h1>' . CRLF . CRLF . CRLF . '<h1>block2</h1>',
498  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
499  ],
500  'Block followed by paragraph and block' => [
501  '<h1>block1</h1>' . CRLF . 'paragraph' . CRLF . '<h1>block2</h1>',
502  '<h1>block1</h1>' . CRLF . '<p>paragraph</p>' . CRLF . '<h1>block2</h1>',
503  ],
504  ];
505  }
506 
511  public function ‪lineBreakCorrectlyTransformedOnWayToRTE($content, $expectedResult)
512  {
513  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
514  $subject = new RteHtmlParser($eventDispatcher);
515  self::assertEquals($expectedResult, $subject->transformTextForRichTextEditor($content, $this->procOptions));
516  }
517 
522  {
523  return [
524  'Empty string' => [
525  '',
526  '',
527  ],
528  'Empty paragraph' => [
529  '<p></p>',
530  '<p>&nbsp;</p>',
531  ],
532  'Double empty paragraph' => [
533  '<p></p><p></p>',
534  '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
535  ],
536  'Triple empty paragraph' => [
537  '<p></p><p></p><p></p>',
538  '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
539  ],
540  'Plain text' => [
541  'plain text',
542  '<p>plain text</p>',
543  ],
544  'Plain text followed by linebreak' => [
545  'plain text' . CRLF,
546  '<p>plain text </p>',
547  ],
548  'Plain text followed by paragraph' => [
549  'plain text<p>paragraph</p>',
550  '<p>plain text</p>' . CRLF . '<p>paragraph</p>',
551  ],
552  'Spacing paragraph' => [
553  '<p>&nbsp;</p>',
554  '<p>&nbsp;</p>',
555  ],
556  'Double spacing paragraph' => [
557  '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
558  '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
559  ],
560  'Paragraph' => [
561  '<p>paragraph</p>',
562  '<p>paragraph</p>',
563  ],
564  'Paragraph followed by linebreak' => [
565  '<p>paragraph</p>' . CRLF,
566  '<p>paragraph</p>',
567  ],
568  'Paragraph followed by spacing paragraph' => [
569  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>',
570  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>',
571  ],
572  'Paragraph followed by double spacing paragraph' => [
573  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
574  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>',
575  ],
576  'Paragraph followed by paragraph' => [
577  '<p>paragraph1</p><p>paragraph2</p>',
578  '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
579  ],
580  'Paragraph followed by paragraph, linebreak-separated' => [
581  '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
582  '<p>paragraph1</p>' . CRLF . '<p>paragraph2</p>',
583  ],
584  'Paragraph followed by spacing paragraph and by paragraph' => [
585  '<p>paragraph1</p><p>&nbsp;</p><p>paragraph2</p>',
586  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
587  ],
588  'Paragraph followed by spacing paragraph and by paragraph, linebreak-separated' => [
589  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
590  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
591  ],
592  'Paragraph followed by double spacing paragraph and by paragraph' => [
593  '<p>paragraph1</p><p>&nbsp;</p><p>&nbsp;</p><p>paragraph2</p>',
594  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
595  ],
596  'Paragraph followed by double spacing paragraph and by paragraph, linebreak-separated' => [
597  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
598  '<p>paragraph1</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>paragraph2</p>',
599  ],
600  'Paragraph followed by block' => [
601  '<p>paragraph</p><h1>block</h1>',
602  '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
603  ],
604  'Paragraph followed by block, linebreak-separated' => [
605  '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
606  '<p>paragraph</p>' . CRLF . '<h1>block</h1>',
607  ],
608  'Paragraph followed by spacing paragraph and by block' => [
609  '<p>paragraph</p><p>&nbsp;</p><h1>block</h1>',
610  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
611  ],
612  'Paragraph followed by spacing paragraph and by block, linebreak-separated' => [
613  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
614  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
615  ],
616  'Paragraph followed by double spacing paragraph and by block' => [
617  '<p>paragraph</p><p>&nbsp;</p><p>&nbsp;</p><h1>block</h1>',
618  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
619  ],
620  'Paragraph followed by double spacing paragraph and by block, linebreak-separated' => [
621  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
622  '<p>paragraph</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block</h1>',
623  ],
624  'Block followed by block' => [
625  '<h1>block1</h1><h1>block2</h1>',
626  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
627  ],
628  'Block followed by block, linebreak-separated' => [
629  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
630  '<h1>block1</h1>' . CRLF . '<h1>block2</h1>',
631  ],
632  'Block followed by empty paragraph and by block' => [
633  '<h1>block1</h1><p></p><h1>block2</h1>',
634  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
635  ],
636  'Block followed by empty paragraph and by block, linebreak-separated' => [
637  '<h1>block1</h1>' . CRLF . '<p></p>' . CRLF . '<h1>block2</h1>',
638  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
639  ],
640  'Block followed by spacing paragraph and by block' => [
641  '<h1>block1</h1><p>&nbsp;</p><h1>block2</h1>',
642  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
643  ],
644  'Block followed by spacing paragraph and by block, linebreak-separated' => [
645  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
646  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
647  ],
648  'Block followed by double spacing paragraph and by block' => [
649  '<h1>block1</h1><p>&nbsp;</p><p>&nbsp;</p><h1>block2</h1>',
650  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
651  ],
652  'Block followed by double spacing paragraph and by block, linebreak-separated' => [
653  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
654  '<h1>block1</h1>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<p>&nbsp;</p>' . CRLF . '<h1>block2</h1>',
655  ],
656  ];
657  }
658 
663  public function ‪paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRte($content, $expectedResult)
664  {
665  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
666  $subject = new RteHtmlParser($eventDispatcher);
667  self::assertEquals($expectedResult, $subject->transformTextForRichTextEditor($subject->transformTextForPersistence($content, $this->procOptions), $this->procOptions));
668  }
669 
674  {
675  return [
676  [
677  '<p><a name="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>',
678  '<p><a name="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>'
679  ],
680  [
681  '<p><a id="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>',
682  '<p><a id="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>'
683  ],
684  [
685  '<p><a name="some_anchor" id="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>',
686  '<p><a name="some_anchor" id="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>'
687  ],
688  [
689  '<p><a id="some_anchor">Some text inside the anchor</a></p>',
690  '<p><a id="some_anchor">Some text inside the anchor</a></p>'
691  ]
692  ];
693  }
694 
701  public function ‪anchorCorrectlyTransformedOnWayToDatabase($content, $expectedResult)
702  {
703  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
704  $subject = new RteHtmlParser($eventDispatcher);
705  self::assertEquals($expectedResult, $subject->transformTextForPersistence($content, $this->procOptions));
706  }
707 
712  {
713  return [
714  [
715  '<p><a name="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>',
716  '<p><a name="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>'
717  ],
718  [
719  '<p><a id="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>',
720  '<p><a id="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>'
721  ],
722  [
723  '<p><a name="some_anchor" id="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>',
724  '<p><a name="some_anchor" id="some_anchor"></a></p>' . CRLF . '<h3>Some headline here</h3>'
725  ],
726  [
727  '<p><a id="some_anchor">Some text inside the anchor</a></p>',
728  '<p><a id="some_anchor">Some text inside the anchor</a></p>'
729  ]
730  ];
731  }
732 
739  public function ‪anchorCorrectlyTransformedOnWayToDatabaseAndBackToRTE($content, $expectedResult)
740  {
741  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
742  $subject = new RteHtmlParser($eventDispatcher);
743  self::assertEquals($expectedResult, $subject->transformTextForRichTextEditor($subject->transformTextForPersistence($content, $this->procOptions), $this->procOptions));
744  }
745 
750  {
751  $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
752  $subject = new RteHtmlParser($eventDispatcher);
753  self::assertEquals('<figure class="table">' . CRLF . '<table>Allowed outside of p-tag</table>' . CRLF . '</figure>', $subject->transformTextForRichTextEditor('<figure class="table">' . CRLF . '<table>Allowed outside of p-tag</table>' . CRLF . '</figure>', $this->procOptions));
754  self::assertEquals('<figure class="table">' . CRLF . '<table>Allowed outside of p-tag</table>' . CRLF . '<figcaption>My Logo</figcaption></figure>', $subject->transformTextForRichTextEditor('<figure class="table">' . CRLF . '<table>Allowed outside of p-tag</table>' . CRLF . '<figcaption>My Logo</figcaption></figure>', $this->procOptions));
755  }
756 }
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\$procOptions
‪$procOptions
Definition: RteHtmlParserTest.php:33
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\paragraphCorrectlyTransformedOnWayToDatabaseProvider
‪static paragraphCorrectlyTransformedOnWayToDatabaseProvider()
Definition: RteHtmlParserTest.php:232
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\brTagCorrectlyTransformedOnWayToDatabaseAndBackToRte
‪brTagCorrectlyTransformedOnWayToDatabaseAndBackToRte($content, $expectedResult)
Definition: RteHtmlParserTest.php:220
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\paragraphCorrectlyTransformedOnWayToDatabase
‪paragraphCorrectlyTransformedOnWayToDatabase($content, $expectedResult)
Definition: RteHtmlParserTest.php:410
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\tableAndFigureApplyCorrectlyOutsideOfParagraphTags
‪tableAndFigureApplyCorrectlyOutsideOfParagraphTags()
Definition: RteHtmlParserTest.php:748
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\lineBreakCorrectlyTransformedOnWayToRTE
‪lineBreakCorrectlyTransformedOnWayToRTE($content, $expectedResult)
Definition: RteHtmlParserTest.php:510
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\anchorCorrectlyTransformedOnWayToDatabaseAndBackToRTE
‪anchorCorrectlyTransformedOnWayToDatabaseAndBackToRTE($content, $expectedResult)
Definition: RteHtmlParserTest.php:738
‪TYPO3\CMS\Core\Tests\Unit\Html
Definition: HtmlParserTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\anchorCorrectlyTransformedOnWayToDatabaseAndBackToRTEProvider
‪static anchorCorrectlyTransformedOnWayToDatabaseAndBackToRTEProvider()
Definition: RteHtmlParserTest.php:710
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\anchorCorrectlyTransformedOnWayToDatabaseProvider
‪static anchorCorrectlyTransformedOnWayToDatabaseProvider()
Definition: RteHtmlParserTest.php:672
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\brTagCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider
‪static brTagCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider()
Definition: RteHtmlParserTest.php:198
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\lineBreakCorrectlyTransformedOnWayToRteProvider
‪static lineBreakCorrectlyTransformedOnWayToRteProvider()
Definition: RteHtmlParserTest.php:420
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRte
‪paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRte($content, $expectedResult)
Definition: RteHtmlParserTest.php:662
‪TYPO3\CMS\Core\Html\RteHtmlParser
Definition: RteHtmlParser.php:38
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider
‪static hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider()
Definition: RteHtmlParserTest.php:120
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest
Definition: RteHtmlParserTest.php:28
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider
‪static paragraphCorrectlyTransformedOnWayToDatabaseAndBackToRteProvider()
Definition: RteHtmlParserTest.php:520
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\hrTagCorrectlyTransformedOnWayToDataBaseDataProvider
‪static hrTagCorrectlyTransformedOnWayToDataBaseDataProvider()
Definition: RteHtmlParserTest.php:38
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\$resetSingletonInstances
‪bool $resetSingletonInstances
Definition: RteHtmlParserTest.php:31
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRte
‪hrTagCorrectlyTransformedOnWayToDatabaseAndBackToRte($content, $expectedResult)
Definition: RteHtmlParserTest.php:186
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\anchorCorrectlyTransformedOnWayToDatabase
‪anchorCorrectlyTransformedOnWayToDatabase($content, $expectedResult)
Definition: RteHtmlParserTest.php:700
‪TYPO3\CMS\Core\Tests\Unit\Html\RteHtmlParserTest\hrTagCorrectlyTransformedOnWayToDataBase
‪hrTagCorrectlyTransformedOnWayToDataBase($content, $expectedResult)
Definition: RteHtmlParserTest.php:108