pptx/transition-timing

The <p:transition> element carries timing attributes alongside its effect child: @advClick (auto-advance vs. click-advance), @advTm (delay before auto-advance in ms), and the PowerPoint 2010+ @p14:dur extension attribute (transition animation duration in ms). This family covers three configurations — fast transition (p14:dur=250ms), slow transition (p14:dur=2000ms), and auto-advance (advClick=0 with advTm=5000ms) — each backed by a distinct fixture pptx/transition-timing--<id>.pptx generated from the same gen_transition_timing.py script parameterised by --dur, --adv-click, and --adv-tm.

Cases (3)

Feature IDAxis bindingspython-pptxpptxjs
pptx/transition-timing--auto-advancetiming=auto-advance
pptx/transition-timing--fast-transitiontiming=fast-transition
pptx/transition-timing--slow-transitiontiming=slow-transition

Aggregate

LibraryPassFailPending
python-pptx003
pptxjs003

Parameter axes

Spec notes

ECMA-376 Part 1 clause 19.5.70 defines <p:transition> with attributes @spd (fast|med|slow), @advClick (xsd:boolean, default true), and @advTm (xsd:unsignedInt, delay in ms before auto-advance). The @p14:dur attribute (animation duration in ms) is a PowerPoint 2010+ extension in the http://schemas.microsoft.com/office/powerpoint/2010/main namespace, gated in Office-authored files by a mc:Ignorable='p14' declaration on the sld root. This family axis differs from pptx/slide-transition (which exercises the choice-child effect token): here the effect child is fixed (p:fade) and the varying dimension is the timing attributes carried on <p:transition> itself. python-pptx exposes no high-level transition API, so the generator sets these attributes via lxml.

Generator source

scripts/gen_transition_timing.py — runs with --arg_template --dur {timing.dur} --adv-click {timing.advClick} --adv-tm {timing.advTm} --out fixtures/pptx/transition-timing--{timing.id}.pptx

#!/usr/bin/env python3
"""Generate a single ``fixtures/pptx/transition-timing--<id>.pptx``.

Parameterised generator for the ``pptx/transition-timing`` manifest
family. Each case produces a single-slide presentation whose
``<p:transition>`` carries one ``<p:fade/>`` effect child (a fixed
axis — this family tests timing, not effect choice) and the three
timing attributes:

- ``p14:dur`` — PowerPoint 2010+ extension attribute, animation
  duration in milliseconds.
- ``advClick`` — xsd:boolean, whether the slide advances on mouse
  click (default true).
- ``advTm`` — xsd:unsignedInt, delay in milliseconds before the slide
  auto-advances (only meaningful with advClick=0).

python-pptx exposes no high-level transition API, so ``<p:transition>``
is appended directly via lxml with the p14 namespace decl emitted so
``@p14:dur`` serialises cleanly.
"""

from __future__ import annotations

import argparse
import datetime as _dt
from pathlib import Path

from lxml import etree
from pptx import Presentation
from pptx.oxml.ns import qn

_REPO_ROOT = Path(__file__).resolve().parent.parent
_REPRODUCIBLE_DT = _dt.datetime(2000, 1, 1, 0, 0, 0)

_P14_NS = "http://schemas.microsoft.com/office/powerpoint/2010/main"


def _write(dur: str, adv_click: str, adv_tm: str, out: Path) -> None:
    prs = Presentation()
    # "Title Only" layout — a title placeholder on an otherwise plain slide.
    slide = prs.slides.add_slide(prs.slide_layouts[5])
    if slide.shapes.title is not None:
        slide.shapes.title.text = "Transition timing"

    # Append <p:transition p14:dur="..." advClick="..." [advTm="..."]>
    #          <p:fade/>
    #        </p:transition>
    # to <p:sld>. Schema order is (cSld, clrMapOvr, transition, timing,
    # extLst); with no timing/extLst present, appending at end is valid.
    sld = slide._element
    transition = etree.SubElement(
        sld,
        qn("p:transition"),
        nsmap={"p14": _P14_NS},
    )
    transition.set("advClick", adv_click)
    if adv_tm:
        transition.set("advTm", adv_tm)
    transition.set(f"{{{_P14_NS}}}dur", dur)
    etree.SubElement(transition, qn("p:fade"))

    out.parent.mkdir(parents=True, exist_ok=True)
    prs.save(out, zip_date_time=_REPRODUCIBLE_DT)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--dur",
        required=True,
        help="@p14:dur attribute value (ms).",
    )
    parser.add_argument(
        "--adv-click",
        required=True,
        help="@advClick attribute value ('0' or '1').",
    )
    parser.add_argument(
        "--adv-tm",
        default="",
        help="@advTm attribute value (ms); empty to omit.",
    )
    parser.add_argument(
        "--out",
        required=True,
        help="Output fixture 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.dur, args.adv_click, args.adv_tm, out_path)
    print(out_path)
    return 0


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

Manifest (parent, unexpanded)

{
  "$schema": "../manifest.schema.json",
  "id": "pptx/transition-timing",
  "kind": "parameterised",
  "title": "Slide transition timing attributes",
  "format": "pptx",
  "category": "slide-content",
  "summary": "The <p:transition> element carries timing attributes alongside its effect child: @advClick (auto-advance vs. click-advance), @advTm (delay before auto-advance in ms), and the PowerPoint 2010+ @p14:dur extension attribute (transition animation duration in ms). This family covers three configurations — fast transition (p14:dur=250ms), slow transition (p14:dur=2000ms), and auto-advance (advClick=0 with advTm=5000ms) — each backed by a distinct fixture pptx/transition-timing--<id>.pptx generated from the same gen_transition_timing.py script parameterised by --dur, --adv-click, and --adv-tm.",
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "19.5.70",
    "element": "p:transition",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/pml.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/pml.xsd",
    "notes": "ECMA-376 Part 1 clause 19.5.70 defines <p:transition> with attributes @spd (fast|med|slow), @advClick (xsd:boolean, default true), and @advTm (xsd:unsignedInt, delay in ms before auto-advance). The @p14:dur attribute (animation duration in ms) is a PowerPoint 2010+ extension in the http://schemas.microsoft.com/office/powerpoint/2010/main namespace, gated in Office-authored files by a mc:Ignorable='p14' declaration on the sld root. This family axis differs from pptx/slide-transition (which exercises the choice-child effect token): here the effect child is fixed (p:fade) and the varying dimension is the timing attributes carried on <p:transition> itself. python-pptx exposes no high-level transition API, so the generator sets these attributes via lxml."
  },
  "fixtures": {
    "machine": "pptx/transition-timing"
  },
  "generator": {
    "python": "scripts/gen_transition_timing.py",
    "arg_template": "--dur {timing.dur} --adv-click {timing.advClick} --adv-tm {timing.advTm} --out fixtures/pptx/transition-timing--{timing.id}.pptx"
  },
  "parameters": {
    "timing": [
      {
        "id": "fast-transition",
        "dur": "250",
        "advClick": "1",
        "advTm": "",
        "attr_xpath": "//p:transition/@p14:dur",
        "attr_value": "250",
        "advclick_xpath": "string(//p:transition/@advClick)",
        "advclick_must": "match",
        "advclick_value": "^(1|true|)$"
      },
      {
        "id": "slow-transition",
        "dur": "2000",
        "advClick": "1",
        "advTm": "",
        "attr_xpath": "//p:transition/@p14:dur",
        "attr_value": "2000",
        "advclick_xpath": "string(//p:transition/@advClick)",
        "advclick_must": "match",
        "advclick_value": "^(1|true|)$"
      },
      {
        "id": "auto-advance",
        "dur": "1000",
        "advClick": "0",
        "advTm": "5000",
        "attr_xpath": "//p:transition/@p14:dur",
        "attr_value": "1000",
        "advclick_xpath": "string(//p:transition/@advClick)",
        "advclick_must": "equal",
        "advclick_value": "0"
      }
    ]
  },
  "assertions_template": [
    {
      "id": "transition-present-{timing.id}",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "p": "http://schemas.openxmlformats.org/presentationml/2006/main"
      },
      "xpath": "count(//p:transition)",
      "must": "match",
      "value": "^1(\\.0)?$",
      "description": "Slide must carry exactly one <p:transition> element."
    },
    {
      "id": "transition-effect-child-{timing.id}",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "p": "http://schemas.openxmlformats.org/presentationml/2006/main"
      },
      "xpath": "local-name(//p:transition/*[1])",
      "must": "equal",
      "value": "fade",
      "description": "The <p:transition> for all timing cases carries a single <p:fade/> effect child; this family tests timing attributes, not effect choice."
    },
    {
      "id": "transition-p14-dur-{timing.id}",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "p": "http://schemas.openxmlformats.org/presentationml/2006/main",
        "p14": "http://schemas.microsoft.com/office/powerpoint/2010/main"
      },
      "xpath": "{timing.attr_xpath}",
      "must": "equal",
      "value": "{timing.attr_value}",
      "description": "The @p14:dur attribute on <p:transition> must equal {timing.attr_value} (milliseconds)."
    },
    {
      "id": "transition-adv-click-{timing.id}",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "p": "http://schemas.openxmlformats.org/presentationml/2006/main"
      },
      "xpath": "{timing.advclick_xpath}",
      "must": "{timing.advclick_must}",
      "value": "{timing.advclick_value}",
      "description": "The @advClick attribute on <p:transition> must reflect the case axis (click-advance vs auto-advance)."
    }
  ]
}