xref: /dokuwiki/_test/tests/Parsing/ParserMode/GfmMediaTest.php (revision 47a02a102092be9e1e6f1ddaf158bdfffdb13d4f)
13440a8c0SAndreas Gohr<?php
23440a8c0SAndreas Gohr
33440a8c0SAndreas Gohrnamespace dokuwiki\test\Parsing\ParserMode;
43440a8c0SAndreas Gohr
53440a8c0SAndreas Gohruse dokuwiki\Parsing\ParserMode\GfmLink;
63440a8c0SAndreas Gohruse dokuwiki\Parsing\ParserMode\GfmMedia;
73440a8c0SAndreas Gohr
83440a8c0SAndreas Gohr/**
93440a8c0SAndreas Gohr * Tests for GFM inline image syntax `![alt](url)` dispatching to DokuWiki's
103440a8c0SAndreas Gohr * internalmedia / externalmedia handler instructions.
113440a8c0SAndreas Gohr */
123440a8c0SAndreas Gohrclass GfmMediaTest extends ParserTestBase
133440a8c0SAndreas Gohr{
143440a8c0SAndreas Gohr    public function setUp(): void
153440a8c0SAndreas Gohr    {
163440a8c0SAndreas Gohr        parent::setUp();
17*47a02a10SAndreas Gohr        $this->setSyntax('md');
183440a8c0SAndreas Gohr    }
193440a8c0SAndreas Gohr
203440a8c0SAndreas Gohr    function testInternalMedia()
213440a8c0SAndreas Gohr    {
223440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
233440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png) Bar');
243440a8c0SAndreas Gohr        $calls = [
253440a8c0SAndreas Gohr            ['document_start', []],
263440a8c0SAndreas Gohr            ['p_open', []],
273440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
283440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', null, null, null, 'cache', 'details']],
293440a8c0SAndreas Gohr            ['cdata', [' Bar']],
303440a8c0SAndreas Gohr            ['p_close', []],
313440a8c0SAndreas Gohr            ['document_end', []],
323440a8c0SAndreas Gohr        ];
333440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
343440a8c0SAndreas Gohr    }
353440a8c0SAndreas Gohr
363440a8c0SAndreas Gohr    function testExternalMediaHttps()
373440a8c0SAndreas Gohr    {
383440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
393440a8c0SAndreas Gohr        $this->P->parse('Foo ![logo](https://example.com/img.png) Bar');
403440a8c0SAndreas Gohr        $calls = [
413440a8c0SAndreas Gohr            ['document_start', []],
423440a8c0SAndreas Gohr            ['p_open', []],
433440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
443440a8c0SAndreas Gohr            ['externalmedia', ['https://example.com/img.png', 'logo', null, null, null, 'cache', 'details']],
453440a8c0SAndreas Gohr            ['cdata', [' Bar']],
463440a8c0SAndreas Gohr            ['p_close', []],
473440a8c0SAndreas Gohr            ['document_end', []],
483440a8c0SAndreas Gohr        ];
493440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
503440a8c0SAndreas Gohr    }
513440a8c0SAndreas Gohr
523440a8c0SAndreas Gohr    function testExternalMediaInterwiki()
533440a8c0SAndreas Gohr    {
543440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
553440a8c0SAndreas Gohr        $this->P->parse('Foo ![foo](wp>Example.png) Bar');
563440a8c0SAndreas Gohr        $calls = [
573440a8c0SAndreas Gohr            ['document_start', []],
583440a8c0SAndreas Gohr            ['p_open', []],
593440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
603440a8c0SAndreas Gohr            ['externalmedia', ['wp>Example.png', 'foo', null, null, null, 'cache', 'details']],
613440a8c0SAndreas Gohr            ['cdata', [' Bar']],
623440a8c0SAndreas Gohr            ['p_close', []],
633440a8c0SAndreas Gohr            ['document_end', []],
643440a8c0SAndreas Gohr        ];
653440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
663440a8c0SAndreas Gohr    }
673440a8c0SAndreas Gohr
683440a8c0SAndreas Gohr    function testEmptyAlt()
693440a8c0SAndreas Gohr    {
703440a8c0SAndreas Gohr        // GFM allows `![](/url)` with empty alt; we pass null in the caption
713440a8c0SAndreas Gohr        // slot to match how DW's Media mode emits no-caption media.
723440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
733440a8c0SAndreas Gohr        $this->P->parse('Foo ![](image.png) Bar');
743440a8c0SAndreas Gohr        $calls = [
753440a8c0SAndreas Gohr            ['document_start', []],
763440a8c0SAndreas Gohr            ['p_open', []],
773440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
783440a8c0SAndreas Gohr            ['internalmedia', ['image.png', null, null, null, null, 'cache', 'details']],
793440a8c0SAndreas Gohr            ['cdata', [' Bar']],
803440a8c0SAndreas Gohr            ['p_close', []],
813440a8c0SAndreas Gohr            ['document_end', []],
823440a8c0SAndreas Gohr        ];
833440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
843440a8c0SAndreas Gohr    }
853440a8c0SAndreas Gohr
863440a8c0SAndreas Gohr    function testTitleInDoubleQuotesIsDiscarded()
873440a8c0SAndreas Gohr    {
883440a8c0SAndreas Gohr        // GFM allows ![alt](url "title") but DokuWiki's media handler has
893440a8c0SAndreas Gohr        // no separate title slot (alt doubles as caption). The title parses
903440a8c0SAndreas Gohr        // cleanly but is dropped.
913440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
923440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png "caption") Bar');
933440a8c0SAndreas Gohr        $calls = [
943440a8c0SAndreas Gohr            ['document_start', []],
953440a8c0SAndreas Gohr            ['p_open', []],
963440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
973440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', null, null, null, 'cache', 'details']],
983440a8c0SAndreas Gohr            ['cdata', [' Bar']],
993440a8c0SAndreas Gohr            ['p_close', []],
1003440a8c0SAndreas Gohr            ['document_end', []],
1013440a8c0SAndreas Gohr        ];
1023440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
1033440a8c0SAndreas Gohr    }
1043440a8c0SAndreas Gohr
1053440a8c0SAndreas Gohr    function testTitleInSingleQuotesIsDiscarded()
1063440a8c0SAndreas Gohr    {
1073440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
1083440a8c0SAndreas Gohr        $this->P->parse("Foo ![alt](wiki:image.png 'caption') Bar");
1093440a8c0SAndreas Gohr        $calls = [
1103440a8c0SAndreas Gohr            ['document_start', []],
1113440a8c0SAndreas Gohr            ['p_open', []],
1123440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
1133440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', null, null, null, 'cache', 'details']],
1143440a8c0SAndreas Gohr            ['cdata', [' Bar']],
1153440a8c0SAndreas Gohr            ['p_close', []],
1163440a8c0SAndreas Gohr            ['document_end', []],
1173440a8c0SAndreas Gohr        ];
1183440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
1193440a8c0SAndreas Gohr    }
1203440a8c0SAndreas Gohr
1213440a8c0SAndreas Gohr    function testMultibyteAlt()
1223440a8c0SAndreas Gohr    {
1233440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
1243440a8c0SAndreas Gohr        $this->P->parse('Foo ![日本語](pic.png) Bar');
1253440a8c0SAndreas Gohr        $calls = [
1263440a8c0SAndreas Gohr            ['document_start', []],
1273440a8c0SAndreas Gohr            ['p_open', []],
1283440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
1293440a8c0SAndreas Gohr            ['internalmedia', ['pic.png', '日本語', null, null, null, 'cache', 'details']],
1303440a8c0SAndreas Gohr            ['cdata', [' Bar']],
1313440a8c0SAndreas Gohr            ['p_close', []],
1323440a8c0SAndreas Gohr            ['document_end', []],
1333440a8c0SAndreas Gohr        ];
1343440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
1353440a8c0SAndreas Gohr    }
1363440a8c0SAndreas Gohr
1373440a8c0SAndreas Gohr    function testPlainLinkNotImage()
1383440a8c0SAndreas Gohr    {
1393440a8c0SAndreas Gohr        // With both gfm_media and gfm_link loaded, `[text](url)` (no leading
1403440a8c0SAndreas Gohr        // `!`) must dispatch through gfm_link, not gfm_media.
1413440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
1423440a8c0SAndreas Gohr        $this->P->addMode('gfm_link', new GfmLink());
1433440a8c0SAndreas Gohr        $this->P->parse('Foo [text](page) Bar');
1443440a8c0SAndreas Gohr        $modes = array_column($this->H->calls, 0);
1453440a8c0SAndreas Gohr        $this->assertContains('internallink', $modes);
1463440a8c0SAndreas Gohr        $this->assertNotContains('internalmedia', $modes);
1473440a8c0SAndreas Gohr    }
1483440a8c0SAndreas Gohr
1493440a8c0SAndreas Gohr    function testBangAloneIsNotImage()
1503440a8c0SAndreas Gohr    {
1513440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
1523440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt] Bar');
1533440a8c0SAndreas Gohr        $modes = array_column($this->H->calls, 0);
1543440a8c0SAndreas Gohr        $this->assertNotContains('internalmedia', $modes);
1553440a8c0SAndreas Gohr        $this->assertNotContains('externalmedia', $modes);
1563440a8c0SAndreas Gohr    }
1573440a8c0SAndreas Gohr
1583440a8c0SAndreas Gohr    function testSpaceBetweenBracketsAndParensIsNotAnImage()
1593440a8c0SAndreas Gohr    {
1603440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
1613440a8c0SAndreas Gohr        $this->P->parse('![foo] (bar)');
1623440a8c0SAndreas Gohr        $modes = array_column($this->H->calls, 0);
1633440a8c0SAndreas Gohr        $this->assertNotContains('internalmedia', $modes);
1643440a8c0SAndreas Gohr        $this->assertNotContains('externalmedia', $modes);
1653440a8c0SAndreas Gohr    }
1663440a8c0SAndreas Gohr
1673440a8c0SAndreas Gohr    function testReferenceStyleImageNotMatched()
1683440a8c0SAndreas Gohr    {
1693440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
1703440a8c0SAndreas Gohr        $this->P->parse('![foo][bar]');
1713440a8c0SAndreas Gohr        $modes = array_column($this->H->calls, 0);
1723440a8c0SAndreas Gohr        $this->assertNotContains('internalmedia', $modes);
1733440a8c0SAndreas Gohr        $this->assertNotContains('externalmedia', $modes);
1743440a8c0SAndreas Gohr    }
1753440a8c0SAndreas Gohr
1763440a8c0SAndreas Gohr    function testTwoImagesInOneLine()
1773440a8c0SAndreas Gohr    {
1783440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
1793440a8c0SAndreas Gohr        $this->P->parse('Foo ![one](a.png) and ![two](b.png) Bar');
1803440a8c0SAndreas Gohr        $calls = [
1813440a8c0SAndreas Gohr            ['document_start', []],
1823440a8c0SAndreas Gohr            ['p_open', []],
1833440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
1843440a8c0SAndreas Gohr            ['internalmedia', ['a.png', 'one', null, null, null, 'cache', 'details']],
1853440a8c0SAndreas Gohr            ['cdata', [' and ']],
1863440a8c0SAndreas Gohr            ['internalmedia', ['b.png', 'two', null, null, null, 'cache', 'details']],
1873440a8c0SAndreas Gohr            ['cdata', [' Bar']],
1883440a8c0SAndreas Gohr            ['p_close', []],
1893440a8c0SAndreas Gohr            ['document_end', []],
1903440a8c0SAndreas Gohr        ];
1913440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
1923440a8c0SAndreas Gohr    }
1933440a8c0SAndreas Gohr
1943440a8c0SAndreas Gohr    function testWidthOnlyParameter()
1953440a8c0SAndreas Gohr    {
1963440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
1973440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png?200) Bar');
1983440a8c0SAndreas Gohr        $calls = [
1993440a8c0SAndreas Gohr            ['document_start', []],
2003440a8c0SAndreas Gohr            ['p_open', []],
2013440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
2023440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', null, '200', null, 'cache', 'details']],
2033440a8c0SAndreas Gohr            ['cdata', [' Bar']],
2043440a8c0SAndreas Gohr            ['p_close', []],
2053440a8c0SAndreas Gohr            ['document_end', []],
2063440a8c0SAndreas Gohr        ];
2073440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
2083440a8c0SAndreas Gohr    }
2093440a8c0SAndreas Gohr
2103440a8c0SAndreas Gohr    function testWidthAndHeightParameter()
2113440a8c0SAndreas Gohr    {
2123440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
2133440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png?200x100) Bar');
2143440a8c0SAndreas Gohr        $calls = [
2153440a8c0SAndreas Gohr            ['document_start', []],
2163440a8c0SAndreas Gohr            ['p_open', []],
2173440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
2183440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', null, '200', '100', 'cache', 'details']],
2193440a8c0SAndreas Gohr            ['cdata', [' Bar']],
2203440a8c0SAndreas Gohr            ['p_close', []],
2213440a8c0SAndreas Gohr            ['document_end', []],
2223440a8c0SAndreas Gohr        ];
2233440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
2243440a8c0SAndreas Gohr    }
2253440a8c0SAndreas Gohr
2263440a8c0SAndreas Gohr    function testLinkingParameter()
2273440a8c0SAndreas Gohr    {
2283440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
2293440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png?nolink) Bar');
2303440a8c0SAndreas Gohr        $calls = [
2313440a8c0SAndreas Gohr            ['document_start', []],
2323440a8c0SAndreas Gohr            ['p_open', []],
2333440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
2343440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', null, null, null, 'cache', 'nolink']],
2353440a8c0SAndreas Gohr            ['cdata', [' Bar']],
2363440a8c0SAndreas Gohr            ['p_close', []],
2373440a8c0SAndreas Gohr            ['document_end', []],
2383440a8c0SAndreas Gohr        ];
2393440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
2403440a8c0SAndreas Gohr    }
2413440a8c0SAndreas Gohr
2423440a8c0SAndreas Gohr    function testCacheParameter()
2433440a8c0SAndreas Gohr    {
2443440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
2453440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png?recache) Bar');
2463440a8c0SAndreas Gohr        $calls = [
2473440a8c0SAndreas Gohr            ['document_start', []],
2483440a8c0SAndreas Gohr            ['p_open', []],
2493440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
2503440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', null, null, null, 'recache', 'details']],
2513440a8c0SAndreas Gohr            ['cdata', [' Bar']],
2523440a8c0SAndreas Gohr            ['p_close', []],
2533440a8c0SAndreas Gohr            ['document_end', []],
2543440a8c0SAndreas Gohr        ];
2553440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
2563440a8c0SAndreas Gohr    }
2573440a8c0SAndreas Gohr
2583440a8c0SAndreas Gohr    function testCombinedParameters()
2593440a8c0SAndreas Gohr    {
2603440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
2613440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png?200x100&nolink&nocache) Bar');
2623440a8c0SAndreas Gohr        $calls = [
2633440a8c0SAndreas Gohr            ['document_start', []],
2643440a8c0SAndreas Gohr            ['p_open', []],
2653440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
2663440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', null, '200', '100', 'nocache', 'nolink']],
2673440a8c0SAndreas Gohr            ['cdata', [' Bar']],
2683440a8c0SAndreas Gohr            ['p_close', []],
2693440a8c0SAndreas Gohr            ['document_end', []],
2703440a8c0SAndreas Gohr        ];
2713440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
2723440a8c0SAndreas Gohr    }
2733440a8c0SAndreas Gohr
2743440a8c0SAndreas Gohr    function testLastQuestionMarkIsTheParameterDelimiter()
2753440a8c0SAndreas Gohr    {
2763440a8c0SAndreas Gohr        // URLs may carry their own query string; DW splits on the *last* `?`
2773440a8c0SAndreas Gohr        // so the URL query survives as part of the src.
2783440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
2793440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](https://example.com/img?v=2?200x100) Bar');
2803440a8c0SAndreas Gohr        $calls = [
2813440a8c0SAndreas Gohr            ['document_start', []],
2823440a8c0SAndreas Gohr            ['p_open', []],
2833440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
2843440a8c0SAndreas Gohr            ['externalmedia', ['https://example.com/img?v=2', 'alt', null, '200', '100', 'cache', 'details']],
2853440a8c0SAndreas Gohr            ['cdata', [' Bar']],
2863440a8c0SAndreas Gohr            ['p_close', []],
2873440a8c0SAndreas Gohr            ['document_end', []],
2883440a8c0SAndreas Gohr        ];
2893440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
2903440a8c0SAndreas Gohr    }
2913440a8c0SAndreas Gohr
2923440a8c0SAndreas Gohr    function testAlignRight()
2933440a8c0SAndreas Gohr    {
2943440a8c0SAndreas Gohr        // GFM has no native image-alignment syntax, so GfmMedia borrows
2953440a8c0SAndreas Gohr        // DW's ?right/?left/?center keyword from the shared URL parameter
2963440a8c0SAndreas Gohr        // block — the only way to align an inline GFM image.
2973440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
2983440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png?right) Bar');
2993440a8c0SAndreas Gohr        $calls = [
3003440a8c0SAndreas Gohr            ['document_start', []],
3013440a8c0SAndreas Gohr            ['p_open', []],
3023440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
3033440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', 'right', null, null, 'cache', 'details']],
3043440a8c0SAndreas Gohr            ['cdata', [' Bar']],
3053440a8c0SAndreas Gohr            ['p_close', []],
3063440a8c0SAndreas Gohr            ['document_end', []],
3073440a8c0SAndreas Gohr        ];
3083440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
3093440a8c0SAndreas Gohr    }
3103440a8c0SAndreas Gohr
3113440a8c0SAndreas Gohr    function testAlignWithSizeAndLinking()
3123440a8c0SAndreas Gohr    {
3133440a8c0SAndreas Gohr        $this->P->addMode('gfm_media', new GfmMedia());
3143440a8c0SAndreas Gohr        $this->P->parse('Foo ![alt](wiki:image.png?200x100&center&nolink) Bar');
3153440a8c0SAndreas Gohr        $calls = [
3163440a8c0SAndreas Gohr            ['document_start', []],
3173440a8c0SAndreas Gohr            ['p_open', []],
3183440a8c0SAndreas Gohr            ['cdata', ["\nFoo "]],
3193440a8c0SAndreas Gohr            ['internalmedia', ['wiki:image.png', 'alt', 'center', '200', '100', 'cache', 'nolink']],
3203440a8c0SAndreas Gohr            ['cdata', [' Bar']],
3213440a8c0SAndreas Gohr            ['p_close', []],
3223440a8c0SAndreas Gohr            ['document_end', []],
3233440a8c0SAndreas Gohr        ];
3243440a8c0SAndreas Gohr        $this->assertCalls($calls, $this->H->calls);
3253440a8c0SAndreas Gohr    }
3263440a8c0SAndreas Gohr
3273440a8c0SAndreas Gohr    function testSortValue()
3283440a8c0SAndreas Gohr    {
3293440a8c0SAndreas Gohr        $this->assertSame(310, (new GfmMedia())->getSort());
3303440a8c0SAndreas Gohr    }
3313440a8c0SAndreas Gohr}
332