{"version":3,"file":"index.cjs","names":[],"sources":["../libs/replace-node.ts","../libs/utils/significant-node.ts","../libs/utils/join-without-excess-whitespace.ts","../libs/utils/wrap-significant-content.ts","../libs/utils/replace-streaming-command-in-array.ts","../libs/replace-streaming-command.ts","../libs/replace-node-during-visit.ts","../libs/unified-latex-streaming-command.ts","../index.ts"],"sourcesContent":["import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { visit, VisitInfo } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Recursively replace nodes in `ast`. The `visitor` function is called on each node. If\n * `visitor` returns a node or an array of nodes, those nodes replace the node passed to `visitor`.\n * If `null` is returned, the node is deleted. If `undefined` is returned, no replacement happens.\n */\nexport function replaceNode(\n    ast: Ast.Ast,\n    visitor: (\n        node: Ast.Node | Ast.Argument,\n        info: VisitInfo\n    ) =>\n        | Ast.Node\n        | Ast.Argument\n        | (Ast.Node | Ast.Argument)[]\n        | null\n        | undefined\n        | void\n) {\n    visit(ast, {\n        leave: (node, info) => {\n            let replacement = visitor(node, info);\n            // Returning `undefined` or the same node means we shouldn't replace that node\n            if (typeof replacement === \"undefined\" || replacement === node) {\n                return;\n            }\n\n            if (!info.containingArray || info.index == null) {\n                throw new Error(\n                    \"Trying to replace node, but cannot find containing array\"\n                );\n            }\n\n            if (\n                replacement === null ||\n                (Array.isArray(replacement) && replacement.length === 0)\n            ) {\n                // A null return means that we delete the current node\n                info.containingArray.splice(info.index, 1);\n                return info.index;\n            }\n\n            if (!Array.isArray(replacement)) {\n                replacement = [replacement];\n            }\n\n            info.containingArray.splice(info.index, 1, ...replacement);\n            // We don't want to *reprocess* the nodes we just inserted into the array,\n            // lest we get stuck in a recursive loop if the replacement contains the original.\n            // Thus we jump to the index after our replacements.\n            return info.index + replacement.length;\n        },\n    });\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\n\n/**\n * Returns the first non-whitespace/non-comment node in `nodes`. If there is no such\n * node, `null` is returned.\n */\nexport function firstSignificantNode(\n    nodes: Ast.Node[],\n    parbreaksAreInsignificant?: boolean\n): Ast.Node | null {\n    const index = firstSignificantNodeIndex(nodes, parbreaksAreInsignificant);\n    if (index == null) {\n        return null;\n    }\n    return nodes[index];\n}\n\n/**\n * Returns the last non-whitespace/non-comment node in `nodes`. If there is no such\n * node, `null` is returned.\n */\nexport function lastSignificantNode(\n    nodes: Ast.Node[],\n    parbreaksAreInsignificant?: boolean\n): Ast.Node | null {\n    const index = lastSignificantNodeIndex(nodes, parbreaksAreInsignificant);\n    if (index == null) {\n        return null;\n    }\n    return nodes[index];\n}\n\n/**\n * Returns the index of the last non-whitespace/non-comment node in `nodes`. If there is no such\n * node, `null` is returned.\n */\nexport function lastSignificantNodeIndex(\n    nodes: Ast.Node[],\n    parbreaksAreInsignificant?: boolean\n): number | undefined {\n    for (let i = nodes.length - 1; i >= 0; i--) {\n        const node = nodes[i];\n        if (\n            match.whitespace(node) ||\n            match.comment(node) ||\n            (parbreaksAreInsignificant && match.parbreak(node))\n        ) {\n            continue;\n        }\n        return i;\n    }\n    return undefined;\n}\n\n/**\n * Returns the index of the first non-whitespace/non-comment node in `nodes`. If there is no such\n * node, `null` is returned.\n */\nexport function firstSignificantNodeIndex(\n    nodes: Ast.Node[],\n    parbreaksAreInsignificant?: boolean\n): number | undefined {\n    for (let i = 0; i < nodes.length; i++) {\n        const node = nodes[i];\n        if (\n            match.whitespace(node) ||\n            match.comment(node) ||\n            (parbreaksAreInsignificant && match.parbreak(node))\n        ) {\n            continue;\n        }\n        return i;\n    }\n    return undefined;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { trimStart } from \"@unified-latex/unified-latex-util-trim\";\n\n/**\n * Is the node space-like? I.e., is it whitespace or\n * a comment with leading whitespace?\n */\nfunction isSpaceLike(node: Ast.Node): boolean {\n    return (\n        match.whitespace(node) ||\n        (match.comment(node) && Boolean(node.leadingWhitespace))\n    );\n}\n\n/**\n * Similar to `head.push(...tail)` except that whitespace at the start\n * of `tail` and the end of `head` is collapsed.\n */\nexport function joinWithoutExcessWhitespace(\n    head: Ast.Node[],\n    tail: Ast.Node[]\n): void {\n    if (tail.length === 0) {\n        return;\n    }\n    if (head.length === 0) {\n        head.push(...tail);\n        return;\n    }\n    const headEnd = head[head.length - 1];\n    const tailStart = tail[0];\n    // Whitespace we can just trim off from either end\n    if (match.whitespace(headEnd) && match.whitespace(tailStart)) {\n        head.push(...tail.slice(1));\n        return;\n    }\n    // If there's no whitespace at one of the ends, no need to worry\n    // unless `tailStart` is a comment, in which case it should \"eat\"\n    // the whitespace\n    if (!isSpaceLike(headEnd) || !isSpaceLike(tailStart)) {\n        if (match.whitespace(headEnd) && match.comment(tailStart)) {\n            const comment: Ast.Comment = {\n                type: \"comment\",\n                content: tailStart.content,\n                sameline: true,\n                leadingWhitespace: true,\n            };\n            tail = tail.slice(1);\n            trimStart(tail);\n            head.pop();\n            head.push(comment, ...tail);\n            return;\n        }\n        head.push(...tail);\n        return;\n    }\n\n    // If we're here, we have a comment with leading whitespace on one side\n    // and whitespace/comments on the other.\n    if (match.comment(headEnd) && match.comment(tailStart)) {\n        if (tailStart.leadingWhitespace || tailStart.sameline) {\n            head.push(\n                { type: \"comment\", content: tailStart.content },\n                ...tail.slice(1)\n            );\n            return;\n        }\n        head.push(...tail);\n        return;\n    }\n\n    // Exactly one side is a comment, so we should trim the whitespace and keep the comment,\n    // but make sure the comment has leading whitespace!\n    let comment = match.comment(headEnd) ? headEnd : tailStart;\n    if (!match.comment(comment)) {\n        throw new Error(\n            `Expected a comment but found ${JSON.stringify(comment)}`\n        );\n    }\n\n    if (!comment.leadingWhitespace || !comment.sameline) {\n        comment = {\n            type: \"comment\",\n            content: comment.content,\n            leadingWhitespace: true,\n            sameline: true,\n        };\n    }\n\n    head.pop();\n    head.push(comment, ...tail.slice(1));\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\n\n/**\n * Wraps `content` in the specified wrapper. This command is roughly equivalent to\n * `wrapper(content)` except that leading and trailing whitespace and comments are extracted\n * from `content` and moved to the front or back of the return array. For example,\n * `[\" \", \"foo\", \"bar\", \"% xxx\"]` -> `[\" \", wrapped([\"foo\", \"bar\"]), \"% xxx\"]`.\n *\n */\nexport function wrapSignificantContent(\n    content: Ast.Node[],\n    wrapper: (content: Ast.Node[]) => Ast.Node[] | Ast.Node\n): Ast.Node[] {\n    let hoistUntil = 0;\n    let hoistAfter = content.length;\n    for (let i = 0; i < content.length; i++) {\n        if (match.whitespace(content[i]) || match.comment(content[i])) {\n            hoistUntil = i + 1;\n            continue;\n        }\n        break;\n    }\n    for (let j = content.length - 1; j >= 0; j--) {\n        if (match.whitespace(content[j]) || match.comment(content[j])) {\n            hoistAfter = j;\n            continue;\n        }\n        break;\n    }\n\n    if (hoistUntil === 0 && hoistAfter === content.length) {\n        return ensureArray(wrapper(content));\n    }\n\n    const frontMatter = content.slice(0, hoistUntil);\n    const middle = content.slice(hoistUntil, hoistAfter);\n    const backMatter = content.slice(hoistAfter, content.length);\n\n    return frontMatter.concat(wrapper(middle), backMatter);\n}\n\nfunction ensureArray(x: Ast.Node | Ast.Node[]) {\n    if (!Array.isArray(x)) {\n        return [x];\n    }\n    return x;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { trimEnd, trimStart } from \"@unified-latex/unified-latex-util-trim\";\nimport { joinWithoutExcessWhitespace } from \"./join-without-excess-whitespace\";\nimport { wrapSignificantContent } from \"./wrap-significant-content\";\n\n/**\n * Replace commands identified by `isStreamingCommand` with the return value of `replacer`.\n * E.g., the array `[head, streamingCommand, ...tail]` will become `[head, replacer(tail, streamingCommand)]`.\n * This function does not split based on parbreaks/etc.. It is right-associative and returns\n * the streaming commands that were encountered.\n */\nexport function replaceStreamingCommandInArray(\n    nodes: Ast.Node[],\n    isStreamingCommand: (node: any) => node is Ast.Macro,\n    replacer: (\n        content: Ast.Node[],\n        streamingCommand: Ast.Macro\n    ) => Ast.Node | Ast.Node[]\n): { foundStreamingCommands: Ast.Node[] } {\n    // Streaming commands that come at the end don't do anything,\n    // so we should remove them\n    while (nodes.length > 0 && isStreamingCommand(nodes[nodes.length - 1])) {\n        nodes.pop();\n        trimEnd(nodes);\n    }\n\n    const foundStreamingCommands: Ast.Node[] = [];\n\n    for (let i = nodes.length - 1; i >= 0; i--) {\n        const node = nodes[i];\n        if (isStreamingCommand(node)) {\n            const wrapper = (content: Ast.Node[]) => replacer(content, node);\n            let tail = nodes.slice(i + 1);\n            // Streaming commands are followed by whitespace, which becomes unneeded when the commands are replaced.\n            trimStart(tail);\n            tail = wrapSignificantContent(tail, wrapper);\n            foundStreamingCommands.push(node);\n\n            // Trim off what we're about to replace!\n            nodes.splice(i);\n\n            joinWithoutExcessWhitespace(nodes, tail);\n        }\n    }\n\n    return { foundStreamingCommands };\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport {\n    splitOnCondition,\n    unsplitOnMacro,\n} from \"@unified-latex/unified-latex-util-split\";\nimport {\n    trim,\n    trimEnd,\n    trimStart,\n} from \"@unified-latex/unified-latex-util-trim\";\nimport { firstSignificantNode } from \"./utils/significant-node\";\nimport { replaceStreamingCommandInArray } from \"./utils/replace-streaming-command-in-array\";\nimport { wrapSignificantContent } from \"./utils/wrap-significant-content\";\n\ntype Replacer = (nodes: Ast.Node[]) => Ast.Node[];\n\n/**\n * Process streaming commands in a group. If needed, \"escape\" the group.\n * For example, `{\\bfseries xx}` -> `\\textbf{xx}`, but `{foo \\bfseries xx}` -> `{foo \\textbf{xx}}`.\n */\nexport function replaceStreamingCommandInGroup(\n    group: Ast.Group,\n    isStreamingCommand: (node: any) => node is Ast.Macro,\n    replacer: (\n        content: Ast.Node[],\n        streamingCommand: Ast.Macro\n    ) => Ast.Node | Ast.Node[],\n    options?: {\n        macrosThatBreakPars?: string[];\n        environmentsThatDontBreakPars?: string[];\n    }\n): Ast.Node[] {\n    const content = group.content;\n    // If the group started with a streaming command, we want to pop\n    // out of the group. E.g. `{\\bfseries foo}` -> `\\textbf{foo}` and not `{\\textbf{foo}}`\n    let popFromGroup = isStreamingCommand(firstSignificantNode(content));\n\n    let innerProcessed = replaceStreamingCommand(\n        content,\n        isStreamingCommand,\n        replacer,\n        options\n    );\n\n    // If the group consisted of just streaming commands (for some reason...)\n    // it should be eliminated\n    if (innerProcessed.length === 0) {\n        return [];\n    }\n\n    if (popFromGroup) {\n        return innerProcessed;\n    } else {\n        return [{ type: \"group\", content: innerProcessed }];\n    }\n}\n\n/**\n * Given a group or a node array, look for streaming commands (e.g., `\\bfseries`) and replace them\n * with the specified macro. The \"arguments\" of the streaming command are passed to `replacer` and the return\n * value of `replacer` is inserted into the stream.\n *\n * By default, this command will split at parbreaks (since commands like `\\textbf{...} do not accept parbreaks in their\n * contents) and call `replacer` multiple times, once per paragraph.\n *\n * Commands are also split at environments and at any macros listed in `macrosThatBreakPars`.\n */\nexport function replaceStreamingCommand(\n    ast: Ast.Group | Ast.Node[],\n    isStreamingCommand: (node: any) => node is Ast.Macro,\n    replacer: (\n        content: Ast.Node[],\n        streamingCommand: Ast.Macro\n    ) => Ast.Node | Ast.Node[],\n    options?: {\n        macrosThatBreakPars?: string[];\n        environmentsThatDontBreakPars?: string[];\n    }\n): Ast.Node[] {\n    if (typeof isStreamingCommand !== \"function\") {\n        throw new Error(\n            `'isStreamingCommand' must be a function, not '${typeof isStreamingCommand}'`\n        );\n    }\n\n    const {\n        macrosThatBreakPars = [\n            \"part\",\n            \"chapter\",\n            \"section\",\n            \"subsection\",\n            \"subsubsection\",\n            \"vspace\",\n            \"smallskip\",\n            \"medskip\",\n            \"bigskip\",\n            \"hfill\",\n        ],\n        environmentsThatDontBreakPars = [],\n    } = options || {};\n\n    let processedContent: Ast.Node[] = [];\n    if (match.group(ast)) {\n        processedContent = replaceStreamingCommandInGroup(\n            ast,\n            isStreamingCommand,\n            replacer\n        );\n    }\n\n    if (Array.isArray(ast)) {\n        // Streaming commands that come at the end of a sequence of nodes don't do anything.\n        // They also will consume whitespace, so we should remove them and the whitespace.\n        const nodes = ast;\n        let scanIndex = nodes.length;\n        let sliceIndex = scanIndex;\n        while (\n            scanIndex > 0 &&\n            (isStreamingCommand(nodes[scanIndex - 1]) ||\n                match.whitespace(nodes[scanIndex - 1]))\n        ) {\n            scanIndex--;\n            if (isStreamingCommand(nodes[scanIndex])) {\n                sliceIndex = scanIndex;\n            }\n        }\n        if (sliceIndex !== nodes.length) {\n            nodes.splice(sliceIndex);\n        }\n\n        const macroThatBreaks = match.createMacroMatcher(macrosThatBreakPars);\n        const envThatDoesntBreak = match.createEnvironmentMatcher(\n            environmentsThatDontBreakPars\n        );\n        // A \"par\" is anything that a streaming command shouldn't wrap and breaks the stream.\n        // This includes regular pars, but also environments and special macros like \\section\n        const isPar = (node: Ast.Node) =>\n            match.parbreak(node) ||\n            match.macro(node, \"par\") ||\n            macroThatBreaks(node) ||\n            (match.environment(node) && !envThatDoesntBreak(node)) ||\n            node.type === \"displaymath\";\n\n        // We split on both a parbreak and a literal `\\par`. But we will\n        // normalize everything to be parbreaks\n        const splitByPar = splitOnCondition(nodes, isPar);\n        splitByPar.separators = splitByPar.separators.map((sep) =>\n            match.macro(sep, \"par\") ? { type: \"parbreak\" } : sep\n        );\n\n        const replacers: Replacer[] = [];\n        let segments = splitByPar.segments.map((segment) => {\n            if (segment.length === 0) {\n                return segment;\n            }\n            function applyAccumulatedReplacers(nodes: Ast.Node[]): Ast.Node[] {\n                if (replacers.length === 0) {\n                    return nodes;\n                }\n                return wrapSignificantContent(\n                    nodes,\n                    composeReplacers(replacers)\n                );\n            }\n\n            const { foundStreamingCommands } = replaceStreamingCommandInArray(\n                segment,\n                isStreamingCommand,\n                replacer\n            );\n\n            // All streaming commands in `segment` have now been replaced. However,\n            // there might be commands from the previous paragraphs that should wrap\n            // the current segment!\n            const ret = applyAccumulatedReplacers(segment);\n\n            // Any streaming commands from this segment will carry over to the next,\n            // so keep track of them.\n            foundStreamingCommands.forEach((macro) => {\n                replacers.push((nodes: Ast.Node[]) => {\n                    const ret = replacer(nodes, macro as Ast.Macro);\n                    if (!Array.isArray(ret)) {\n                        return [ret];\n                    }\n                    return ret;\n                });\n            });\n\n            return ret;\n        });\n\n        // Leading/trailing whitespace was hoisted in front/back of each replacer.\n        // Since we're separated by parbreaks, we can safely trim all that whitespace.\n        if (segments.length > 1) {\n            segments.forEach((segment, i) => {\n                if (i === 0) {\n                    trimEnd(segment);\n                } else if (i === segments.length - 1) {\n                    trimStart(segment);\n                } else {\n                    trim(segment);\n                }\n            });\n        }\n\n        processedContent = unsplitOnMacro({\n            segments: segments,\n            macros: splitByPar.separators,\n        });\n    }\n\n    return processedContent;\n}\n\n/**\n * Given a sequence of replacer functions `[f, g, h]` return\n * `h \\circ g \\circ f`\n *\n * @param {((nodes: Ast.Node[]) => Ast.Node)[]} replacers\n * @returns {(nodes: Ast.Node[]) => Ast.Node}\n */\nfunction composeReplacers(replacers: Replacer[]): Replacer {\n    if (replacers.length === 0) {\n        throw new Error(\"Cannot compose zero replacement functions\");\n    }\n    return (nodes: Ast.Node[]) => {\n        let ret = nodes;\n        for (let i = 0; i < replacers.length; i++) {\n            const func = replacers[i];\n            ret = func(ret);\n        }\n        return ret;\n    };\n}\n","import { VisitInfo } from \"@unified-latex/unified-latex-util-visit\";\nimport * as Ast from \"@unified-latex/unified-latex-types\";\n\n/**\n * Replaces the current node with `replacement`. It is assumed that the current\n * node is in an array that is a child of a parent element. If this is not the case,\n * the function will error.\n */\nexport function replaceNodeDuringVisit(\n    replacement: Ast.Node | Ast.Argument | (Ast.Node | Ast.Argument)[],\n    info: VisitInfo\n) {\n    const parent = info.parents[0];\n    if (!parent) {\n        throw new Error(`Cannot replace node: parent not found`);\n    }\n    const container = parent[info.key as keyof typeof parent] as\n        | (Ast.Node | Ast.Argument)[]\n        | undefined;\n    if (!Array.isArray(container)) {\n        throw new Error(`Cannot replace node: containing array not found`);\n    }\n    if (info.index == null) {\n        throw new Error(`Cannot replace node: node index undefined`);\n    }\n    if (!Array.isArray(replacement)) {\n        container[info.index] = replacement;\n    } else {\n        container.splice(info.index, 1, ...replacement);\n    }\n}\n","import { Plugin } from \"unified\";\nimport * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { trimEnd, trimStart } from \"@unified-latex/unified-latex-util-trim\";\nimport { visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { replaceStreamingCommand } from \"./replace-streaming-command\";\nimport { replaceNodeDuringVisit } from \"./replace-node-during-visit\";\n\ntype PluginOptions = {\n    replacers: Record<\n        string,\n        (\n            content: Ast.Node[],\n            streamingCommand: Ast.Macro\n        ) => Ast.Node | Ast.Node[]\n    >;\n};\n\n/**\n * Unified plugin to replace all found streaming commands with their argument-style equivalents.\n * This only applies to sections of the tree with no math ancestor.\n *\n * @param options.replacer A record of macro names and replacer functions. A replacer function accepts content and the original streaming command and is expected to return the argument-style command. It may be called multiple times per streaming command.\n */\nexport const unifiedLatexReplaceStreamingCommands: Plugin<\n    PluginOptions[],\n    Ast.Root,\n    Ast.Root\n> = function unifiedLatexReplaceStreamingCommands(options) {\n    const { replacers = {} } = options || {};\n    const isReplaceable = match.createMacroMatcher(replacers);\n    return (tree) => {\n        // We traverse all groups before we replace nodes in other contexts\n        visit(\n            tree,\n            (group, info) => {\n                if (\n                    info.context.hasMathModeAncestor ||\n                    !group.content.some(isReplaceable)\n                ) {\n                    return;\n                }\n\n                let fixed = replaceStreamingCommand(\n                    group,\n                    isReplaceable,\n                    (content, command) => {\n                        return replacers[command.content](content, command);\n                    }\n                );\n\n                // We cannot replace the node unless we can access the containing array.\n                if (!info.containingArray || info.index == null) {\n                    return;\n                }\n\n                // `fixed` may consist of only whitespace. If this is the case,\n                // surrounding whitespace must trimmed before\n                // inserting the group's contents.\n                const prevToken = info.containingArray[info.index - 1];\n                const nextToken = info.containingArray[info.index + 1];\n                if (\n                    match.whitespaceLike(prevToken) &&\n                    match.whitespaceLike(fixed[0])\n                ) {\n                    trimStart(fixed);\n                }\n                if (\n                    match.whitespaceLike(nextToken) &&\n                    match.whitespaceLike(fixed[fixed.length - 1])\n                ) {\n                    trimEnd(fixed);\n                }\n                replaceNodeDuringVisit(fixed, info);\n            },\n            { test: match.group }\n        );\n\n        visit(\n            tree,\n            (nodes, info) => {\n                if (\n                    info.context.hasMathModeAncestor ||\n                    !nodes.some(isReplaceable)\n                ) {\n                    return;\n                }\n\n                const replaced = replaceStreamingCommand(\n                    nodes,\n                    isReplaceable,\n                    (content, command) => {\n                        return replacers[command.content](content, command);\n                    }\n                );\n\n                // If we get back a different array than we input, the replacement did\n                // not happen in-place. In this case we need to manipulate `nodes`.\n                if (replaced !== nodes) {\n                    nodes.length = 0;\n                    nodes.push(...replaced);\n                }\n            },\n            { includeArrays: true, test: Array.isArray }\n        );\n    };\n};\n","export * from \"./libs/replace-node\";\nexport * from \"./libs/unified-latex-streaming-command\";\nexport * from \"./libs/replace-streaming-command\";\nexport * from \"./libs/replace-node-during-visit\";\nexport * from \"./libs/utils/significant-node\";\n\n// NOTE: The docstring comment must be the last item in the index.ts file!\n/**\n * ## What is this?\n *\n * Functions to help modify a `unified-latex` Abstract Syntax Tree (AST).\n *\n * ## When should I use this?\n *\n * If you want to recursively replace particular AST nodes.\n */\n"],"mappings":"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"}