docx/run-strike-variants

Matrix over the two OOXML strikethrough variants (w:strike single line, w:dstrike double line) x the two conventional enabled states (empty element, explicit w:val="true").

Cases (4)

Feature IDAxis bindingspython-docxdocxjs
docx/run-strike-variants--double--enabledkind=double, state=enabled
docx/run-strike-variants--double--explicit-truekind=double, state=explicit-true
docx/run-strike-variants--single--enabledkind=single, state=enabled
docx/run-strike-variants--single--explicit-truekind=single, state=explicit-true

Aggregate

LibraryPassFailPending
python-docx004
docxjs004

Parameter axes

Spec notes

Two mutually-exclusive strikethrough elements live in the OOXML run-properties schema: <w:strike> (clause 17.3.2.37) draws a single line, <w:dstrike> (clause 17.3.2.9) draws two parallel lines. Both are CT_OnOff toggles: an empty element means true; w:val="true"/"1"/"on" are equivalent explicit-true spellings; w:val="false"/"0"/"off" explicitly disables. This parameterised family walks the kind axis (single vs double) against the state axis (empty / explicit-true), producing 4 cases that confirm both variants accept both conventional enabled spellings. The existing literal manifests docx/strikethrough-text and docx/double-strikethrough cover the empty-element default shape only; this family adds the explicit-true dimension and keeps the two kinds in a single matrix.

Generator source

scripts/gen_run_strike_variants.py — runs with --arg_template --kind {kind.id} --state {state.id} --out fixtures/docx/run-strike-variants--{kind.id}--{state.id}.docx

#!/usr/bin/env python3
"""Generate a ``fixtures/docx/run-strike-variants--*.docx`` fixture.

Parameterised: called with ``--kind single|double --state enabled|explicit-true --out <path>``.
Writes a one-run document containing the text ``Striked text`` with
either a ``<w:strike>`` (kind=single) or ``<w:dstrike>`` (kind=double)
child inside the run's ``<w:rPr>``. The state axis controls whether the
element is emitted as an empty toggle (``state=enabled``) or with an
explicit ``w:val="true"`` attribute (``state=explicit-true``).

The ``features/docx/run-strike-variants.json`` manifest's
``generator.arg_template`` field drives these args at expansion time;
the Cartesian product of 2 kinds x 2 states yields 4 fixtures.
"""

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


def _write(kind: str, state: str, out: Path) -> None:
    doc = Document()
    paragraph = doc.add_paragraph()
    run = paragraph.add_run("Striked text")
    rPr = run._r.get_or_add_rPr()
    if kind == "single":
        tag = "w:strike"
    elif kind == "double":
        tag = "w:dstrike"
    else:
        raise ValueError(f"unknown kind {kind!r}; expected 'single' or 'double'")
    el = OxmlElement(tag)
    if state == "explicit-true":
        el.set(qn("w:val"), "true")
    elif state != "enabled":
        raise ValueError(
            f"unknown state {state!r}; expected 'enabled' or 'explicit-true'"
        )
    rPr.append(el)
    out.parent.mkdir(parents=True, exist_ok=True)
    doc.save(out, reproducible=True)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--kind",
        choices=("single", "double"),
        required=True,
        help="'single' -> <w:strike>, 'double' -> <w:dstrike>",
    )
    parser.add_argument(
        "--state",
        choices=("enabled", "explicit-true"),
        required=True,
        help="'enabled' -> empty element (implicit true); "
        "'explicit-true' -> w:val=\"true\"",
    )
    parser.add_argument(
        "--out",
        required=True,
        help="Output .docx path (absolute, or repo-relative).",
    )
    args = parser.parse_args()

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


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

Manifest (parent, unexpanded)

{
  "$schema": "../manifest.schema.json",
  "id": "docx/run-strike-variants",
  "kind": "parameterised",
  "title": "Run strike variants (single vs double, enabled states)",
  "format": "docx",
  "category": "text-formatting",
  "summary": "Matrix over the two OOXML strikethrough variants (w:strike single line, w:dstrike double line) x the two conventional enabled states (empty element, explicit w:val=\"true\").",
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "17.3.2.37",
    "element": "w:strike",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/WordprocessingML.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/wml.xsd",
    "notes": "Two mutually-exclusive strikethrough elements live in the OOXML run-properties schema: <w:strike> (clause 17.3.2.37) draws a single line, <w:dstrike> (clause 17.3.2.9) draws two parallel lines. Both are CT_OnOff toggles: an empty element means true; w:val=\"true\"/\"1\"/\"on\" are equivalent explicit-true spellings; w:val=\"false\"/\"0\"/\"off\" explicitly disables. This parameterised family walks the kind axis (single vs double) against the state axis (empty / explicit-true), producing 4 cases that confirm both variants accept both conventional enabled spellings. The existing literal manifests docx/strikethrough-text and docx/double-strikethrough cover the empty-element default shape only; this family adds the explicit-true dimension and keeps the two kinds in a single matrix."
  },
  "fixtures": {
    "machine": "docx/run-strike-variants"
  },
  "generator": {
    "python": "scripts/gen_run_strike_variants.py",
    "arg_template": "--kind {kind.id} --state {state.id} --out fixtures/docx/run-strike-variants--{kind.id}--{state.id}.docx"
  },
  "parameters": {
    "kind": [
      {
        "id": "single",
        "element": "w:strike"
      },
      {
        "id": "double",
        "element": "w:dstrike"
      }
    ],
    "state": [
      {
        "id": "enabled",
        "val_attr": "",
        "expected_present": true
      },
      {
        "id": "explicit-true",
        "val_attr": "true",
        "expected_present": true
      }
    ]
  },
  "assertions_template": [
    {
      "id": "{kind.id}-strike-present-{state.id}",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:r[w:t[normalize-space()='Striked text']]/w:rPr/{kind.element}",
      "must": "exist",
      "description": "The run must carry a <{kind.element}> child inside <w:rPr> for state '{state.id}'."
    }
  ]
}