Repository navigation
fix(cli): media-treatment applies one treatment to every matched image or video - #5443
Conversation
Edit accuracy: accurate 2061 (base branch 2061), smooth 1635 of thoseThe gate passes. Quarantined, measured but not gated (0) |
…cuments the per-element merge
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
…write cannot redirect another
…-finding elements
jrusso1020
left a comment
There was a problem hiding this comment.
Approve at 0a7c9f6b. No blockers.
What I checked:
applyMediaTreatmentToHtmlnow parses once with the studio-serverparseSourceDocument(which runsensureHfIdsfirst), selects from that same document, writes each match in place, and serializes once withensureHfIds. That is the same parse → write → serialize sequencepatchElementInHtmluses (sourceMutation.ts:246-328), so a single-element apply gives the same bytes as before. Nothing is looked up again after a write, so thevideo:has(+ video[data-color-grading])and duplicate-data-hf-idcases can't send one write to another element.selectMediaElementschecks every target before any write: tag isimg/videoandisHTMLElement. A mixed selector or a<video>inside an SVGforeignObjectfails before the document changes, and ifserializeGradingPatchthrows partway through the map, nothing is written either.--analyzestill goes through the single-targetselectMediaElement, which keeps the "matched N elements" error.actioncomes from every target (every(value === null)). The JSON keeps the old single-target fields whencount === 1and reportstargetsotherwise. Nothing in the repo reads the old multi-match shape (that case used to fail), so no caller breaks.- Docs,
help.tsand the media-use reference describe the new default and the per-element merge.
Local run at this head (no real media files or render involved):
media-treatment.test.ts: 34/34 pass.- Mutation probe: I changed
actionback to "from the first target", andreports apply when any match keeps a grading after the patchfailed. I reverted the change afterwards.
All 11 required checks are green at this head.
— Rames
jrusso1020
left a comment
There was a problem hiding this comment.
Approve at 99343c71. I'm re-pinning my earlier approval of 0a7c9f6b.
The new head fast-forwards the one I approved by a single commit. That commit changes one line in skills-manifest.json: the media-use hash goes from 206565a9b0cc6ac2 to 1a841e4288d862af, and the file count stays at 110. No code changed, so my review of 0a7c9f6b still holds. Skills: manifest in sync passes at this head, which confirms the new hash, and all 11 required checks are green.
— Rames
What changes for the user
hyperframes media-treatment --selector video --grading '<patch>' --applynow applies the patch to every matched image or video, instead of failing with "Selector matched N elements". Grading every segment of a cut alike is one command. The text output says how many of the matched elements changed, and--jsonreportscountplus each target (selectorIndex,tag,changed,before,after,value). Each match gets the patch merged into its own current grading, so segments that already differ keep their other settings; run--clearwith the same selector first for an identical look.--selector-indexstill treats only one match, and--dry-runpreviews all of them without writing. The reported action (Applied/Cleared, JSONaction) reflects every target, not just the first.Why this default
The command's own help example (
--selector 'video' --grading ... --dry-run) only worked on a project with exactly one video, and the reported case wanted one consistent look on every segment. The change is previewable (--dry-run) and reversible (--clearwith the same selector). Every match must be an<img>or<video>: a selector that also matches anything else fails the whole command, naming the element it matched, and so does a match that is not an HTML element (a<video>inside an SVGforeignObject). The previous path refused that only when a write was needed; it is now refused on every run, including--analyzeand no-op runs. Matches come from the main document or, when it has none, from the first<template>that has any, the same scope rule as Studio's source edits.How
selectMediaElementsinmedia-treatment.tsreturns every match (or the one--selector-indexpicks), each checked to be an<img>or<video>.applyMediaTreatmentToHtmlparses the file once (the sameparseSourceDocumentthe studio-server patch uses), finds every match in that one document, sets or removesdata-color-gradingon each matched element directly, and serializes once withensureHfIds, exactly aspatchElementInHtmldoes. Nothing re-finds an element after a write, so a write that changes which elements the selector matches (video[data-color-grading],video:has(+ video[data-color-grading])), duplicateddata-hf-ids in the file, or matches inside a<template>cannot redirect another write. A single-element apply produces the same bytes as before.--analyzestill needs a single element, since it inspects one media file. The JSON keeps the old single-target fields (selectorIndex,tag,before,after,value) when one element is treated, and reportstargetsinstead when several are. The flag help, thehelpsummary, the CLI docs page and the media-use treatment reference now describe the behaviour.Verification
media-treatment.test.tscases: two videos matched byvideoboth get the same grading; clearing withvideo[data-color-grading]clears both; a mixed match (.segon a video and a div) is rejected naming<div>; two images are both graded unless--selector-indexpicks one;--apply --jsonreportscount: 2and both targets and writes both. Each fails on the previous code except the--selector-indexcase, which the previous code already supported.video:has(+ video[data-color-grading])clear over four graded videos clears exactly the three it matched, in the main document and inside a<template>; with an<img>and a<video>sharing onedata-hf-id,--selector videogrades the video, not the image; a later match's change is written when the first match is already graded; two matches starting from different gradings each keep their own settings under the merged patch; a patch that leaves one match ungraded and another graded reportsapply(fails on the previous head, which reportedclearfrom the first match).<video>inside an SVGforeignObjectis refused rather than written (writing it would serialize the following content inside the video tag); fails on the previous head.