import { Math as DocxMath, MathRun, MathFraction, MathRadical, MathSuperScript, MathSubScript, MathSubSuperScript } from "docx" type MathMLTag = | "MATH" // MathML集合 | "MI" // 标识符 | "MN" // 数字 | "MO" // 符号 | "MTEXT" // 一般文本(非数学内容) | "MS" // 字符串文本 | "MGLYPH" // 自定义图形符号 | "MROW" // 水平排列子表达式 | "MFRAC" // 分数 (numerator/denominator) | "MSUP" // 上标(如 x²) | "MSUB" // 下标(如 a₁) | "MSUBSUP" // 同时上标与下标 | "MSQRT" // 平方根 | "MROOT" // 带根指数的根式(如 ∛x) | string; // 支持未列出的标签 /** * docx支持的数学公式符合如下: * MathRun 文本 * MathFraction 分数 * - numerator 分子 * - denominator 分母 * MathSum 累加和 * - subScript 变量和初值(i=1) * - superScript 最大值(n) * MathRadical 根号 * - degree 次数 * MathSuperScript 上标 * - superScript 上标文本或指数 * MathSubScript 下标 * - subScript 下标文本 * MathSubSuperScript 上下标 * - superScript 上标文本 * - subScript 下标文本 * MathFunctions 函数 * - name 函数名 * MathSquareBrackets 方括号[] * MathRoundBrackets 圆括号() * MathCurlyBrackets 花括号{} * MathAngledBrackets 尖括号<> * MathLimitUpper 上限(效果未知) * - limit * MathLimitLower 下限(效果未知) * - limit **/ interface ParsedMathMLNode { tag: MathMLTag; text: string | undefined; children: ParsedMathMLNode[]; } function convertMathMLElement(node: Element): ParsedMathMLNode { const tag = node.tagName; // 如 'MFRAC', 'MI' const children = Array.from(node.children).map(convertMathMLElement); const text = node.textContent?.trim(); return { tag, text, children }; } function convertMathMLNode(node: ParsedMathMLNode) { switch (node.tag) { case "MATH": return new DocxMath({ children: Array.from(node.children).map(convertMathMLNode), }); case "MSUP": return new MathSuperScript({ children: [convertMathMLNode(node.children[0])], superScript: convertMathMLNode(node.children[1]), }); case "MSUB": return new MathSubScript({ children: [convertMathMLNode(node.children[0])], subScript: convertMathMLNode(node.children[1]), }); case "MSUBSUP": return new MathSubSuperScript({ children: [convertMathMLNode(node.children[0])], subScript: convertMathMLNode(node.children[1]), superScript: convertMathMLNode(node.children[2]), }); case "MFRAC": return new MathFraction({ numerator: convertMathMLNode(node.children[0]), denominator: convertMathMLNode(node.children[1]), }); case "MSQRT": return new MathRadical({ children: [convertMathMLNode(node.children[0])], }); case "MROOT": return new MathRadical({ children: [convertMathMLNode(node.children[0])], degree: [convertMathMLNode(node.children[1])] }); case "MI": case "MN": case "MO": case "MTEXT": case "MS": case "MGLYPH": return new MathRun(node.text ?? ""); case "MROW": return Array.from(node.children).map(convertMathMLNode); default: console.warn("Unsupported MathML tag:", node.tag); return new MathRun(`[${node.tag}]`); } } const handleMath = (el: Element): DocxMath | undefined => { const tag = el.tagName.toLowerCase() // 段落处理 if (tag === "math") { const mathMlNode = convertMathMLElement(el) return convertMathMLNode(mathMlNode) } } export default { handleMath, config: {} // 无配置 }