/**
     * Rewrite links with special "api:" prefix, from two possible formats:
     * 1. [api:DataObject]
     * 2. (My Title)(api:DataObject)
     * 
     * Hack: Replaces any backticks with "<code>" blocks,
     * as the currently used markdown parser doesn't resolve links in backticks,
     * but does resolve in "<code>" blocks.
     * 
     * @param String $md
     * @param DocumentationPage $page
     * @return String
     */
    static function rewrite_api_links($md, $page)
    {
        // Links with titles
        $re = '/
			`?
			\\[
				(.*?) # link title (non greedy)
			\\] 
			\\(
				api:(.*?) # link url (non greedy)
			\\)
			`?
		/x';
        preg_match_all($re, $md, $linksWithTitles);
        if ($linksWithTitles) {
            foreach ($linksWithTitles[0] as $i => $match) {
                $title = $linksWithTitles[1][$i];
                $subject = $linksWithTitles[2][$i];
                $url = sprintf(self::$api_link_base, $subject, $page->getVersion(), $page->getEntity()->getModuleFolder());
                $md = str_replace($match, sprintf('<code>[%s](%s)</code>', $title, $url), $md);
            }
        }
        // Bare links
        $re = '/
			`?
			\\[
				api:(.*?)
			\\]
			`?
		/x';
        preg_match_all($re, $md, $links);
        if ($links) {
            foreach ($links[0] as $i => $match) {
                $subject = $links[1][$i];
                $url = sprintf(self::$api_link_base, $subject, $page->getVersion(), $page->getEntity()->getModuleFolder());
                $md = str_replace($match, sprintf('<code>[%s](%s)</code>', $subject, $url), $md);
            }
        }
        return $md;
    }
    /**
     * Resolves all relative links within markdown.
     * 
     * @param String $md Markdown content
     * @param DocumentationPage $page
     *
     * @return String Markdown
     */
    public static function rewrite_relative_links($md, $page)
    {
        $baselink = $page->getEntity()->Link();
        $re = '/
			([^\\!]?) # exclude image format
			\\[
				(.*?) # link title (non greedy)
			\\] 
			\\(
				(.*?) # link url (non greedy)
			\\)
		/x';
        preg_match_all($re, $md, $matches);
        // relative path (relative to module base folder), without the filename.
        // For "sapphire/en/current/topics/templates", this would be "templates"
        $relativePath = dirname($page->getRelativePath());
        if (strpos($page->getRelativePath(), 'index.md')) {
            $relativeLink = $page->getRelativeLink();
        } else {
            $relativeLink = dirname($page->getRelativeLink());
        }
        if ($relativePath == '.') {
            $relativePath = '';
        }
        if ($relativeLink == ".") {
            $relativeLink = '';
        }
        // file base link
        $fileBaseLink = Director::makeRelative(dirname($page->getPath()));
        if ($matches) {
            foreach ($matches[0] as $i => $match) {
                $title = $matches[2][$i];
                $url = $matches[3][$i];
                // Don't process API links
                if (preg_match('/^api:/', $url)) {
                    continue;
                }
                // Don't process absolute links (based on protocol detection)
                $urlParts = parse_url($url);
                if ($urlParts && isset($urlParts['scheme'])) {
                    continue;
                }
                // for images we need to use the file base path
                if (preg_match('/_images/', $url)) {
                    $relativeUrl = Controller::join_links(Director::absoluteBaseURL(), $fileBaseLink, $url);
                } else {
                    // Rewrite public URL
                    if (preg_match('/^\\//', $url)) {
                        // Absolute: Only path to module base
                        $relativeUrl = Controller::join_links($baselink, $url, '/');
                    } else {
                        // Relative: Include path to module base and any folders
                        $relativeUrl = Controller::join_links($baselink, $relativeLink, $url, '/');
                    }
                }
                // Resolve relative paths
                while (strpos($relativeUrl, '..') !== FALSE) {
                    $relativeUrl = preg_replace('/[-\\w]+\\/\\.\\.\\//', '', $relativeUrl);
                }
                // Replace any double slashes (apart from protocol)
                $relativeUrl = preg_replace('/([^:])\\/{2,}/', '$1/', $relativeUrl);
                // Replace in original content
                $md = str_replace($match, sprintf('%s[%s](%s)', $matches[1][$i], $title, $relativeUrl), $md);
            }
        }
        return $md;
    }
 /**
  * @return DocumentationEntity
  */
 public function getEntity()
 {
     return $this->record ? $this->record->getEntity() : null;
 }