feat(#74): IMP-45 u1~u8 slide-level CSS override (frontmatter slide_overrides.css + --override-slide-css/--slide-css-file + idempotent Step 13 injector)
Some checks failed
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 22s
Some checks failed
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 22s
u1 KNOWN_AXES tuple gains slide_css entry in src/user_overrides_io.py
(snake_case parity with image_overrides); round-trip test extends
to 6 axes.
u2 src/mdx_normalizer.py surfaces nested slide_overrides.css from the
MDX frontmatter into the normalize_mdx_content return dict; absent
key -> {}, non-string css drops. 4 unit cases in tests/test_mdx_normalizer.py
(present / absent / non-string / title-only).
u3 src/slide_css_injector.py NEW (88 lines) mirrors the
inject_image_overrides_style contract from src/image_id_stamper.py:
marker pair <!--IMP45-SLIDE-CSS:OPEN--> / <!--IMP45-SLIDE-CSS:CLOSE-->,
idempotent re-injection, </head> > <body> > document-start three-tier
fallback, empty/None -> unchanged. 8 fixtures in
tests/test_slide_css_injector.py mirror test_image_id_stamper.py.
u4 run_phase_z2_mvp1 accepts override_slide_css: Optional[str] = None;
None -> frontmatter slide_overrides.css fallback. Step 13 calls
inject_slide_css after image override injection and before the
final.html disk write, so CLI/CI/regression renders observe the same
backend artifact.
u5 argparse adds mutually-exclusive --override-slide-css TEXT (inline
CSS, <style> wrapper optional) and --slide-css-file PATH (UTF-8 read,
fail-closed sys.exit(2) on missing path / decode error / both flags
present). Resolved string is forwarded as override_slide_css kwarg.
6 cases in tests/test_phase_z2_cli_overrides.py (inline / file / both
/ missing / non-utf8 / neither).
u6 samples/mdx_batch/04.mdx frontmatter gains slide_overrides.css
block (verbatim of the former MDX04_DEFAULT_OVERRIDE_CSS constant,
no sample/frame gate). Subprocess smoke in
tests/test_phase_z2_slide_css_smoke.py verifies the marker pair and
CSS substring land in final.html.
u7 Front/client removes the sample/frame-gated frontend-only injection:
Home.tsx drops the MDX04_DEFAULT_OVERRIDE_CSS constant and the
sample==="04"+frame==="process_product_two_way" branch (-28 lines);
SlideCanvas.tsx drops the iframe contentDocument.head injection of
that prop (-14 lines). Live preview now reads backend final.html only.
u8 tests/regression/fixtures/89a_pre_baseline_sha.json 04.mdx entry
resyncs to the live SHA ddb6bf2f... / 28042 bytes (overwrites the
earlier 5-byte-drift d02c76fd... / 28047). Other entries untouched.
Note: 01.mdx baseline drift (ad6f16a3... / 29089 -> live f26a7fac...
/ 29084) predates this branch and is split to a follow-up issue per
the closed-issue fresh validation rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,14 +5,16 @@ auto-restores user choices without re-clicking. Source of truth = MDX-keyed
|
||||
file (stem of the MDX path), NOT ``data/runs/<run_id>/`` which mints a fresh
|
||||
run_id per ``/api/run`` invocation.
|
||||
|
||||
Schema (5 axes; stable order; IMP-51 #79 u1 added ``image_overrides``):
|
||||
Schema (6 axes; stable order; IMP-51 #79 u1 added ``image_overrides``;
|
||||
IMP-45 #74 u1 added ``slide_css``):
|
||||
|
||||
{
|
||||
"layout": <string|null>,
|
||||
"zone_geometries": {<zone_id>: {"x": float, "y": float, "w": float, "h": float}},
|
||||
"zone_sections": {<zone_id>: [<section_id>, ...]},
|
||||
"frames": {<unit_id>: <template_id>},
|
||||
"image_overrides": {<image_id>: {"x": float, "y": float, "w": float, "h": float}}
|
||||
"image_overrides": {<image_id>: {"x": float, "y": float, "w": float, "h": float}},
|
||||
"slide_css": <string|null>
|
||||
}
|
||||
|
||||
``image_id`` is the stable identifier emitted by the user-content image
|
||||
@@ -53,16 +55,17 @@ from typing import Any, Optional
|
||||
_PKG_ROOT = Path(__file__).resolve().parent.parent
|
||||
DEFAULT_OVERRIDES_ROOT = _PKG_ROOT / "data" / "user_overrides"
|
||||
|
||||
# The five in-scope axes (IMP-51 #79 u1 added ``image_overrides``). Any
|
||||
# other top-level key in the file is preserved but ignored by callers —
|
||||
# keeps the file forward-compatible with future axes (e.g., zone_sizes)
|
||||
# without a schema bump here.
|
||||
# The six in-scope axes (IMP-51 #79 u1 added ``image_overrides``; IMP-45
|
||||
# #74 u1 added ``slide_css``). Any other top-level key in the file is
|
||||
# preserved but ignored by callers — keeps the file forward-compatible
|
||||
# with future axes (e.g., zone_sizes) without a schema bump here.
|
||||
KNOWN_AXES: tuple[str, ...] = (
|
||||
"layout",
|
||||
"zone_geometries",
|
||||
"zone_sections",
|
||||
"frames",
|
||||
"image_overrides",
|
||||
"slide_css",
|
||||
)
|
||||
|
||||
# Key validation — MDX stem must be safe for filesystem use. Allow
|
||||
|
||||
Reference in New Issue
Block a user