文件预览

omml.py

查看 word-latex-formula 技能包中的文件内容。

文件内容

resources/latex_convert_project/latex_convert/omml.py

from __future__ import annotations

from lxml import etree

from .math_parser import Delim, Frac, Node, Script, Seq, Text


M_NS = "http://schemas.openxmlformats.org/officeDocument/2006/math"
W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
XML_NS = "http://www.w3.org/XML/1998/namespace"


def m_tag(name: str) -> str:
    return f"{{{M_NS}}}{name}"


def w_tag(name: str) -> str:
    return f"{{{W_NS}}}{name}"


def node_to_omath(node: Node) -> etree._Element:
    omath = etree.Element(m_tag("oMath"))
    append_node(omath, node)
    return omath


def append_node(parent: etree._Element, node: Node) -> None:
    if isinstance(node, Seq):
        for item in node.items:
            append_node(parent, item)
        return
    if isinstance(node, Text):
        _append_math_text(parent, node.value)
        return
    if isinstance(node, Frac):
        f = etree.SubElement(parent, m_tag("f"))
        fpr = etree.SubElement(f, m_tag("fPr"))
        ftype = etree.SubElement(fpr, m_tag("type"))
        ftype.set(m_tag("val"), "bar")
        num = etree.SubElement(f, m_tag("num"))
        append_node(num, node.num)
        den = etree.SubElement(f, m_tag("den"))
        append_node(den, node.den)
        return
    if isinstance(node, Script):
        tag = "sSubSup" if node.sub is not None and node.sup is not None else "sSub" if node.sub is not None else "sSup"
        elem = etree.SubElement(parent, m_tag(tag))
        base = etree.SubElement(elem, m_tag("e"))
        append_node(base, node.base)
        if node.sub is not None:
            sub = etree.SubElement(elem, m_tag("sub"))
            append_node(sub, node.sub)
        if node.sup is not None:
            sup = etree.SubElement(elem, m_tag("sup"))
            append_node(sup, node.sup)
        return
    if isinstance(node, Delim):
        d = etree.SubElement(parent, m_tag("d"))
        dpr = etree.SubElement(d, m_tag("dPr"))
        beg = etree.SubElement(dpr, m_tag("begChr"))
        beg.set(m_tag("val"), node.begin)
        end = etree.SubElement(dpr, m_tag("endChr"))
        end.set(m_tag("val"), node.end)
        e = etree.SubElement(d, m_tag("e"))
        append_node(e, node.body)
        return
    raise TypeError(f"Unsupported math node: {node!r}")


def _append_math_text(parent: etree._Element, value: str) -> None:
    if not value:
        return
    r = etree.SubElement(parent, m_tag("r"))
    t = etree.SubElement(r, m_tag("t"))
    if value[:1].isspace() or value[-1:].isspace():
        t.set(f"{{{XML_NS}}}space", "preserve")
    t.text = value