docx/font-color--orange

Set a run's foreground color to a specific RGB hex value.

Library verdicts: python-docx: — docxjs: pass

Metadata

Feature iddocx/font-color--orange
Formatdocx
Categorytext-formatting
Familydocx/font-color
Axis valuescolor=orange
Spececma-376-5-part-1 § 17.3.2.6 w:color

XPath assertions

ID / partPredicateXPathpython-docxdocxjs
color-element-present-orange
word/document.xml
exist
The run must have a <w:color> child carrying the foreground color.
//w:r[w:t[normalize-space()='Orange text']]/w:rPr/w:color
color-val-is-orange
word/document.xml
match = ^FF7F00$
Foreground color must be RGB #FF7F00 (6 uppercase hex digits).
//w:r[w:t[normalize-space()='Orange text']]/w:rPr/w:color/@w:val

Render assertions

IDPredicateSelectorpython-docxdocxjs
font-color-orange-text-presentcss_selector/ match-text = Orange text
The rendered DOM must contain the fixture text.
.docx-wrapper span, .docx-wrapper ppass
font-color-orange-is-correctcomputed_style = ^(rgb\(255,\s*127,\s*0\)|#ff7f00|#FF7F00)$ style=color
The computed foreground color on the coloured run must resolve to the expected RGB.
.docx-wrapper span:not(:has(*))pass

Generator source

scripts/gen_font_color.py

#!/usr/bin/env python3
"""Generate a ``fixtures/docx/font-color*.docx`` fixture.

Supports two modes:

- **Literal (legacy):** no arguments — writes
  ``fixtures/docx/font-color.docx`` with the hard-coded "Red text" +
  ``#FF0000`` shape. Retained so the pre-parameterised manifest form
  still works for anyone who pins this file directly.

- **Parameterised:** called with ``--color-rgb <RRGGBB> --text
  <text> --out <path>``. Writes the fixture to the given path with
  the specified colour and text. The ``features/docx/font-color.json``
  manifest's ``generator.arg_template`` field drives these args at
  expansion time.
"""

from __future__ import annotations

import argparse
from pathlib import Path

from docx import Document
from docx.shared import RGBColor

_REPO_ROOT = Path(__file__).resolve().parent.parent


def _hex_to_rgb(hex_value: str) -> RGBColor:
    if len(hex_value) != 6:
        raise ValueError(f"Expected 6-digit hex RRGGBB, got {hex_value!r}")
    r = int(hex_value[0:2], 16)
    g = int(hex_value[2:4], 16)
    b = int(hex_value[4:6], 16)
    return RGBColor(r, g, b)


def _write(text: str, color_rgb: str, out: Path) -> None:
    doc = Document()
    paragraph = doc.add_paragraph()
    run = paragraph.add_run(text)
    run.font.color.rgb = _hex_to_rgb(color_rgb)
    out.parent.mkdir(parents=True, exist_ok=True)
    doc.save(out, reproducible=True)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--color-rgb", default="FF0000", help="6-digit uppercase hex")
    parser.add_argument("--text", default="Red text")
    parser.add_argument(
        "--out",
        default=str(_REPO_ROOT / "fixtures" / "docx" / "font-color.docx"),
    )
    args = parser.parse_args()

    out_path = Path(args.out)
    if not out_path.is_absolute():
        out_path = _REPO_ROOT / out_path
    _write(args.text, args.color_rgb, out_path)
    print(out_path)
    return 0


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

Manifest (expanded)

{
  "$schema": "../manifest.schema.json",
  "id": "docx/font-color--orange",
  "kind": "literal",
  "title": "Font color",
  "format": "docx",
  "category": "text-formatting",
  "summary": "Set a run's foreground color to a specific RGB hex value.",
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "17.3.2.6",
    "element": "w:color",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/WordprocessingML.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/wml.xsd",
    "notes": "<w:color w:val=\"RRGGBB\"/> sets the foreground color. The value is 6 uppercase hex digits OR the literal 'auto'. This manifest is a parameterised family: one manifest file expands into ten concrete colour test cases (FF0000 through 7F00FF) at runtime. Each expanded case targets a distinct fixture `docx/font-color--<id>.docx` generated from the same gen_font_color.py script parameterised by CLI args."
  },
  "fixtures": {
    "machine": "docx/font-color--orange",
    "office": "docx/font-color--orange"
  },
  "generator": {
    "python": "scripts/gen_font_color.py",
    "arg_template": "--color-rgb {color.rgb} --text \"{color.text}\" --out fixtures/docx/font-color--{color.id}.docx"
  },
  "_expansion": {
    "parent_id": "docx/font-color",
    "bindings": {
      "color": "orange"
    }
  },
  "assertions": [
    {
      "id": "color-element-present-orange",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:r[w:t[normalize-space()='Orange text']]/w:rPr/w:color",
      "must": "exist",
      "description": "The run must have a <w:color> child carrying the foreground color."
    },
    {
      "id": "color-val-is-orange",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:r[w:t[normalize-space()='Orange text']]/w:rPr/w:color/@w:val",
      "must": "match",
      "value": "^FF7F00$",
      "description": "Foreground color must be RGB #FF7F00 (6 uppercase hex digits)."
    }
  ],
  "render_assertions": [
    {
      "id": "font-color-orange-text-present",
      "kind": "css_selector",
      "selector": ".docx-wrapper span, .docx-wrapper p",
      "must": "match-text",
      "value": "Orange text",
      "description": "The rendered DOM must contain the fixture text."
    },
    {
      "id": "font-color-orange-is-correct",
      "kind": "computed_style",
      "selector": ".docx-wrapper span:not(:has(*))",
      "style_property": "color",
      "value": "^(rgb\\(255,\\s*127,\\s*0\\)|#ff7f00|#FF7F00)$",
      "description": "The computed foreground color on the coloured run must resolve to the expected RGB."
    }
  ]
}

Fixture

Download font-color--orange.docx (18.6 KB)

Reference preview

Reference (machine, page 1 PNG)

docx/font-color--orange page 1 reference

Reference PDF


Download PDF Open in PDF.js

Spec notes

<w:color w:val="RRGGBB"/> sets the foreground color. The value is 6 uppercase hex digits OR the literal 'auto'. This manifest is a parameterised family: one manifest file expands into ten concrete colour test cases (FF0000 through 7F00FF) at runtime. Each expanded case targets a distinct fixture `docx/font-color--<id>.docx` generated from the same gen_font_color.py script parameterised by CLI args.