@mintlify/link-rot
Version: 
Static checking for broken internal links
73 lines (72 loc) • 3.46 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { coreRemark } from '@mintlify/common';
import fs from 'fs-extra';
import { normalize } from 'path';
import { visit } from 'unist-util-visit';
/**
 * Go through fileContent and replace all links that match existingLink with newLink
 */
const getContentWithRenamedInternalLinks = (fileContent, existingLink, newLink) => __awaiter(void 0, void 0, void 0, function* () {
    let numRenamedLinks = 0;
    const remarkMdxReplaceLinks = () => {
        return (tree) => {
            visit(tree, (node) => {
                if ((node.type === 'link' || node.type === 'image') &&
                    node.url &&
                    normalize(node.url) === existingLink) {
                    node.url = newLink;
                    numRenamedLinks++;
                    return;
                }
                const mdxJsxFlowElement = node;
                if (mdxJsxFlowElement.name === 'img' || mdxJsxFlowElement.name === 'source') {
                    const srcAttr = mdxJsxFlowElement.attributes.find((attr) => attr.type === 'mdxJsxAttribute' && attr.name === 'src');
                    if (srcAttr &&
                        'value' in srcAttr &&
                        typeof srcAttr.value === 'string' &&
                        normalize(srcAttr.value) === existingLink) {
                        srcAttr.value = newLink;
                        numRenamedLinks++;
                        return;
                    }
                }
                else if (mdxJsxFlowElement.name === 'a' || mdxJsxFlowElement.name === 'Card') {
                    const hrefAttr = mdxJsxFlowElement.attributes.find((attr) => attr.type === 'mdxJsxAttribute' && attr.name === 'href');
                    if (hrefAttr &&
                        'value' in hrefAttr &&
                        typeof hrefAttr.value === 'string' &&
                        normalize(hrefAttr.value) === existingLink) {
                        hrefAttr.value = newLink;
                        numRenamedLinks++;
                        return;
                    }
                }
                return;
            });
        };
    };
    const file = yield coreRemark().use(remarkMdxReplaceLinks).process(fileContent);
    return {
        numRenamedLinks,
        newContent: String(file),
    };
});
const renameInternalLinksInPage = (filePath, oldLink, newLink) => __awaiter(void 0, void 0, void 0, function* () {
    const fileContent = fs.readFileSync(filePath).toString();
    const { numRenamedLinks, newContent } = yield getContentWithRenamedInternalLinks(fileContent, oldLink, newLink);
    if (numRenamedLinks > 0) {
        fs.outputFileSync(filePath, newContent, {
            flag: 'w',
        });
    }
    return numRenamedLinks;
});
export default renameInternalLinksInPage;