docx/text-direction--tbrlv

Section or table-cell <w:textDirection> carries the flow direction of text via @w:val (ST_TextDirection).

Library verdicts: python-docx: — docxjs: —

Metadata

Feature iddocx/text-direction--tbrlv
Formatdocx
Categorypage-layout
Familydocx/text-direction
Axis valuesdirection=tbrlv
Spececma-376-5-part-1 § 17.4.34 w:textDirection

XPath assertions

ID / partPredicateXPathpython-docxdocxjs
text-direction-tbrlv
word/document.xml
equal = tbRlV
w:textDirection@w:val on either the section or a table cell must equal 'tbRlV' for the tbrlv case.
//w:sectPr/w:textDirection/@w:val | //w:tcPr/w:textDirection/@w:val

Render assertions

No render assertions declared.

Generator source

scripts/gen_text_direction.py

#!/usr/bin/env python3
"""Generate ``fixtures/docx/text-direction*.docx`` fixtures.

Parameterised generator for the ``docx/text-direction`` family.
Emits a minimal document whose default section carries a
``<w:textDirection w:val="..."/>`` child inside ``<w:sectPr>`` with
the value supplied on the command line. The manifest expands this
into six concrete fixtures, one per ``ST_TextDirection`` enumerator
Word emits in the Transitional namespace (``lrTb``, ``tbRl``,
``btLr``, ``lrTbV``, ``tbRlV``, ``tbLrV``).

Note: the ECMA-376 Part 1 ``ST_TextDirection`` simple type
(clause 17.18.93) lists the Strict-style two-letter tokens ``tb``,
``rl``, ``lr``, ``tbV``, ``rlV``, ``lrV``. Word writes the longer
Transitional tokens (``lrTb`` etc.) and readers accept them; we
match Word.
"""

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_DIRECTIONS = {"lrTb", "tbRl", "btLr", "lrTbV", "tbRlV", "tbLrV"}


def _write(direction: str, out: Path) -> None:
    doc = Document()
    doc.add_paragraph("Text-direction test")

    section = doc.sections[-1]
    sectPr = section._sectPr
    # Remove any existing textDirection so we write a clean single child.
    existing = sectPr.find(qn("w:textDirection"))
    if existing is not None:
        sectPr.remove(existing)
    td = OxmlElement("w:textDirection")
    td.set(qn("w:val"), direction)
    sectPr.append(td)

    out.parent.mkdir(parents=True, exist_ok=True)
    doc.save(out, reproducible=True)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--direction",
        default="lrTb",
        help="ST_TextDirection enumerator (Transitional: lrTb, tbRl, btLr, lrTbV, tbRlV, tbLrV)",
    )
    parser.add_argument(
        "--out",
        default=str(_REPO_ROOT / "fixtures" / "docx" / "text-direction.docx"),
    )
    args = parser.parse_args()

    if args.direction not in _VALID_DIRECTIONS:
        raise SystemExit(
            f"Invalid --direction {args.direction!r}; expected one of "
            f"{sorted(_VALID_DIRECTIONS)}"
        )

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


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

Manifest (expanded)

{
  "$schema": "../manifest.schema.json",
  "id": "docx/text-direction--tbrlv",
  "kind": "literal",
  "title": "Text direction",
  "format": "docx",
  "category": "page-layout",
  "summary": "Section or table-cell <w:textDirection> carries the flow direction of text via @w:val (ST_TextDirection).",
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "17.4.34",
    "element": "w:textDirection",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/WordprocessingML.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/wml.xsd",
    "notes": "<w:textDirection w:val=\"...\"/> sets the flow direction of text within its containing element. It may appear inside <w:sectPr> (affecting a whole section) or inside <w:tcPr> (affecting a single table cell). The ECMA-376 ST_TextDirection simple type lists the Strict tokens 'tb', 'rl', 'lr', 'tbV', 'rlV', 'lrV'. Microsoft Word writes, and readers accept, the longer Transitional tokens: 'lrTb' (left-to-right, top-to-bottom — the default), 'tbRl' (top-to-bottom, right-to-left, e.g. vertical Japanese), 'btLr' (bottom-to-top, left-to-right), 'lrTbV' (left-to-right, top-to-bottom, vertical), 'tbRlV' (top-to-bottom, right-to-left, vertical) and 'tbLrV' (top-to-bottom, left-to-right, vertical). This manifest matches Word. It is a parameterised family: one manifest file expands into six concrete test cases, each targeting a distinct fixture docx/text-direction--<id>.docx produced from the same gen_text_direction.py script. For simplicity, the generator applies <w:textDirection> at section level (inside <w:sectPr>) rather than per table cell."
  },
  "fixtures": {
    "machine": "docx/text-direction--tbrlv"
  },
  "generator": {
    "python": "scripts/gen_text_direction.py",
    "arg_template": "--direction {direction.val} --out fixtures/docx/text-direction--{direction.id}.docx"
  },
  "_expansion": {
    "parent_id": "docx/text-direction",
    "bindings": {
      "direction": "tbrlv"
    }
  },
  "assertions": [
    {
      "id": "text-direction-tbrlv",
      "part": "word/document.xml",
      "namespaces": {
        "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
      },
      "xpath": "//w:sectPr/w:textDirection/@w:val | //w:tcPr/w:textDirection/@w:val",
      "must": "equal",
      "value": "tbRlV",
      "description": "w:textDirection@w:val on either the section or a table cell must equal 'tbRlV' for the tbrlv case."
    }
  ]
}

Fixture

Download text-direction--tbrlv.docx (18.6 KB)

Reference preview

Reference (machine, page 1 PNG)

docx/text-direction--tbrlv page 1 reference

Reference PDF


Download PDF Open in PDF.js

Spec notes

<w:textDirection w:val="..."/> sets the flow direction of text within its containing element. It may appear inside <w:sectPr> (affecting a whole section) or inside <w:tcPr> (affecting a single table cell). The ECMA-376 ST_TextDirection simple type lists the Strict tokens 'tb', 'rl', 'lr', 'tbV', 'rlV', 'lrV'. Microsoft Word writes, and readers accept, the longer Transitional tokens: 'lrTb' (left-to-right, top-to-bottom — the default), 'tbRl' (top-to-bottom, right-to-left, e.g. vertical Japanese), 'btLr' (bottom-to-top, left-to-right), 'lrTbV' (left-to-right, top-to-bottom, vertical), 'tbRlV' (top-to-bottom, right-to-left, vertical) and 'tbLrV' (top-to-bottom, left-to-right, vertical). This manifest matches Word. It is a parameterised family: one manifest file expands into six concrete test cases, each targeting a distinct fixture docx/text-direction--<id>.docx produced from the same gen_text_direction.py script. For simplicity, the generator applies <w:textDirection> at section level (inside <w:sectPr>) rather than per table cell.