feat(#79): IMP-51 image_overrides axis (u1~u11 backend stamp+CLI+CSS inject + frontend drag/resize+persistence + tests)
This commit is contained in:
@@ -1,19 +1,26 @@
|
||||
"""IMP-52 (#80) u1 — user_overrides.json persistence layer (backend IO).
|
||||
|
||||
Persists the four CLI-wired override axes per MDX so a subsequent render
|
||||
Persists the CLI-wired override axes per MDX so a subsequent render
|
||||
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 (4 axes; stable order):
|
||||
Schema (5 axes; stable order; IMP-51 #79 u1 added ``image_overrides``):
|
||||
|
||||
{
|
||||
"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>}
|
||||
"frames": {<unit_id>: <template_id>},
|
||||
"image_overrides": {<image_id>: {"x": float, "y": float, "w": float, "h": float}}
|
||||
}
|
||||
|
||||
``image_id`` is the stable identifier emitted by the user-content image
|
||||
stamper (IMP-51 u4) and matched via the selector
|
||||
``.slide img[data-image-role="user-content"]``. Coordinates are
|
||||
percent-of-slide (zone-agnostic, slide-absolute) to match the SlideCanvas
|
||||
edit-mode handle conventions in IMP-51 u8~u11.
|
||||
|
||||
``unit_id`` is the convention already used by ``--override-frame`` :
|
||||
``"+".join(source_section_ids)`` (e.g., ``"03-1"`` or ``"03-1+03-2"``).
|
||||
|
||||
@@ -46,10 +53,17 @@ from typing import Any, Optional
|
||||
_PKG_ROOT = Path(__file__).resolve().parent.parent
|
||||
DEFAULT_OVERRIDES_ROOT = _PKG_ROOT / "data" / "user_overrides"
|
||||
|
||||
# The four in-scope axes. 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, image_overrides) without a schema bump here.
|
||||
KNOWN_AXES: tuple[str, ...] = ("layout", "zone_geometries", "zone_sections", "frames")
|
||||
# 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.
|
||||
KNOWN_AXES: tuple[str, ...] = (
|
||||
"layout",
|
||||
"zone_geometries",
|
||||
"zone_sections",
|
||||
"frames",
|
||||
"image_overrides",
|
||||
)
|
||||
|
||||
# Key validation — MDX stem must be safe for filesystem use. Allow
|
||||
# alphanumerics, underscore, hyphen, and dot in the middle (sample stems
|
||||
@@ -92,7 +106,7 @@ def load(key: str, root: Optional[Path] = None) -> dict[str, Any]:
|
||||
|
||||
Missing file → ``{}``. Corrupt JSON → warning to stderr + ``{}``.
|
||||
Returns the raw mapping (including any foreign keys); callers should
|
||||
pick the four KNOWN_AXES they care about.
|
||||
pick the KNOWN_AXES they care about.
|
||||
"""
|
||||
path = override_path(key, root=root)
|
||||
if not path.exists():
|
||||
|
||||
Reference in New Issue
Block a user