1*3440a8c0SAndreas Gohr<?php 2*3440a8c0SAndreas Gohr 3*3440a8c0SAndreas Gohrnamespace dokuwiki\test\Parsing\Markdown; 4*3440a8c0SAndreas Gohr 5*3440a8c0SAndreas Gohruse Doku_Renderer_xhtml; 6*3440a8c0SAndreas Gohr 7*3440a8c0SAndreas Gohr/** 8*3440a8c0SAndreas Gohr * XHTML renderer tuned to emit the minimal HTML shape GFM's spec.txt uses. 9*3440a8c0SAndreas Gohr * 10*3440a8c0SAndreas Gohr * DokuWiki's production XHTML renderer wraps internal media in details 11*3440a8c0SAndreas Gohr * links pointing at `/lib/exe/fetch.php?media=...` / `/lib/exe/detail.php?media=...`, 12*3440a8c0SAndreas Gohr * rewrites internal link hrefs to `/doku.php?id=...`, and adds wiki-specific 13*3440a8c0SAndreas Gohr * classes and attributes. All of this is correct for live wiki pages but 14*3440a8c0SAndreas Gohr * diverges byte-for-byte from GFM's bare `<img src="...">` and 15*3440a8c0SAndreas Gohr * `<a href="...">...</a>`. 16*3440a8c0SAndreas Gohr * 17*3440a8c0SAndreas Gohr * This renderer is used only by {@see GfmSpecTest} so the spec roundtrip 18*3440a8c0SAndreas Gohr * can compare against byte-level spec HTML. Production rendering is 19*3440a8c0SAndreas Gohr * unchanged. Methods not overridden here fall through to the XHTML 20*3440a8c0SAndreas Gohr * renderer (paragraphs, emphasis, code spans, lists, etc.) — those render 21*3440a8c0SAndreas Gohr * the same shape the spec expects. 22*3440a8c0SAndreas Gohr * 23*3440a8c0SAndreas Gohr * Note: title attributes on links/images are discarded at handle time 24*3440a8c0SAndreas Gohr * (no DW instruction slot), so spec examples that expect `title="..."` 25*3440a8c0SAndreas Gohr * still don't pass and stay in `skip.php`. 26*3440a8c0SAndreas Gohr */ 27*3440a8c0SAndreas Gohrclass SpecCompatRenderer extends Doku_Renderer_xhtml 28*3440a8c0SAndreas Gohr{ 29*3440a8c0SAndreas Gohr public function internalmedia( 30*3440a8c0SAndreas Gohr $src, 31*3440a8c0SAndreas Gohr $title = null, 32*3440a8c0SAndreas Gohr $align = null, 33*3440a8c0SAndreas Gohr $width = null, 34*3440a8c0SAndreas Gohr $height = null, 35*3440a8c0SAndreas Gohr $cache = null, 36*3440a8c0SAndreas Gohr $linking = null, 37*3440a8c0SAndreas Gohr $return = false 38*3440a8c0SAndreas Gohr ) { 39*3440a8c0SAndreas Gohr $this->doc .= $this->specImg($src, $title, $width, $height); 40*3440a8c0SAndreas Gohr } 41*3440a8c0SAndreas Gohr 42*3440a8c0SAndreas Gohr public function externalmedia( 43*3440a8c0SAndreas Gohr $src, 44*3440a8c0SAndreas Gohr $title = null, 45*3440a8c0SAndreas Gohr $align = null, 46*3440a8c0SAndreas Gohr $width = null, 47*3440a8c0SAndreas Gohr $height = null, 48*3440a8c0SAndreas Gohr $cache = null, 49*3440a8c0SAndreas Gohr $linking = null, 50*3440a8c0SAndreas Gohr $return = false 51*3440a8c0SAndreas Gohr ) { 52*3440a8c0SAndreas Gohr $this->doc .= $this->specImg($src, $title, $width, $height); 53*3440a8c0SAndreas Gohr } 54*3440a8c0SAndreas Gohr 55*3440a8c0SAndreas Gohr public function internallink($id, $name = null, $search = null, $returnonly = false, $linktype = 'content') 56*3440a8c0SAndreas Gohr { 57*3440a8c0SAndreas Gohr $this->doc .= $this->specLink($id, $name); 58*3440a8c0SAndreas Gohr } 59*3440a8c0SAndreas Gohr 60*3440a8c0SAndreas Gohr public function externallink($url, $name = null, $returnonly = false) 61*3440a8c0SAndreas Gohr { 62*3440a8c0SAndreas Gohr $this->doc .= $this->specLink($url, $name); 63*3440a8c0SAndreas Gohr } 64*3440a8c0SAndreas Gohr 65*3440a8c0SAndreas Gohr public function interwikilink($match, $name, $wikiName, $wikiUri, $returnonly = false) 66*3440a8c0SAndreas Gohr { 67*3440a8c0SAndreas Gohr // Spec has no interwiki expectations; emit the raw `wp>Page` form as 68*3440a8c0SAndreas Gohr // href so the mode is still visible but obviously non-standard. 69*3440a8c0SAndreas Gohr $this->doc .= $this->specLink($match, $name); 70*3440a8c0SAndreas Gohr } 71*3440a8c0SAndreas Gohr 72*3440a8c0SAndreas Gohr public function emaillink($address, $name = null, $returnonly = false) 73*3440a8c0SAndreas Gohr { 74*3440a8c0SAndreas Gohr $this->doc .= $this->specLink('mailto:' . $address, $name ?? $address); 75*3440a8c0SAndreas Gohr } 76*3440a8c0SAndreas Gohr 77*3440a8c0SAndreas Gohr public function locallink($hash, $name = null, $returnonly = false) 78*3440a8c0SAndreas Gohr { 79*3440a8c0SAndreas Gohr $this->doc .= $this->specLink('#' . $hash, $name ?? $hash); 80*3440a8c0SAndreas Gohr } 81*3440a8c0SAndreas Gohr 82*3440a8c0SAndreas Gohr public function windowssharelink($url, $name = null, $returnonly = false) 83*3440a8c0SAndreas Gohr { 84*3440a8c0SAndreas Gohr $this->doc .= $this->specLink($url, $name); 85*3440a8c0SAndreas Gohr } 86*3440a8c0SAndreas Gohr 87*3440a8c0SAndreas Gohr private function specImg($src, $alt, $width, $height): string 88*3440a8c0SAndreas Gohr { 89*3440a8c0SAndreas Gohr $out = '<img src="' . hsc((string) $src) . '"'; 90*3440a8c0SAndreas Gohr $out .= ' alt="' . hsc((string) $alt) . '"'; 91*3440a8c0SAndreas Gohr if ($width !== null) $out .= ' width="' . (int) $width . '"'; 92*3440a8c0SAndreas Gohr if ($height !== null) $out .= ' height="' . (int) $height . '"'; 93*3440a8c0SAndreas Gohr $out .= ' />'; 94*3440a8c0SAndreas Gohr return $out; 95*3440a8c0SAndreas Gohr } 96*3440a8c0SAndreas Gohr 97*3440a8c0SAndreas Gohr /** 98*3440a8c0SAndreas Gohr * Emit a bare <a href="...">label</a>. If the label is a media 99*3440a8c0SAndreas Gohr * descriptor array (the shape Media::parseMedia() returns, passed by 100*3440a8c0SAndreas Gohr * Internallink / GfmLink when the label is `{{img}}` / ``), 101*3440a8c0SAndreas Gohr * render the <img> inside the <a>. 102*3440a8c0SAndreas Gohr */ 103*3440a8c0SAndreas Gohr private function specLink($href, $label): string 104*3440a8c0SAndreas Gohr { 105*3440a8c0SAndreas Gohr if (is_array($label) && isset($label['type'])) { 106*3440a8c0SAndreas Gohr $img = $this->specImg( 107*3440a8c0SAndreas Gohr $label['src'], 108*3440a8c0SAndreas Gohr $label['title'], 109*3440a8c0SAndreas Gohr $label['width'] ?? null, 110*3440a8c0SAndreas Gohr $label['height'] ?? null 111*3440a8c0SAndreas Gohr ); 112*3440a8c0SAndreas Gohr return '<a href="' . hsc((string) $href) . '">' . $img . '</a>'; 113*3440a8c0SAndreas Gohr } 114*3440a8c0SAndreas Gohr $text = ($label === null || $label === '') ? $href : $label; 115*3440a8c0SAndreas Gohr return '<a href="' . hsc((string) $href) . '">' . hsc((string) $text) . '</a>'; 116*3440a8c0SAndreas Gohr } 117*3440a8c0SAndreas Gohr} 118