pptx/bullet-numbered

A content placeholder carries three paragraphs, each bulleted as an auto-numbered arabic-period list item via <a:buAutoNum type="arabicPeriod"/>.

Library verdicts: python-pptx: — pptxjs: fail

Metadata

Feature idpptx/bullet-numbered
Formatpptx
Categoryslide-content
Spececma-376-5-part-1 § 21.1.2.4 a:buAutoNum

XPath assertions

ID / partPredicateXPathpython-pptxpptxjs
numbered-bullet-auto-num-exists
ppt/slides/slide1.xml
exist
At least one paragraph's <a:pPr> must carry <a:buAutoNum type="arabicPeriod"/>.
//a:pPr/a:buAutoNum[@type='arabicPeriod']
numbered-bullet-item-one
ppt/slides/slide1.xml
exist
A numbered paragraph must contain the text 'One'.
//a:p[a:pPr/a:buAutoNum[@type='arabicPeriod']]/a:r/a:t[normalize-space()='One']fail
numbered-bullet-item-two
ppt/slides/slide1.xml
exist
A numbered paragraph must contain the text 'Two'.
//a:p[a:pPr/a:buAutoNum[@type='arabicPeriod']]/a:r/a:t[normalize-space()='Two']fail
numbered-bullet-item-three
ppt/slides/slide1.xml
exist
A numbered paragraph must contain the text 'Three'.
//a:p[a:pPr/a:buAutoNum[@type='arabicPeriod']]/a:r/a:t[normalize-space()='Three']fail

Render assertions

IDPredicateSelectorpython-pptxpptxjs
numbered-bullet-three-itemscss_selector/ equal-count
Three numbered list-item DOM nodes must be rendered for the content placeholder.
ol li, [data-bullet-type='numbered']fail
numbered-bullet-item-onecss_selector/ match-text = One
First rendered list item must contain 'One'. Fallback text-match for renderers using non-list markup.
ol li, [data-bullet-type='numbered'], section[data-slide] p, section.slide pfail
numbered-bullet-item-twocss_selector/ match-text = Two
Second rendered list item must contain 'Two'.
ol li:nth-of-type(2), [data-bullet-type='numbered']:nth-of-type(2), section[data-slide] p:nth-of-type(2), section.slide p:nth-of-type(2)fail
numbered-bullet-item-threecss_selector/ match-text = Three
Third rendered list item must contain 'Three'.
ol li:nth-of-type(3), [data-bullet-type='numbered']:nth-of-type(3), section[data-slide] p:nth-of-type(3), section.slide p:nth-of-type(3)fail
slide-countcss_selector/ equal-count
Exactly one slide container must be rendered. Catches renderers that emit zero slides (hard failure) or duplicate the slide.
section.pptx-slide, .pptx-slide, section[data-slide], .slide, [data-slide]

Generator source

scripts/gen_bullet_numbered.py

#!/usr/bin/env python3
"""Generate ``fixtures/pptx/bullet-numbered.pptx``.

A one-slide presentation whose content placeholder carries three
paragraphs, each bulleted as an arabic-period auto-number via
<a:buAutoNum type="arabicPeriod"/>. python-pptx does not expose an API
for bullet auto-numbering, so the generator attaches the element
directly through lxml. Designed to satisfy the assertions in
``features/pptx/bullet-numbered.json``.
"""

from __future__ import annotations

from pathlib import Path

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

import datetime as _dt
_REPRODUCIBLE_DT = _dt.datetime(2000, 1, 1, 0, 0, 0)

_REPO_ROOT = Path(__file__).resolve().parent.parent
_OUT = _REPO_ROOT / "fixtures" / "pptx" / "bullet-numbered.pptx"


def main() -> int:
    prs = Presentation()
    slide = prs.slides.add_slide(prs.slide_layouts[1])
    slide.shapes.title.text = "Numbered list"
    body = slide.placeholders[1].text_frame
    body.text = "One"
    body.add_paragraph().text = "Two"
    body.add_paragraph().text = "Three"

    # Attach <a:buAutoNum type="arabicPeriod"/> to each paragraph's <a:pPr>.
    for p in body.paragraphs:
        pPr = p._pPr
        if pPr is None:
            pPr = etree.SubElement(p._p, qn("a:pPr"))
            p._p.insert(0, pPr)
        autoNum = etree.SubElement(pPr, qn("a:buAutoNum"))
        autoNum.set("type", "arabicPeriod")

    _OUT.parent.mkdir(parents=True, exist_ok=True)
    prs.save(_OUT, zip_date_time=_REPRODUCIBLE_DT)
    print(_OUT)
    return 0


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

Manifest (expanded)

{
  "$schema": "../manifest.schema.json",
  "id": "pptx/bullet-numbered",
  "title": "Numbered (auto-num) bullet list",
  "format": "pptx",
  "category": "slide-content",
  "summary": "A content placeholder carries three paragraphs, each bulleted as an auto-numbered arabic-period list item via <a:buAutoNum type=\"arabicPeriod\"/>.",
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "21.1.2.4",
    "element": "a:buAutoNum",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/DrawingML.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/dml-text.xsd",
    "notes": "python-pptx does not expose an API for setting bullet auto-numbering, so the generator attaches <a:buAutoNum type=\"arabicPeriod\"/> to each paragraph's <a:pPr> directly via lxml. The three paragraphs carry 'One', 'Two', 'Three'."
  },
  "fixtures": {
    "machine": "pptx/bullet-numbered",
    "office": "pptx/bullet-numbered"
  },
  "generator": {
    "python": "scripts/gen_bullet_numbered.py"
  },
  "assertions": [
    {
      "id": "numbered-bullet-auto-num-exists",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "p": "http://schemas.openxmlformats.org/presentationml/2006/main",
        "a": "http://schemas.openxmlformats.org/drawingml/2006/main"
      },
      "xpath": "//a:pPr/a:buAutoNum[@type='arabicPeriod']",
      "must": "exist",
      "description": "At least one paragraph's <a:pPr> must carry <a:buAutoNum type=\"arabicPeriod\"/>."
    },
    {
      "id": "numbered-bullet-item-one",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "p": "http://schemas.openxmlformats.org/presentationml/2006/main",
        "a": "http://schemas.openxmlformats.org/drawingml/2006/main"
      },
      "xpath": "//a:p[a:pPr/a:buAutoNum[@type='arabicPeriod']]/a:r/a:t[normalize-space()='One']",
      "must": "exist",
      "description": "A numbered paragraph must contain the text 'One'."
    },
    {
      "id": "numbered-bullet-item-two",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "p": "http://schemas.openxmlformats.org/presentationml/2006/main",
        "a": "http://schemas.openxmlformats.org/drawingml/2006/main"
      },
      "xpath": "//a:p[a:pPr/a:buAutoNum[@type='arabicPeriod']]/a:r/a:t[normalize-space()='Two']",
      "must": "exist",
      "description": "A numbered paragraph must contain the text 'Two'."
    },
    {
      "id": "numbered-bullet-item-three",
      "part": "ppt/slides/slide1.xml",
      "namespaces": {
        "p": "http://schemas.openxmlformats.org/presentationml/2006/main",
        "a": "http://schemas.openxmlformats.org/drawingml/2006/main"
      },
      "xpath": "//a:p[a:pPr/a:buAutoNum[@type='arabicPeriod']]/a:r/a:t[normalize-space()='Three']",
      "must": "exist",
      "description": "A numbered paragraph must contain the text 'Three'."
    }
  ],
  "render_assertions": [
    {
      "id": "numbered-bullet-three-items",
      "kind": "css_selector",
      "selector": "ol li, [data-bullet-type='numbered']",
      "must": "equal-count",
      "count": 3,
      "description": "Three numbered list-item DOM nodes must be rendered for the content placeholder."
    },
    {
      "id": "numbered-bullet-item-one",
      "kind": "css_selector",
      "selector": "ol li, [data-bullet-type='numbered'], section[data-slide] p, section.slide p",
      "must": "match-text",
      "value": "One",
      "description": "First rendered list item must contain 'One'. Fallback text-match for renderers using non-list markup."
    },
    {
      "id": "numbered-bullet-item-two",
      "kind": "css_selector",
      "selector": "ol li:nth-of-type(2), [data-bullet-type='numbered']:nth-of-type(2), section[data-slide] p:nth-of-type(2), section.slide p:nth-of-type(2)",
      "must": "match-text",
      "value": "Two",
      "description": "Second rendered list item must contain 'Two'."
    },
    {
      "id": "numbered-bullet-item-three",
      "kind": "css_selector",
      "selector": "ol li:nth-of-type(3), [data-bullet-type='numbered']:nth-of-type(3), section[data-slide] p:nth-of-type(3), section.slide p:nth-of-type(3)",
      "must": "match-text",
      "value": "Three",
      "description": "Third rendered list item must contain 'Three'."
    },
    {
      "id": "slide-count",
      "kind": "css_selector",
      "selector": "section.pptx-slide, .pptx-slide, section[data-slide], .slide, [data-slide]",
      "must": "equal-count",
      "count": 1,
      "description": "Exactly one slide container must be rendered. Catches renderers that emit zero slides (hard failure) or duplicate the slide."
    }
  ]
}

Fixture

Download bullet-numbered.pptx (27.5 KB)

Reference preview

Reference (machine, page 1 PNG)

pptx/bullet-numbered page 1 reference

Reference PDF


Download PDF Open in PDF.js

Spec notes

python-pptx does not expose an API for setting bullet auto-numbering, so the generator attaches <a:buAutoNum type="arabicPeriod"/> to each paragraph's <a:pPr> directly via lxml. The three paragraphs carry 'One', 'Two', 'Three'.