1aedf28f1SMichael Bowers<?php 2aedf28f1SMichael Bowers/** 3aedf28f1SMichael Bowers * DokuWiki Plugin svgEmbed (Syntax Component) 4aedf28f1SMichael Bowers * 5aedf28f1SMichael Bowers * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 65abc08bcSEmma Bowers * @author Emma Bowers <emb@pobox.com> 7aedf28f1SMichael Bowers */ 8aedf28f1SMichael Bowers 9aedf28f1SMichael Bowers// must be run within Dokuwiki 10aedf28f1SMichael Bowersif (!defined('DOKU_INC')) { 11aedf28f1SMichael Bowers die(); 12aedf28f1SMichael Bowers} 13aedf28f1SMichael Bowers 1421a1ef9eSMichael Bowers 15aedf28f1SMichael Bowersclass syntax_plugin_svgembed extends DokuWiki_Syntax_Plugin 16aedf28f1SMichael Bowers{ 17a1e3c6f8SMichael Bowers /** 1821a1ef9eSMichael Bowers * Get the new parameters added to the syntax. 1921a1ef9eSMichael Bowers * 2021a1ef9eSMichael Bowers * @param string $match The text that matched the lexer pattern that we are inspecting 2121a1ef9eSMichael Bowers */ 2221a1ef9eSMichael Bowers private function Get_New_Parameters($match, &$p) { 2321a1ef9eSMichael Bowers // Strip the opening and closing markup 2421a1ef9eSMichael Bowers $link = preg_replace(array('/^\{\{/', '/\}\}$/u'), '', $match); 2521a1ef9eSMichael Bowers 2621a1ef9eSMichael Bowers // Split title from URL 2721a1ef9eSMichael Bowers $link = explode('|', $link, 2); 2821a1ef9eSMichael Bowers 2921a1ef9eSMichael Bowers //remove aligning spaces 3021a1ef9eSMichael Bowers $link[0] = trim($link[0]); 3121a1ef9eSMichael Bowers 3221a1ef9eSMichael Bowers //split into src and parameters (using the very last question mark) 3321a1ef9eSMichael Bowers $pos = strrpos($link[0], '?'); 3421a1ef9eSMichael Bowers 3521a1ef9eSMichael Bowers if ($pos !== false) { 3621a1ef9eSMichael Bowers $param = substr($link[0], $pos + 1); 3721a1ef9eSMichael Bowers 3821a1ef9eSMichael Bowers // Get units 3921a1ef9eSMichael Bowers $p['inResponsiveUnits'] = (preg_match('/units:(\%|vw)/i', $param, $local_match) > 0); 4021a1ef9eSMichael Bowers $p['responsiveUnits'] = ($p['inResponsiveUnits'] && count($local_match) > 1) ? $local_match[1] : NULL; 4121a1ef9eSMichael Bowers 4221a1ef9eSMichael Bowers // Get declared CSS classes 4321a1ef9eSMichael Bowers unset($local_match); 4421a1ef9eSMichael Bowers $p['hasCssClasses'] = (preg_match_all('/class:(-?[_a-z]+[_a-z0-9-]*)/i', $param, $local_match) > 0); 4521a1ef9eSMichael Bowers $p['cssClasses'] = ($p['hasCssClasses'] && isset($local_match[1]) && count($local_match[1])) ? $local_match[1] : NULL; 4621a1ef9eSMichael Bowers 4780b00982SMichael Bowers // Get printing 4880b00982SMichael Bowers if (preg_match_all('/(^|&)(print|print:(on|true|yes|1|off|false|no|0))(&|$)/i', $param, $local_match)) { 4980b00982SMichael Bowers $p['print'] = in_array(strtolower($local_match[2][0]), array('print', 'print:on', 'print:true', 'print:yes', 'print:1')); 5080b00982SMichael Bowers } 5180b00982SMichael Bowers else { 5280b00982SMichael Bowers $p['print'] = ($this->getConf('default_print') == '1'); 5380b00982SMichael Bowers } 5480b00982SMichael Bowers 5521a1ef9eSMichael Bowers // Re-parse width and height 5621a1ef9eSMichael Bowers $param = preg_replace('/class:(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)/i', '', $param); // Remove the classes since they can have numbers embedded 5721a1ef9eSMichael Bowers if(preg_match('/(\d+)(x(\d+))?/i', $param, $size)) { 5821a1ef9eSMichael Bowers $p['width'] = (!empty($size[1]) ? $size[1] : null); 5921a1ef9eSMichael Bowers $p['height'] = (!empty($size[3]) ? $size[3] : null); 6021a1ef9eSMichael Bowers } else { 6121a1ef9eSMichael Bowers $p['width'] = null; 6221a1ef9eSMichael Bowers $p['height'] = null; 6321a1ef9eSMichael Bowers } 6421a1ef9eSMichael Bowers } 6521a1ef9eSMichael Bowers } 6621a1ef9eSMichael Bowers 6721a1ef9eSMichael Bowers 6821a1ef9eSMichael Bowers /** 69a1e3c6f8SMichael Bowers * Figure out the pixel adjustment if an absolute measurement unit is given. 70a1e3c6f8SMichael Bowers * 71a1e3c6f8SMichael Bowers * @param string $value Dimension to analyze for unit value (cm|mm|Q|in|pc|pt|px) 72a1e3c6f8SMichael Bowers */ 73a1e3c6f8SMichael Bowers private function Get_SVG_Unit_Adjustment($value) { 74a1e3c6f8SMichael Bowers define('SVG_DPI', 96.0); 75a1e3c6f8SMichael Bowers 76a1e3c6f8SMichael Bowers $matches = array(); 77a1e3c6f8SMichael Bowers $adjustment = 1; 78a1e3c6f8SMichael Bowers 79a1e3c6f8SMichael Bowers if (preg_match('/(cm|mm|Q|in|pc|pt|px)/', $value, $matches) && count($matches)) { 80a1e3c6f8SMichael Bowers switch ($matches[1]) { 81a1e3c6f8SMichael Bowers // Don't bother checking for "px", we already set adjustment to 1, but we still 82a1e3c6f8SMichael Bowers // want to count it in the matches 83a1e3c6f8SMichael Bowers case 'pt': 84a1e3c6f8SMichael Bowers $adjustment = SVG_DPI / 72; 85a1e3c6f8SMichael Bowers break; 86a1e3c6f8SMichael Bowers case 'pc': 87a1e3c6f8SMichael Bowers $adjustment = SVG_DPI / 6; 88a1e3c6f8SMichael Bowers break; 89a1e3c6f8SMichael Bowers case 'in': 90a1e3c6f8SMichael Bowers $adjustment = SVG_DPI; 91a1e3c6f8SMichael Bowers break; 92a1e3c6f8SMichael Bowers case 'cm': 93a1e3c6f8SMichael Bowers $adjustment = SVG_DPI / 2.54; 94a1e3c6f8SMichael Bowers break; 95a1e3c6f8SMichael Bowers case 'mm': 96a1e3c6f8SMichael Bowers $adjustment = SVG_DPI / 25.4; 97a1e3c6f8SMichael Bowers break; 98a1e3c6f8SMichael Bowers case 'Q': 99a1e3c6f8SMichael Bowers $adjustment = SVG_DPI / 101.6; 100a1e3c6f8SMichael Bowers break; 101a1e3c6f8SMichael Bowers } 102a1e3c6f8SMichael Bowers } 103a1e3c6f8SMichael Bowers 104a1e3c6f8SMichael Bowers return $adjustment; 105a1e3c6f8SMichael Bowers } 106a1e3c6f8SMichael Bowers 107a1e3c6f8SMichael Bowers 108aedf28f1SMichael Bowers /** 109aedf28f1SMichael Bowers * @return string Syntax mode type 110aedf28f1SMichael Bowers */ 111a93b1ea1SMichael Bowers public function getType() { 112a93b1ea1SMichael Bowers return 'container'; 113aedf28f1SMichael Bowers } 114aedf28f1SMichael Bowers 115aedf28f1SMichael Bowers /** 116aedf28f1SMichael Bowers * @return string Paragraph type 117aedf28f1SMichael Bowers */ 118a93b1ea1SMichael Bowers public function getPType() { 1199a16c2e0SEmma Bowers return 'normal'; 120aedf28f1SMichael Bowers } 121aedf28f1SMichael Bowers 122aedf28f1SMichael Bowers /** 123aedf28f1SMichael Bowers * @return int Sort order - Low numbers go before high numbers 124aedf28f1SMichael Bowers */ 125a93b1ea1SMichael Bowers public function getSort() { 126aedf28f1SMichael Bowers // Run it before the standard media functionality 127aedf28f1SMichael Bowers return 315; 128aedf28f1SMichael Bowers } 129aedf28f1SMichael Bowers 130aedf28f1SMichael Bowers /** 131aedf28f1SMichael Bowers * Connect lookup pattern to lexer. 132aedf28f1SMichael Bowers * 133aedf28f1SMichael Bowers * @param string $mode Parser mode 134aedf28f1SMichael Bowers */ 135a93b1ea1SMichael Bowers public function connectTo($mode) { 136aedf28f1SMichael Bowers // match everything the media component does, but short circuit into my code first 13735c70d5dSMichael Bowers $this->Lexer->addSpecialPattern("\{\{(?:[^\}\>\<]|(?:\}[^\>\<\}]))+\}\}", $mode, 'plugin_svgembed'); 138aedf28f1SMichael Bowers } 139aedf28f1SMichael Bowers 140aedf28f1SMichael Bowers /** 141aedf28f1SMichael Bowers * Handle matches of the media syntax, overridden by this plugin 142aedf28f1SMichael Bowers * 143aedf28f1SMichael Bowers * @param string $match The match of the syntax 144aedf28f1SMichael Bowers * @param int $state The state of the handler 145aedf28f1SMichael Bowers * @param int $pos The position in the document 146aedf28f1SMichael Bowers * @param Doku_Handler $handler The handler 147aedf28f1SMichael Bowers * 148aedf28f1SMichael Bowers * @return array Data for the renderer 149aedf28f1SMichael Bowers */ 150a93b1ea1SMichael Bowers public function handle($match, $state, $pos, Doku_Handler $handler) { 151aedf28f1SMichael Bowers $p = Doku_Handler_Parse_Media($match); 152aedf28f1SMichael Bowers $isSVG = preg_match('/\.svg$/i', trim($p['src'])); 15321a1ef9eSMichael Bowers if ($isSVG) 15421a1ef9eSMichael Bowers $this->Get_New_Parameters($match, $p); 155aedf28f1SMichael Bowers 15621a1ef9eSMichael Bowers if (!$isSVG || $p['type'] != 'internalmedia') { 157aedf28f1SMichael Bowers // If it's external media or not an SVG, perform the regular processing... 158aedf28f1SMichael Bowers $handler->media($match, $state, $pos); 159aedf28f1SMichael Bowers return false; 160aedf28f1SMichael Bowers } 161aedf28f1SMichael Bowers else { 162aedf28f1SMichael Bowers // ...otherwise, feed into my renderer 163aedf28f1SMichael Bowers return ($p); 164aedf28f1SMichael Bowers } 165aedf28f1SMichael Bowers } 166aedf28f1SMichael Bowers 167aedf28f1SMichael Bowers /** 168aedf28f1SMichael Bowers * Render xhtml output or metadata 169aedf28f1SMichael Bowers * 170a93b1ea1SMichael Bowers * @param string $mode Renderer mode (supported modes: xhtml, metadata) 171aedf28f1SMichael Bowers * @param Doku_Renderer $renderer The renderer 172aedf28f1SMichael Bowers * @param array $data The data from the handler() function 173aedf28f1SMichael Bowers * 174aedf28f1SMichael Bowers * @return bool If rendering was successful. 175aedf28f1SMichael Bowers */ 176a93b1ea1SMichael Bowers public function render($mode, Doku_Renderer $renderer, $data) { 177aedf28f1SMichael Bowers // If no data or we're not rendering XHTML, exit without handling 178a93b1ea1SMichael Bowers if (!$data) 179aedf28f1SMichael Bowers return false; 180aedf28f1SMichael Bowers 1819a16c2e0SEmma Bowers $src = $data['src']; 1829a16c2e0SEmma Bowers $isInternal = ($data['type'] == 'internalmedia' && !media_isexternal($src)); 1839a16c2e0SEmma Bowers $exists = true; 1849a16c2e0SEmma Bowers if ($isInternal) { 1859a16c2e0SEmma Bowers global $ID; 1869a16c2e0SEmma Bowers list($src) = explode('#', $src, 2); 1879a16c2e0SEmma Bowers resolve_mediaid(getNS($ID), $src, $exists); 1889a16c2e0SEmma Bowers } 1899a16c2e0SEmma Bowers 190a93b1ea1SMichael Bowers if ($mode == 'xhtml') { 191a93b1ea1SMichael Bowers global $conf; 192a93b1ea1SMichael Bowers 193daa0a102SMichael Bowers // Determine the maximum width allowed 194daa0a102SMichael Bowers if (isset($data['width'])) { 195daa0a102SMichael Bowers // Single width value specified? Render with this width, but determine the file height and scale accordingly 196daa0a102SMichael Bowers $svg_max = $data['width']; 197daa0a102SMichael Bowers } 198daa0a102SMichael Bowers else { 199daa0a102SMichael Bowers // If a value is set, use that, else load the default value 200daa0a102SMichael Bowers $svg_max = isset($conf['plugin']['svgembed']['max_svg_width']) ? 201daa0a102SMichael Bowers $conf['plugin']['svgembed']['max_svg_width'] : 202daa0a102SMichael Bowers $this->getConf('max_svg_width'); 203daa0a102SMichael Bowers } 204daa0a102SMichael Bowers 205aedf28f1SMichael Bowers // From here, it's basically a copy of the default renderer, but it inserts SVG with an embed tag rather than img tag. 206daa0a102SMichael Bowers $ret = ''; 2079a16c2e0SEmma Bowers $hasdimensions = (isset($data['width']) || isset($data['height'])); 208daa0a102SMichael Bowers 209daa0a102SMichael Bowers // If both dimensions are not specified by the page then find them in the SVG file (if possible), and if not just pop out a default 210daa0a102SMichael Bowers if (!$hasdimensions) { 2119a16c2e0SEmma Bowers $svg_file = sprintf('%s%s', $conf['mediadir'], str_replace(':', '/', $src)); 212daa0a102SMichael Bowers 213daa0a102SMichael Bowers if (file_exists($svg_file) && ($svg_fp = fopen($svg_file, 'r'))) { 2149a16c2e0SEmma Bowers $svg_xml = simplexml_load_file($svg_file, SimpleXMLElement::class, XML_PARSE_HUGE); 215a1e3c6f8SMichael Bowers 216a1e3c6f8SMichael Bowers // Find the amount to adjust the pixels for layout if a unit is involved; use the 217a1e3c6f8SMichael Bowers // largest adjustment if they are mixed 218a1e3c6f8SMichael Bowers $svg_adjustment = max($this->Get_SVG_Unit_Adjustment($svg_xml->attributes()->width), 219a1e3c6f8SMichael Bowers $this->Get_SVG_Unit_Adjustment($svg_xml->attributes()->height)); 220a1e3c6f8SMichael Bowers 221a1e3c6f8SMichael Bowers $svg_width = round(floatval($svg_xml->attributes()->width) * $svg_adjustment); 222a1e3c6f8SMichael Bowers $svg_height = round(floatval($svg_xml->attributes()->height) * $svg_adjustment); 223daa0a102SMichael Bowers 224daa0a102SMichael Bowers if ($svg_width < 1 || $svg_height < 1) { 225daa0a102SMichael Bowers if (isset($svg_xml->attributes()->viewBox)) { 226daa0a102SMichael Bowers $svg_viewbox = preg_split('/[ ,]{1,}/', $svg_xml->attributes()->viewBox); 227daa0a102SMichael Bowers $svg_width = round(floatval($svg_viewbox[2])); 228daa0a102SMichael Bowers $svg_height = round(floatval($svg_viewbox[3])); 229daa0a102SMichael Bowers } 230daa0a102SMichael Bowers } 231daa0a102SMichael Bowers 232daa0a102SMichael Bowers if ($svg_width < 1 || $svg_height < 1) { 233daa0a102SMichael Bowers $svg_width = isset($conf['plugin']['svgembed']['default_width']) ? 234daa0a102SMichael Bowers $conf['plugin']['svgembed']['default_width'] : 23521a1ef9eSMichael Bowers $this->getConf('default_width'); 236daa0a102SMichael Bowers $svg_height = isset($conf['plugin']['svgembed']['default_height']) ? 237daa0a102SMichael Bowers $conf['plugin']['svgembed']['default_height'] : 23821a1ef9eSMichael Bowers $this->getConf('default_height'); 239daa0a102SMichael Bowers } 240daa0a102SMichael Bowers 241daa0a102SMichael Bowers unset($svg_viewbox, $svg_xml); 242daa0a102SMichael Bowers fclose($svg_fp); 243daa0a102SMichael Bowers } 244daa0a102SMichael Bowers 245daa0a102SMichael Bowers // Make sure we're not exceeding the maximum width; if so, let's scale the SVG value to the maximum size 246daa0a102SMichael Bowers if ($svg_width > $svg_max) { 247daa0a102SMichael Bowers $svg_height = round($svg_height * $svg_max / $svg_width); 248daa0a102SMichael Bowers $svg_width = $svg_max; 249daa0a102SMichael Bowers } 250daa0a102SMichael Bowers 251daa0a102SMichael Bowers $data['width'] = $svg_width; 252daa0a102SMichael Bowers $data['height'] = $svg_height; 253daa0a102SMichael Bowers } 254daa0a102SMichael Bowers else { 255daa0a102SMichael Bowers $svg_width = $data['width']; 256daa0a102SMichael Bowers $svg_height = $data['height']; 257daa0a102SMichael Bowers } 258daa0a102SMichael Bowers 259daa0a102SMichael Bowers switch($data['align']) { 260daa0a102SMichael Bowers case 'center': 261daa0a102SMichael Bowers $styleextra = "margin:auto"; 262daa0a102SMichael Bowers break; 263daa0a102SMichael Bowers case 'left': 264daa0a102SMichael Bowers case 'right': 265daa0a102SMichael Bowers $styleextra = "float:" . urlencode($data['align']); 266daa0a102SMichael Bowers break; 267daa0a102SMichael Bowers default: 268daa0a102SMichael Bowers $styleextra = ''; 269daa0a102SMichael Bowers } 270daa0a102SMichael Bowers 2719a16c2e0SEmma Bowers $svgembed_md5 = sprintf('svgembed_%s', md5(ml($src, $ml_array))); 2729a16c2e0SEmma Bowers $ret .= '<span style="display:inline'; 273daa0a102SMichael Bowers 27421a1ef9eSMichael Bowers $spanunits = (isset($data['responsiveUnits'])) ? $data['responsiveUnits'] : 'px'; 27521a1ef9eSMichael Bowers 27621a1ef9eSMichael Bowers if (isset($data['width'])) 27721a1ef9eSMichael Bowers $ret .= ";width:{$data['width']}{$spanunits}"; 27821a1ef9eSMichael Bowers 27921a1ef9eSMichael Bowers if (isset($data['height'])) 28021a1ef9eSMichael Bowers $ret .= ";height:{$data['height']}{$spanunits}"; 28121a1ef9eSMichael Bowers 28221a1ef9eSMichael Bowers if (strlen($styleextra)) 28321a1ef9eSMichael Bowers $ret .= ";{$styleextra}"; 28421a1ef9eSMichael Bowers 28521a1ef9eSMichael Bowers $ret .= '">'; 28621a1ef9eSMichael Bowers 28721a1ef9eSMichael Bowers 2886c75e5fcSMichael Bowers $ml_array = array('cache' => $data['cache']); 28921a1ef9eSMichael Bowers if (!$data['inResponsiveUnits']) 29021a1ef9eSMichael Bowers $ml_array = array_merge($ml_array, array('w' => $data['width'], 'h' => $data['height'])); 29121a1ef9eSMichael Bowers 292*6100efd5SEmma Bowers $properties = '"' . ml($src, $ml_array) . '" class="media' . hsc($data['align']) . '"'; 293aedf28f1SMichael Bowers 294aedf28f1SMichael Bowers if ($data['title']) { 295*6100efd5SEmma Bowers $properties .= ' title="' . hsc($data['title']) . '"'; 296*6100efd5SEmma Bowers $properties .= ' alt="' . hsc($data['title']) . '"'; 297aedf28f1SMichael Bowers } else { 298c8a2da89SMichael Bowers $properties .= ' alt=""'; 299aedf28f1SMichael Bowers } 300aedf28f1SMichael Bowers 3019a16c2e0SEmma Bowers/* 30221a1ef9eSMichael Bowers if (!(is_null($data['width']) || is_null($data['height']))) { 30321a1ef9eSMichael Bowers $properties .= ' style="width:100%"'; 30421a1ef9eSMichael Bowers } 3059a16c2e0SEmma Bowers // Note: 07/04/2025 -- not sure what I was going for here, but this ain't it. 3069a16c2e0SEmma Bowers*/ 3079a16c2e0SEmma Bowers 3089a16c2e0SEmma Bowers if (isset($data['width'])) 309*6100efd5SEmma Bowers $properties .= ' width="' . hsc($data['width'] . $data['responsiveUnits']) . '"'; 3109a16c2e0SEmma Bowers 3119a16c2e0SEmma Bowers if (isset($data['height'])) 312*6100efd5SEmma Bowers $properties .= ' height="' . hsc($data['width'] . $data['responsiveUnits']) . '"'; 3139a16c2e0SEmma Bowers 31421a1ef9eSMichael Bowers 31521a1ef9eSMichael Bowers 31621a1ef9eSMichael Bowers // Add any extra specified classes to the objects 31721a1ef9eSMichael Bowers if ($data['hasCssClasses'] && count($data['cssClasses']) > 0) { 31821a1ef9eSMichael Bowers $additionalCssClasses = ''; 31921a1ef9eSMichael Bowers foreach ($data['cssClasses'] as $newCssClass) 32021a1ef9eSMichael Bowers $additionalCssClasses .= " " . $renderer->_xmlEntities($newCssClass); 32121a1ef9eSMichael Bowers $additionalCssClasses = trim($additionalCssClasses); 32221a1ef9eSMichael Bowers 32321a1ef9eSMichael Bowers if (preg_match('/class="([^"]*)"/i', $properties, $pmatches)) { 32421a1ef9eSMichael Bowers $properties = str_replace("class=\"{$pmatches[1]}\"", "class=\"{$pmatches[1]} {$additionalCssClasses}\"", $properties); 32521a1ef9eSMichael Bowers } 32621a1ef9eSMichael Bowers 32721a1ef9eSMichael Bowers unset($additionalCssClasses, $newCssClass); 32821a1ef9eSMichael Bowers } 329aedf28f1SMichael Bowers 3306592c893SMichael Bowers if (is_a($renderer, 'renderer_plugin_dw2pdf')) { 331475a1642SEmma Bowers $svgembed_files = media_alternativefiles($src, ['png']); 332475a1642SEmma Bowers if (isset($svgembed_files['image/png'])) 333475a1642SEmma Bowers $properties = str_replace(ml($src, $ml_array), ml($svgembed_files['image/png'], $ml_array), $properties); 334475a1642SEmma Bowers 3356592c893SMichael Bowers $ret .= "<img id=\"" . $svgembed_md5 . "\" src={$properties} />"; 3366592c893SMichael Bowers } 3376592c893SMichael Bowers else { 33880b00982SMichael Bowers $ret .= "<object id=\"" . $svgembed_md5 . "\" type=\"image/svg+xml\" data={$properties}><embed type=\"image/svg+xml\" src={$properties} /></object>"; 339c8a2da89SMichael Bowers 340c8a2da89SMichael Bowers unset($properties); 341c8a2da89SMichael Bowers 342281d738fSMichael Bowers if ($data['print']) { 3431e6acb34SMichael Bowers $ret .= '<div class="svgprintbutton_table"><button type="submit" title="Print SVG" onClick="svgembed_printContent(\'' . 3449a16c2e0SEmma Bowers urlencode(ml($src, $ml_array)) . '\'); return false" onMouseOver="svgembed_onMouseOver(\'' . $svgembed_md5 . 3459a16c2e0SEmma Bowers '\'); return false" ' . 'onMouseOut="svgembed_onMouseOut(\'' . $svgembed_md5 . '\'); return false"' . 346281d738fSMichael Bowers '>Print SVG</button></div>'; 347281d738fSMichael Bowers } 3486592c893SMichael Bowers } 34980b00982SMichael Bowers 350c8a2da89SMichael Bowers $ret .= '</span>'; 351aedf28f1SMichael Bowers 352aedf28f1SMichael Bowers $renderer->doc .= $ret; 353a93b1ea1SMichael Bowers } 354a93b1ea1SMichael Bowers 3559a16c2e0SEmma Bowers if ($mode == 'metadata' && $isInternal) { 356a93b1ea1SMichael Bowers // Add metadata so the SVG is associated to the page 357a93b1ea1SMichael Bowers $renderer->meta['relation']['media'][$src] = $exists; 358a93b1ea1SMichael Bowers } 359a93b1ea1SMichael Bowers 360aedf28f1SMichael Bowers return true; 361aedf28f1SMichael Bowers } 362aedf28f1SMichael Bowers} 363