Apply each of the five ST_Em emphasis-mark values (none, dot, comma, circle, underDot) to a run.
Library verdicts: python-docx: — docxjs: —
| Feature id | docx/font-emphasis-mark--dot |
|---|---|
| Format | docx |
| Category | text-formatting |
| Family | docx/font-emphasis-mark |
| Axis values | mark=dot |
| Spec | ecma-376-5-part-1 § 17.3.2.12 w:em |
| ID / part | Predicate | XPath | python-docx | docxjs |
|---|---|---|---|---|
em-element-present-dotword/document.xml | existThe run must carry a <w:em> child inside <w:rPr>. | //w:r[w:t[normalize-space()='Emphasized text']]/w:rPr/w:em | — | — |
em-val-is-dotword/document.xml | equal = dotThe w:em element must carry the expected ST_Em value. | //w:r[w:t[normalize-space()='Emphasized text']]/w:rPr/w:em/@w:val | — | — |
No render assertions declared.
scripts/gen_font_emphasis_mark.py
#!/usr/bin/env python3
"""Generate a ``fixtures/docx/font-emphasis-mark--<mark>.docx`` fixture.
Parameterised generator for the ``docx/font-emphasis-mark`` feature
family. One invocation writes a single fixture with a single run
carrying a ``<w:em w:val="..."/>`` on its ``<w:rPr>``. python-docx has
no high-level API for emphasis marks, so this generator reaches down
to :class:`docx.oxml.OxmlElement` to append the element directly.
Usage::
python scripts/gen_font_emphasis_mark.py \\
--mark underDot \\
--out fixtures/docx/font-emphasis-mark--underdot.docx
``--mark`` is one of the ST_Em enumerants: ``none``, ``dot``,
``comma``, ``circle``, ``underDot``.
"""
from __future__ import annotations
import argparse
from pathlib import Path
from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
_REPO_ROOT = Path(__file__).resolve().parent.parent
_VALID_MARKS = {"none", "dot", "comma", "circle", "underDot"}
def _write(mark: str, out: Path) -> None:
if mark not in _VALID_MARKS:
raise ValueError(
f"Unknown emphasis mark {mark!r}; expected one of {sorted(_VALID_MARKS)}"
)
doc = Document()
paragraph = doc.add_paragraph()
run = paragraph.add_run("Emphasized text")
rPr = run._r.get_or_add_rPr()
# Remove any pre-existing w:em to keep the element a singleton.
for existing in rPr.findall(qn("w:em")):
rPr.remove(existing)
em = OxmlElement("w:em")
em.set(qn("w:val"), mark)
rPr.append(em)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(out, reproducible=True)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"--mark",
required=True,
help=f"ST_Em value, one of {sorted(_VALID_MARKS)}.",
)
parser.add_argument(
"--out",
required=True,
help="Repo-relative or absolute output path for the .docx.",
)
args = parser.parse_args()
out_path = Path(args.out)
if not out_path.is_absolute():
out_path = _REPO_ROOT / out_path
_write(args.mark, out_path)
print(out_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())
{
"$schema": "../manifest.schema.json",
"id": "docx/font-emphasis-mark--dot",
"kind": "literal",
"title": "Font emphasis mark",
"format": "docx",
"category": "text-formatting",
"summary": "Apply each of the five ST_Em emphasis-mark values (none, dot, comma, circle, underDot) to a run.",
"spec": {
"source": "ecma-376-5-part-1",
"clause": "17.3.2.12",
"element": "w:em",
"rnc_reference": "spec/ecma-376-5/part-1/rnc/WordprocessingML.rnc",
"xsd_reference": "spec/ecma-376-5/part-1/xsd/wml.xsd",
"notes": "<w:em w:val=\"...\"/> on a run's rPr selects an emphasis mark, a small glyph drawn above each character (CJK convention, also used elsewhere). ST_Em enumerates 'none', 'dot', 'comma', 'circle', 'underDot'. python-docx has no high-level API for w:em, so this generator writes the element directly via OxmlElement."
},
"fixtures": {
"machine": "docx/font-emphasis-mark--dot"
},
"generator": {
"python": "scripts/gen_font_emphasis_mark.py",
"arg_template": "--mark {mark.val} --out fixtures/docx/font-emphasis-mark--{mark.id}.docx"
},
"_expansion": {
"parent_id": "docx/font-emphasis-mark",
"bindings": {
"mark": "dot"
}
},
"assertions": [
{
"id": "em-element-present-dot",
"part": "word/document.xml",
"namespaces": {
"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
},
"xpath": "//w:r[w:t[normalize-space()='Emphasized text']]/w:rPr/w:em",
"must": "exist",
"description": "The run must carry a <w:em> child inside <w:rPr>."
},
{
"id": "em-val-is-dot",
"part": "word/document.xml",
"namespaces": {
"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
},
"xpath": "//w:r[w:t[normalize-space()='Emphasized text']]/w:rPr/w:em/@w:val",
"must": "equal",
"value": "dot",
"description": "The w:em element must carry the expected ST_Em value."
}
]
}
