docx/modify-set-run-bold

Open alignment-left.docx (plain, no bold), set font.bold = True on the first run, save. Assert the run now carries BOTH <w:b/> and <w:bCs/> (per the 2026.05.1 fix), the run's text and rsid attributes are preserved, and adjacent paragraph structure (paragraph-level w:jc alignment, paragraph's w14:paraId, w:sectPr) is intact. Note: python-docx's save-time _mirror_run_formatting_to_paragraph_mark deliberately copies w:b/w:bCs onto the paragraph mark's pPr/rPr so 'keep typing in bold' works in Word; this is documented behaviour and accommodated rather than flagged.

Library verdicts: python-docx: — docxjs: —

Metadata

Feature iddocx/modify-set-run-bold
Formatdocx
Categorymodify-in-place
Spececma-376-5-part-1 § 17.3.2.1 w:b

XPath assertions

ID / partPredicateXPathpython-docxdocxjs
run-has-w-b
word/document.xml
exist
The mutated run must carry <w:b/>.
//w:r[w:t[normalize-space()='Left aligned paragraph']]/w:rPr/w:b
run-has-w-bCs
word/document.xml
exist
The mutated run must also carry <w:bCs/> (2026.05.1 fix) — omitting it silently drops bold on complex-script runs when Word reopens the file.
//w:r[w:t[normalize-space()='Left aligned paragraph']]/w:rPr/w:bCs
run-bold-val-not-false
word/document.xml
not-match = ^(0|false|off)$
If w:val is present it must not disable bold.
//w:r[w:t[normalize-space()='Left aligned paragraph']]/w:rPr/w:b/@w:val
run-text-preserved
word/document.xml
exist
The run's text must be unchanged.
//w:r/w:t[normalize-space()='Left aligned paragraph']
run-rsid-preserved
word/document.xml
equal = 00000001
The run's w:rsidR attribute must be preserved — bold flip must not re-author adjacent attributes.
//w:r[w:t[normalize-space()='Left aligned paragraph']]/@w:rsidR
paragraph-alignment-preserved
word/document.xml
equal = left
The paragraph-level w:jc alignment — present as a SIBLING of the run we mutated — must be preserved.
//w:body/w:p[1]/w:pPr/w:jc/@w:val
paragraph-paraId-preserved
word/document.xml
equal = 81A65E80
w14:paraId on the paragraph must be byte-identical to the source.
//w:body/w:p[1]/@w14:paraId
run-count-unchanged
word/document.xml
match = ^1(\.0+)?$
Paragraph had 1 run before and must still have 1 run — bold flip must not split or duplicate runs.
count(//w:body/w:p[1]/w:r)
sectPr-pgSz-preserved
word/document.xml
equal = 12240
Section properties (distant adjacent element) must be untouched.
//w:body/w:sectPr/w:pgSz/@w:w

Render assertions

No render assertions declared.

Generator source

scripts/gen_modify_set_run_bold.py

#!/usr/bin/env python3
"""Generate ``fixtures/docx/alignment-left--set-run-bold.docx``.

Thin wrapper around ``scripts.mutations.docx_set_run_bold``. Opens
``fixtures/docx/alignment-left.docx``, flips the first run to bold,
saves. Satisfies ``features/docx/modify-set-run-bold.json``.
"""

from __future__ import annotations

from pathlib import Path

from mutations import docx_set_run_bold

_REPO_ROOT = Path(__file__).resolve().parent.parent
_IN = _REPO_ROOT / "fixtures" / "docx" / "alignment-left.docx"
_OUT = _REPO_ROOT / "fixtures" / "docx" / "alignment-left--set-run-bold.docx"


def main() -> int:
    docx_set_run_bold(_IN, _OUT)
    print(_OUT)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

Manifest (expanded)

{
  "$schema": "../manifest.schema.json",
  "id": "docx/modify-set-run-bold",
  "title": "Modify: flip first run's bold on an existing .docx",
  "format": "docx",
  "category": "modify-in-place",
  "summary": "Open alignment-left.docx (plain, no bold), set font.bold = True on the first run, save. Assert the run now carries BOTH <w:b/> and <w:bCs/> (per the 2026.05.1 fix), the run's text and rsid attributes are preserved, and adjacent paragraph structure (paragraph-level w:jc alignment, paragraph's w14:paraId, w:sectPr) is intact. Note: python-docx's save-time _mirror_run_formatting_to_paragraph_mark deliberately copies w:b/w:bCs onto the paragraph mark's pPr/rPr so 'keep typing in bold' works in Word; this is documented behaviour and accommodated rather than flagged.",
  "roles": [
    "authoring"
  ],
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "17.3.2.1",
    "element": "w:b",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/WordprocessingML.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/wml.xsd",
    "notes": "Word emits <w:b/> AND <w:bCs/> together on bold runs; omitting <w:bCs/> silently drops bold on Arabic/Hebrew/Thai when Word reopens. The 2026.05.1 python-docx fix couples these two setters."
  },
  "fixtures": {
    "machine": "docx/alignment-left--set-run-bold"
  },
  "modify": {
    "input_fixture": "fixtures/docx/alignment-left.docx",
    "mutation": "docx_set_run_bold",
    "output_fixture": "fixtures/docx/alignment-left--set-run-bold.docx"
  },
  "generator": {
    "python": "scripts/gen_modify_set_run_bold.py"
  },
  "assertions": [
    {
      "id": "run-has-w-b",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:r[w:t[normalize-space()='Left aligned paragraph']]/w:rPr/w:b",
      "must": "exist",
      "description": "The mutated run must carry <w:b/>."
    },
    {
      "id": "run-has-w-bCs",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:r[w:t[normalize-space()='Left aligned paragraph']]/w:rPr/w:bCs",
      "must": "exist",
      "description": "The mutated run must also carry <w:bCs/> (2026.05.1 fix) — omitting it silently drops bold on complex-script runs when Word reopens the file."
    },
    {
      "id": "run-bold-val-not-false",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:r[w:t[normalize-space()='Left aligned paragraph']]/w:rPr/w:b/@w:val",
      "must": "not-match",
      "value": "^(0|false|off)$",
      "description": "If w:val is present it must not disable bold."
    },
    {
      "id": "run-text-preserved",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:r/w:t[normalize-space()='Left aligned paragraph']",
      "must": "exist",
      "description": "The run's text must be unchanged."
    },
    {
      "id": "run-rsid-preserved",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:r[w:t[normalize-space()='Left aligned paragraph']]/@w:rsidR",
      "must": "equal",
      "value": "00000001",
      "description": "The run's w:rsidR attribute must be preserved — bold flip must not re-author adjacent attributes."
    },
    {
      "id": "paragraph-alignment-preserved",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:body/w:p[1]/w:pPr/w:jc/@w:val",
      "must": "equal",
      "value": "left",
      "description": "The paragraph-level w:jc alignment — present as a SIBLING of the run we mutated — must be preserved."
    },
    {
      "id": "paragraph-paraId-preserved",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
        "w14": "http://schemas.microsoft.com/office/word/2010/wordml"
      },
      "xpath": "//w:body/w:p[1]/@w14:paraId",
      "must": "equal",
      "value": "81A65E80",
      "description": "w14:paraId on the paragraph must be byte-identical to the source."
    },
    {
      "id": "run-count-unchanged",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "count(//w:body/w:p[1]/w:r)",
      "must": "match",
      "value": "^1(\\.0+)?$",
      "description": "Paragraph had 1 run before and must still have 1 run — bold flip must not split or duplicate runs."
    },
    {
      "id": "sectPr-pgSz-preserved",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:body/w:sectPr/w:pgSz/@w:w",
      "must": "equal",
      "value": "12240",
      "description": "Section properties (distant adjacent element) must be untouched."
    }
  ]
}

Fixture

Download alignment-left--set-run-bold.docx (18.6 KB)

Reference preview

No rendered reference is available for this case.

Spec notes

Word emits <w:b/> AND <w:bCs/> together on bold runs; omitting <w:bCs/> silently drops bold on Arabic/Hebrew/Thai when Word reopens. The 2026.05.1 python-docx fix couples these two setters.