UNPKG

@mintlify/common

Version:

Commonly shared code within Mintlify

49 lines (48 loc) 2.02 kB
import { posix } from 'path'; import { visit } from 'unist-util-visit'; const isRelative = (url) => url.startsWith('./') || url.startsWith('../'); const resolveRelative = (baseDir, url) => { // Preserve any fragment or query string verbatim. const splitIndex = url.search(/[#?]/); const pathPart = splitIndex === -1 ? url : url.slice(0, splitIndex); const tail = splitIndex === -1 ? '' : url.slice(splitIndex); const resolved = posix.normalize(posix.join(baseDir, pathPart)); const absolute = resolved.startsWith('/') && !resolved.startsWith('//') ? resolved : `/${resolved}`; return absolute + tail; }; const ATTR_BY_TAG = { a: 'href', Card: 'href', img: 'src', source: 'src', }; export const remarkResolveRelativeLinks = (options = {}) => { return (tree) => { const { path } = options; if (!path) return; const stripped = path.replace(/^\/+/, '').replace(/\.mdx?$/i, ''); const dir = posix.dirname(stripped); const baseDir = dir === '.' || dir === '' ? '/' : `/${dir}`; visit(tree, (node) => { if (node.type === 'link' || node.type === 'image') { const linkOrImg = node; if (linkOrImg.url && isRelative(linkOrImg.url)) { linkOrImg.url = resolveRelative(baseDir, linkOrImg.url); } return; } if (node.type !== 'mdxJsxFlowElement' && node.type !== 'mdxJsxTextElement') { return; } const jsxNode = node; const attrName = jsxNode.name ? ATTR_BY_TAG[jsxNode.name] : undefined; if (!attrName) return; const attr = jsxNode.attributes.find((a) => a.type === 'mdxJsxAttribute' && a.name === attrName); if (attr && 'value' in attr && typeof attr.value === 'string' && isRelative(attr.value)) { attr.value = resolveRelative(baseDir, attr.value); } }); }; };