daux = $daux; } /** * @param string $url * @return Entry * @throws LinkNotFoundException */ protected function resolveInternalFile($url) { $triedAbsolute = false; // Legacy absolute paths could start with // "!" In this case we will try to find // the file starting at the root if ($url[0] == '!' || $url[0] == '/') { $url = ltrim($url, '!/'); if ($file = DauxHelper::getFile($this->daux['tree'], $url)) { return $file; } $triedAbsolute = true; } // Seems it's not an absolute path or not found, // so we'll continue with the current folder if ($file = DauxHelper::getFile($this->daux->getCurrentPage()->getParent(), $url)) { return $file; } // If we didn't already try it, we'll // do a pass starting at the root if (!$triedAbsolute && $file = DauxHelper::getFile($this->daux['tree'], $url)) { return $file; } throw new LinkNotFoundException("Could not locate file '$url'"); } protected function isValidUrl($url) { return !empty($url) && $url[0] != '#'; } protected function isExternalUrl($url) { return preg_match('#^(?:[a-z]+:)?//|^mailto:#', $url); } /** * @param AbstractInline|Link $inline * @param ElementRendererInterface $htmlRenderer * @return HtmlElement * @throws LinkNotFoundException */ public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer) { // This can't be in the method type as // the method is an abstract and should // have the same interface if (!$inline instanceof Link) { throw new \RuntimeException( 'Wrong type passed to ' . __CLASS__ . '::' . __METHOD__ . " the expected type was 'League\\CommonMark\\Inline\\Element\\Link' but '" . get_class($inline) . "' was provided" ); } $element = parent::render($inline, $htmlRenderer); $url = $inline->getUrl(); // empty urls and anchors should // not go through the url resolver if (!$this->isValidUrl($url)) { return $element; } // Absolute urls, shouldn't either if ($this->isExternalUrl($url)) { $element->setAttribute('class', 'Link--external'); return $element; } // if there's a hash component in the url, ensure we // don't put that part through the resolver. $urlAndHash = explode('#', $url); $url = $urlAndHash[0]; $foundWithHash = false; try { $file = $this->resolveInternalFile($url); $url = DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl()); } catch (LinkNotFoundException $e) { // For some reason, the filename could contain a # and thus the link needs to resolve to that. try { if (strlen($urlAndHash[1] ?? "") > 0) { $file = $this->resolveInternalFile($url . '#' . $urlAndHash[1]); $url = DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl()); $foundWithHash = true; } } catch (LinkNotFoundException $e2) { // If it's still not found here, we'll only // report on the first error as the second // one will tell the same. } if (!$foundWithHash) { if ($this->daux->isStatic()) { throw $e; } $element->setAttribute('class', 'Link--broken'); } } if (!$foundWithHash && isset($urlAndHash[1])) { $url .= '#' . $urlAndHash[1]; } $element->setAttribute('href', $url); return $element; } }