import { retext } from "retext";
import { visit } from "unist-util-visit";
import smartypants from "retext-smartypants";
const VISITED_NODES = new Set(["text", "inlineCode"]);
const IGNORED_HTML_ELEMENTS = new Set(["style", "script"]);
const check = (node, index, parent) => {
    return (parent &&
        (parent.type !== "mdxJsxTextElement" ||
            ("name" in parent &&
                typeof parent.name === "string" &&
                !IGNORED_HTML_ELEMENTS.has(parent.name))) &&
        VISITED_NODES.has(node.type) &&
        isLiteral(node));
};
/**
 * remark plugin to implement SmartyPants.
 */
const remarkSmartypants = (options) => {
    const processor = retext().use(smartypants, {
        ...options,
        // Do not replace ellipses, dashes, backticks because they change string
        // length, and we couldn't guarantee right splice of text in second visit of
        // tree
        ellipses: false,
        dashes: false,
        backticks: false,
    });
    const processor2 = retext().use(smartypants, {
        ...options,
        // Do not replace quotes because they are already replaced in the first
        // processor
        quotes: false,
    });
    return (tree) => {
        let allText = "";
        let startIndex = 0;
        const nodes = [];
        visit(tree, check, (node) => {
            if (!isLiteral(node))
                return;
            allText +=
                node.type === "text" ? node.value : "A".repeat(node.value.length);
            nodes.push(node);
        });
        // Concat all text into one string, to properly replace quotes around links
        // and bold text
        allText = processor.processSync(allText).toString();
        for (const node of nodes) {
            const endIndex = startIndex + node.value.length;
            if (node.type === "text") {
                const processedText = allText.slice(startIndex, endIndex);
                node.value = processor2.processSync(processedText).toString();
            }
            startIndex = endIndex;
        }
    };
};
function isLiteral(node) {
    return "value" in node && typeof node.value === "string";
}
export default remarkSmartypants;
