Every PresentationML package carries at least one theme part (ppt/theme/theme1.xml) whose <a:clrScheme> child defines the twelve standard colour slots (dk1, lt1, dk2, lt2, accent1..accent6, hlink, folHlink). These slots are referenced by <a:schemeClr val="..."/> throughout the package wherever a shape, run, or background fill inherits its colour from the theme. python-pptx's default Presentation() template ships the Office 2007 'Office' theme, which populates all twelve slots.
Library verdicts: python-pptx: — pptxjs: —
| Feature id | pptx/theme-color-scheme |
|---|---|
| Format | pptx |
| Category | theme |
| Spec | ecma-376-5-part-1 § 20.1.6.2 a:clrScheme |
| ID / part | Predicate | XPath | python-pptx | pptxjs |
|---|---|---|---|---|
clr-scheme-presentppt/theme/theme1.xml | match = ^1(\.0)?$The theme must carry exactly one <a:clrScheme> element. | count(//a:clrScheme) | — | — |
clr-scheme-name-nonemptyppt/theme/theme1.xml | match = ^.+$<a:clrScheme> must carry a non-empty @name attribute. | string(//a:clrScheme/@name) | — | — |
clr-scheme-has-twelve-slotsppt/theme/theme1.xml | match = ^12(\.0)?$<a:clrScheme> must carry exactly twelve colour-slot children (dk1, lt1, dk2, lt2, accent1..6, hlink, folHlink). | count(//a:clrScheme/*) | — | — |
clr-scheme-slot-dk1ppt/theme/theme1.xml | existThe dk1 (dark 1) colour slot must be present. | //a:clrScheme/a:dk1 | — | — |
clr-scheme-slot-lt1ppt/theme/theme1.xml | existThe lt1 (light 1) colour slot must be present. | //a:clrScheme/a:lt1 | — | — |
clr-scheme-slot-dk2ppt/theme/theme1.xml | existThe dk2 (dark 2) colour slot must be present. | //a:clrScheme/a:dk2 | — | — |
clr-scheme-slot-lt2ppt/theme/theme1.xml | existThe lt2 (light 2) colour slot must be present. | //a:clrScheme/a:lt2 | — | — |
clr-scheme-slot-accent1ppt/theme/theme1.xml | existThe accent1 colour slot must be present. | //a:clrScheme/a:accent1 | — | — |
clr-scheme-slot-accent2ppt/theme/theme1.xml | existThe accent2 colour slot must be present. | //a:clrScheme/a:accent2 | — | — |
clr-scheme-slot-accent3ppt/theme/theme1.xml | existThe accent3 colour slot must be present. | //a:clrScheme/a:accent3 | — | — |
clr-scheme-slot-accent4ppt/theme/theme1.xml | existThe accent4 colour slot must be present. | //a:clrScheme/a:accent4 | — | — |
clr-scheme-slot-accent5ppt/theme/theme1.xml | existThe accent5 colour slot must be present. | //a:clrScheme/a:accent5 | — | — |
clr-scheme-slot-accent6ppt/theme/theme1.xml | existThe accent6 colour slot must be present. | //a:clrScheme/a:accent6 | — | — |
clr-scheme-slot-hlinkppt/theme/theme1.xml | existThe hlink (hyperlink) colour slot must be present. | //a:clrScheme/a:hlink | — | — |
clr-scheme-slot-folHlinkppt/theme/theme1.xml | existThe folHlink (followed hyperlink) colour slot must be present. | //a:clrScheme/a:folHlink | — | — |
No render assertions declared.
scripts/gen_theme_color_scheme.py
#!/usr/bin/env python3
"""Generate ``fixtures/pptx/theme-color-scheme.pptx``.
Literal (single-case) fixture that exercises the default Office theme
shipped by python-pptx. The generator does nothing exotic: it creates
a fresh ``Presentation()`` (which includes the bundled ``ppt/theme/
theme1.xml`` with the Office 2007 colour scheme) and adds a single
title-only slide so the rendered reference has a text anchor.
The ``features/pptx/theme-color-scheme.json`` manifest asserts that
the theme part carries exactly one ``<a:clrScheme>`` with twelve
colour-slot children (dk1, lt1, dk2, lt2, accent1..6, hlink,
folHlink) and a non-empty ``@name``.
"""
from __future__ import annotations
import argparse
import datetime as _dt
from pathlib import Path
from pptx import Presentation
_REPO_ROOT = Path(__file__).resolve().parent.parent
_REPRODUCIBLE_DT = _dt.datetime(2000, 1, 1, 0, 0, 0)
def _write(out: Path) -> None:
prs = Presentation()
# "Title Only" layout — one 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 = "Default Office theme"
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(
"--out",
default=str(_REPO_ROOT / "fixtures" / "pptx" / "theme-color-scheme.pptx"),
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(out_path)
print(out_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())
{
"$schema": "../manifest.schema.json",
"id": "pptx/theme-color-scheme",
"kind": "literal",
"title": "Theme colour scheme",
"format": "pptx",
"category": "theme",
"summary": "Every PresentationML package carries at least one theme part (ppt/theme/theme1.xml) whose <a:clrScheme> child defines the twelve standard colour slots (dk1, lt1, dk2, lt2, accent1..accent6, hlink, folHlink). These slots are referenced by <a:schemeClr val=\"...\"/> throughout the package wherever a shape, run, or background fill inherits its colour from the theme. python-pptx's default Presentation() template ships the Office 2007 'Office' theme, which populates all twelve slots.",
"spec": {
"source": "ecma-376-5-part-1",
"clause": "20.1.6.2",
"element": "a:clrScheme",
"rnc_reference": "spec/ecma-376-5/part-1/rnc/dml-main.rnc",
"xsd_reference": "spec/ecma-376-5/part-1/xsd/dml-main.xsd",
"notes": "ECMA-376 Part 1 clause 20.1.6 defines <a:clrScheme> as the colour-scheme element of the theme. Its content model is fixed: exactly twelve children in the order dk1, lt1, dk2, lt2, accent1..accent6, hlink, folHlink, each wrapping a single colour choice (srgbClr, sysClr, schemeClr, etc.). This family asserts the twelve slots exist on the default Office theme shipped by python-pptx and that <a:clrScheme> carries a non-empty @name attribute."
},
"fixtures": {
"machine": "pptx/theme-color-scheme"
},
"generator": {
"python": "scripts/gen_theme_color_scheme.py"
},
"assertions": [
{
"id": "clr-scheme-present",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "count(//a:clrScheme)",
"must": "match",
"value": "^1(\\.0)?$",
"description": "The theme must carry exactly one <a:clrScheme> element."
},
{
"id": "clr-scheme-name-nonempty",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "string(//a:clrScheme/@name)",
"must": "match",
"value": "^.+$",
"description": "<a:clrScheme> must carry a non-empty @name attribute."
},
{
"id": "clr-scheme-has-twelve-slots",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "count(//a:clrScheme/*)",
"must": "match",
"value": "^12(\\.0)?$",
"description": "<a:clrScheme> must carry exactly twelve colour-slot children (dk1, lt1, dk2, lt2, accent1..6, hlink, folHlink)."
},
{
"id": "clr-scheme-slot-dk1",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:dk1",
"must": "exist",
"description": "The dk1 (dark 1) colour slot must be present."
},
{
"id": "clr-scheme-slot-lt1",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:lt1",
"must": "exist",
"description": "The lt1 (light 1) colour slot must be present."
},
{
"id": "clr-scheme-slot-dk2",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:dk2",
"must": "exist",
"description": "The dk2 (dark 2) colour slot must be present."
},
{
"id": "clr-scheme-slot-lt2",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:lt2",
"must": "exist",
"description": "The lt2 (light 2) colour slot must be present."
},
{
"id": "clr-scheme-slot-accent1",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:accent1",
"must": "exist",
"description": "The accent1 colour slot must be present."
},
{
"id": "clr-scheme-slot-accent2",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:accent2",
"must": "exist",
"description": "The accent2 colour slot must be present."
},
{
"id": "clr-scheme-slot-accent3",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:accent3",
"must": "exist",
"description": "The accent3 colour slot must be present."
},
{
"id": "clr-scheme-slot-accent4",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:accent4",
"must": "exist",
"description": "The accent4 colour slot must be present."
},
{
"id": "clr-scheme-slot-accent5",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:accent5",
"must": "exist",
"description": "The accent5 colour slot must be present."
},
{
"id": "clr-scheme-slot-accent6",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:accent6",
"must": "exist",
"description": "The accent6 colour slot must be present."
},
{
"id": "clr-scheme-slot-hlink",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:hlink",
"must": "exist",
"description": "The hlink (hyperlink) colour slot must be present."
},
{
"id": "clr-scheme-slot-folHlink",
"part": "ppt/theme/theme1.xml",
"namespaces": {
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"
},
"xpath": "//a:clrScheme/a:folHlink",
"must": "exist",
"description": "The folHlink (followed hyperlink) colour slot must be present."
}
]
}
No rendered reference is available for this case.