Found while adding the content-area report in #171. Reported rather than changed there, because it alters what generated decks look like and #171 was about showing the rectangle, not choosing it.
LayoutResolver applies a template's configured layouts: mapping in provides() and resolve() — so a spec saying layouts: {content: "My Content Layout"} does decide which layout a content slide is built on. But content_area() reads self._by_role, and _by_role is populated from classify_layout() alone:
for layout in self._layouts:
role = classify_layout(layout)
self._roles.append(role)
if role and role not in self._by_role:
self._by_role[role] = layout
self._configured never reaches it. So the content rectangle is read from whichever layout the signature rules classified as content (or the next CONTENT_REFERENCE_ROLES match), regardless of what the admin configured.
Verified
On the shipped 16:9 template, which has seven distinct content rectangles across eleven layouts:
resolver._by_role['content'] with {"content": "Dva obsahy"} -> Nadpis a obsah
content_area() -> Rect(source='Nadpis a obsah')
The override is simply not consulted.
Why it matters
CONTENT_REFERENCE_ROLES begins with ROLE_CONTENT, so the intent is clearly to prefer the content layout — the code just uses the detected one rather than the configured one. An admin who overrides the content role because detection picked the wrong layout has fixed where content slides are built, but not the rectangle that blank, KPI and timeline slides position themselves against. Those keep using the mis-detected layout's geometry, which is the exact problem the override was set to solve.
It is consistent today in one respect — the admin card added in #171 reads it the same way, so the UI shows what the builder does, and there is a test pinning that. Fixing this means the card must start reading the spec's overrides too; the test names that requirement.
Suggested fix
Consult self._configured in content_area() the way resolve() does — try by_name(self._configured.get(role)) for each role in CONTENT_REFERENCE_ROLES before falling back to _by_role[role].
Worth deciding deliberately: it changes the geometry of self-positioned slides for any existing template that both sets a content override and has a differently-shaped detected content layout. That is a narrow set, but not an empty one.
Found while adding the content-area report in #171. Reported rather than changed there, because it alters what generated decks look like and #171 was about showing the rectangle, not choosing it.
LayoutResolverapplies a template's configuredlayouts:mapping inprovides()andresolve()— so a spec sayinglayouts: {content: "My Content Layout"}does decide which layout acontentslide is built on. Butcontent_area()readsself._by_role, and_by_roleis populated fromclassify_layout()alone:self._configurednever reaches it. So the content rectangle is read from whichever layout the signature rules classified ascontent(or the nextCONTENT_REFERENCE_ROLESmatch), regardless of what the admin configured.Verified
On the shipped 16:9 template, which has seven distinct content rectangles across eleven layouts:
The override is simply not consulted.
Why it matters
CONTENT_REFERENCE_ROLESbegins withROLE_CONTENT, so the intent is clearly to prefer the content layout — the code just uses the detected one rather than the configured one. An admin who overrides the content role because detection picked the wrong layout has fixed wherecontentslides are built, but not the rectangle thatblank, KPI and timeline slides position themselves against. Those keep using the mis-detected layout's geometry, which is the exact problem the override was set to solve.It is consistent today in one respect — the admin card added in #171 reads it the same way, so the UI shows what the builder does, and there is a test pinning that. Fixing this means the card must start reading the spec's overrides too; the test names that requirement.
Suggested fix
Consult
self._configuredincontent_area()the wayresolve()does — tryby_name(self._configured.get(role))for each role inCONTENT_REFERENCE_ROLESbefore falling back to_by_role[role].Worth deciding deliberately: it changes the geometry of self-positioned slides for any existing template that both sets a content override and has a differently-shaped detected content layout. That is a narrow set, but not an empty one.