Skip to content

A deck's own settings, and a theme that is one file - #47

Merged
fabeat merged 6 commits into
mainfrom
feature/theme-files
Nov 4, 2026
Merged

fabeat merged 6 commits into
mainfrom
feature/theme-files

Conversation

@fabeat

@fabeat fabeat commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Two changes, both about what a setting belongs to.

The deck's own settings

A deck could not say "my accent is this" for every slide from its own frontmatter. theme-variables: was read per slide, over a theme resolved once from the deck's theme: directive, so the file's own frontmatter reached exactly one slide.

There is now a layer for the deck, and the precedence is slide → template → deck → theme:

---
theme: corporate-dark
deck-settings:
  theme-variables:
    colors:
      accent1: "#123456"
  background: "#101014"
---

deck-settings: holds the same keys template-settings: does, and it is the deck's alone — refused on any slide but the first, the way theme: is.

The pattern the suite now holds, and which this change completes: the ordinary keys are the slide's own, wherever they are written; a key that holds someone else's settings says whose. template-settings: says the template's; deck-settings: says the deck's.

A theme is one file

A theme was a directory of up to five files. It is theme.yml and the master now, with the roles and the named styles as two sections of the file.

All five themes that ship carried a byte-identical layouts.yml — the same eight Office names — so for a theme without a master it was a default written out five times. The library ships it now, and a theme with no layouts: section is drawn with it. A theme with a section has the whole mapping, so a role the section does not name is a role the theme does not map, and the deck that asks for one is told which roles the theme does map.

This breaks a published format. The three files are refused when they are beside a theme, each with a message naming the section its content goes into:

The theme "acme" has a "layouts.yml" beside it. A theme is one file: move its content into the "layouts:" section of its "theme.yml".

The theme "acme" has a "text-styles.yml" beside it. A theme is one file: move its content into the "textStyles:" section of its "theme.yml".

The theme "acme" has a "styles.yml" beside it. That file is the Word half's, and this half does not read it: its slots name Word styles, which a deck of slides has no use for. Delete it, and the theme is read again.

They are refused rather than ignored: a file that is quietly not read is a theme that looks like the one its author wrote and is not. The third is the Word half's file, which this half loaded for years without ever using it — so the classes that read it are gone.

The packages are pre-1.0 and 0.4.0 is unreleased, so the break lands there rather than at 1.0.

The gates

  • 1813 tests, 100% coverage, PHPStan level 9 with no baseline and no ignores.
  • Every new test was shown to fail without its fix.

The deck's frontmatter is its first slide's, and `theme-variables:` is read per
slide, so a deck that named an accent in its frontmatter painted the first slide
in that accent and left every other slide in the theme's own. There was no layer
for the deck at all.

The layer is `deck-settings:` now, and it holds the same settings a slide's own
are written in. The ordinary keys mean the slide's own everywhere, so the deck's
settings say whose they are, the way a template's do: the precedence is slide →
template → deck → theme.

`deck-settings:` belongs in slide 1's front matter, which is the deck's own, and
it is refused on any other slide — the way `theme:` is.
A theme was a directory of up to five files: `theme.yml` for the look,
`layouts.yml` for the eight layout roles, `text-styles.yml` for the named text
styles, `styles.yml` for the Word half's style slots, and `template.pptx` for
the master. It is `theme.yml` and the master now, with the roles and the named
styles as two sections of the file.

All five themes that ship with the library carried a byte-identical
`layouts.yml` — the same eight Office names — so for a theme without a master it
was a default written out five times. The library ships it now, and a theme with
no `layouts:` section is drawn with it. A theme *with* a section has the whole
mapping, so a role the section does not name is a role the theme does not map,
and the deck that asks for one is told which roles the theme does map.

The three files are refused when they are beside a theme, each with a message
naming the section its content goes into. They are refused rather than ignored:
a file that is quietly not read is a theme that looks like the one its author
wrote and is not. The third of them is the Word half's, and this half loaded it
for years without ever using it — its slots name Word styles and a deck of
slides has no use for them — so the classes that read it are gone.
The review read the change and said six of its sentences were wrong. Four of
them made a template's rule and a theme's `layouts:` section the same rule: a
template fills in the roles it covers and leaves the rest where the library puts
them, while a `layouts:` section is the whole mapping — a role it does not name
is a role the theme does not map, and the deck that asks for one is told which
roles the theme does map. The library contradicted itself: the claim guard
already said the right thing, and four sentences said the opposite.

The background of a slide was said to be the first of the settings to name one.
It is the last: a slide's own is painted over the template's, and the
template's over the deck's.

A `styles.yml` beside a theme was refused for a reason given in terms of the
themes that used to ship one. None of them does now, and none can — the file is
refused at loader time — so the reason is now what a `styles.yml` holds.

Each of those phrases is in the claim guard, so it cannot come back.

The new features had nothing to look at. `examples/markdown/20-deck-settings.md`
is the deck that shows the deck's layer: the deck's page and ink on every slide
of it, and the two slides that name a setting of their own. The corporate
example theme carries a `layouts:` section now — every role, because a section
is the whole mapping — and its README says what the section is for.

A named text style is the theme's own and not among the values a slide may lay
over it, so a slide that lays values over the theme keeps it. Nothing said so,
and dropping the styles from that round trip took every test with it: a named
style would have vanished from any slide carrying `theme-variables:`, and
`:brand[…]` would have been refused with "the theme has no text styles".
…t into

The message told the reader to move the content of a file of the old format
into the section it became, and stopped there. The refusal is about the file
being beside the theme rather than about what is in it, so a reader who moved
the content and left the file was refused again on the next render, with the
same message. It now says to delete the file as well, and the pages that quote
it, the tests that assert on it and the comments that describe it say so too.
@sonarqubecloud

sonarqubecloud Bot commented Nov 4, 2026

Copy link
Copy Markdown

@fabeat
fabeat merged commit 9979b8d into main Nov 4, 2026
9 checks passed
@fabeat
fabeat deleted the feature/theme-files branch November 4, 2026 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant