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 = DocumentationHelper::normalizePath(dirname($page->getRelativePath()));

        if (strpos($page->getRelativePath(), 'index.md')) {
            $relativeLink = $page->getRelativeLink();
        } else {
            $relativeLink = DocumentationHelper::normalizePath(dirname($page->getRelativeLink()));
        }

        if ($relativePath == '.') {
            $relativePath = '';
        }

        if ($relativeLink == ".") {
            $relativeLink = '';
        }

        // file base link
        $fileBaseLink = DocumentationHelper::relativePath(DocumentationHelper::normalizePath(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
                    );
                } elseif (preg_match('/^#/', $url)) {
                    // for relative links begining with a hash use the current page link
                    $relativeUrl = Controller::join_links($baselink, $page->getRelativeLink(), $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;
    }