@mevdragon/vidfarm-devcli 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/embedded-captions/CATALOG.md +93 -0
- package/.agents/skills/embedded-captions/SKILL.md +286 -0
- package/.agents/skills/embedded-captions/assets/brand/CDPR-fankit-terms.txt +35 -0
- package/.agents/skills/embedded-captions/assets/brand/cyberpunk-widths.json +115 -0
- package/.agents/skills/embedded-captions/assets/fonts/char-widths.json +2211 -0
- package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScript1.svg +242 -0
- package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScriptMed.svg +242 -0
- package/.agents/skills/embedded-captions/dna/README.md +148 -0
- package/.agents/skills/embedded-captions/dna/chrome.json +68 -0
- package/.agents/skills/embedded-captions/dna/cream.json +69 -0
- package/.agents/skills/embedded-captions/dna/documentary.json +62 -0
- package/.agents/skills/embedded-captions/dna/editorial.json +70 -0
- package/.agents/skills/embedded-captions/dna/glitch.json +82 -0
- package/.agents/skills/embedded-captions/dna/ink.json +65 -0
- package/.agents/skills/embedded-captions/dna/keynote.json +62 -0
- package/.agents/skills/embedded-captions/dna/loud.json +75 -0
- package/.agents/skills/embedded-captions/dna/neon.json +58 -0
- package/.agents/skills/embedded-captions/dna/velocity.json +89 -0
- package/.agents/skills/embedded-captions/modes/cinematic/README.md +48 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/spec.md +98 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/template.html +188 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/spec.md +134 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/template.html +179 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/spec.md +81 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/template.html +170 -0
- package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/spec.md +16 -0
- package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/template.html +226 -0
- package/.agents/skills/embedded-captions/modes/cinematic/engine.html +355 -0
- package/.agents/skills/embedded-captions/modes/standard/_anatomy.md +233 -0
- package/.agents/skills/embedded-captions/modes/standard/_motion.md +192 -0
- package/.agents/skills/embedded-captions/modes/standard/fonts/build-fonts-css.cjs +97 -0
- package/.agents/skills/embedded-captions/references/aesthetic-principles.md +168 -0
- package/.agents/skills/embedded-captions/references/anti-patterns.md +188 -0
- package/.agents/skills/embedded-captions/references/bespoke-vs-presets.md +178 -0
- package/.agents/skills/embedded-captions/references/caption-grouping.md +130 -0
- package/.agents/skills/embedded-captions/references/composition-craft.md +522 -0
- package/.agents/skills/embedded-captions/references/direction-catalog.md +138 -0
- package/.agents/skills/embedded-captions/references/example-renders/champion.html +371 -0
- package/.agents/skills/embedded-captions/references/example-renders/memory-wall.html +334 -0
- package/.agents/skills/embedded-captions/references/failure-modes.md +145 -0
- package/.agents/skills/embedded-captions/references/layout-heuristics.md +238 -0
- package/.agents/skills/embedded-captions/references/motion-vocabulary.md +148 -0
- package/.agents/skills/embedded-captions/references/rail.md +68 -0
- package/.agents/skills/embedded-captions/references/reference-bar.md +47 -0
- package/.agents/skills/embedded-captions/references/scene-types.md +94 -0
- package/.agents/skills/embedded-captions/references/test-set.md +66 -0
- package/.agents/skills/embedded-captions/references/typographic-moves.md +266 -0
- package/.agents/skills/embedded-captions/references/typography-presets.md +63 -0
- package/.agents/skills/embedded-captions/scripts/audio-envelope.cjs +95 -0
- package/.agents/skills/embedded-captions/scripts/check-occlusion.cjs +250 -0
- package/.agents/skills/embedded-captions/scripts/check-overflow.cjs +194 -0
- package/.agents/skills/embedded-captions/scripts/check-rail-climax.cjs +233 -0
- package/.agents/skills/embedded-captions/scripts/check-timing.cjs +173 -0
- package/.agents/skills/embedded-captions/scripts/fill-timings.cjs +124 -0
- package/.agents/skills/embedded-captions/scripts/fit-fonts.cjs +158 -0
- package/.agents/skills/embedded-captions/scripts/gen-stroke-path.py +46 -0
- package/.agents/skills/embedded-captions/scripts/inject-fonts.cjs +169 -0
- package/.agents/skills/embedded-captions/scripts/lib-dna.cjs +201 -0
- package/.agents/skills/embedded-captions/scripts/make-cinematic.cjs +1205 -0
- package/.agents/skills/embedded-captions/scripts/make-composition.cjs +404 -0
- package/.agents/skills/embedded-captions/scripts/make-theme.cjs +8781 -0
- package/.agents/skills/embedded-captions/scripts/matte.cjs +294 -0
- package/.agents/skills/embedded-captions/scripts/measure-layout.cjs +293 -0
- package/.agents/skills/embedded-captions/scripts/prepare.sh +39 -0
- package/.agents/skills/embedded-captions/scripts/preview-frames.cjs +268 -0
- package/.agents/skills/embedded-captions/scripts/render-and-composite.sh +509 -0
- package/.agents/skills/embedded-captions/scripts/render-theme.sh +34 -0
- package/.agents/skills/embedded-captions/scripts/safe-zones.cjs +813 -0
- package/.agents/skills/embedded-captions/scripts/transcribe.cjs +349 -0
- package/.agents/skills/embedded-captions/themes/PORTING.md +49 -0
- package/.agents/skills/embedded-captions/themes/README.md +244 -0
- package/.agents/skills/embedded-captions/themes/anchor.json +27 -0
- package/.agents/skills/embedded-captions/themes/arcade.json +51 -0
- package/.agents/skills/embedded-captions/themes/aurora.json +41 -0
- package/.agents/skills/embedded-captions/themes/biolume.json +35 -0
- package/.agents/skills/embedded-captions/themes/brush.json +74 -0
- package/.agents/skills/embedded-captions/themes/chalkboard.json +52 -0
- package/.agents/skills/embedded-captions/themes/dossier.json +56 -0
- package/.agents/skills/embedded-captions/themes/graffiti.json +62 -0
- package/.agents/skills/embedded-captions/themes/hologram.json +41 -0
- package/.agents/skills/embedded-captions/themes/inkwater.json +43 -0
- package/.agents/skills/embedded-captions/themes/laser.json +46 -0
- package/.agents/skills/embedded-captions/themes/lastpage.json +33 -0
- package/.agents/skills/embedded-captions/themes/neonsign.json +53 -0
- package/.agents/skills/embedded-captions/themes/nightcity.json +56 -0
- package/.agents/skills/embedded-captions/themes/ordnance.json +54 -0
- package/.agents/skills/embedded-captions/themes/papercut.json +37 -0
- package/.agents/skills/embedded-captions/themes/popup.json +46 -0
- package/.agents/skills/embedded-captions/themes/ransom.json +62 -0
- package/.agents/skills/embedded-captions/themes/scoreboard.json +54 -0
- package/.agents/skills/embedded-captions/themes/spectrum.json +46 -0
- package/.agents/skills/embedded-captions/themes/stardust.json +29 -0
- package/.agents/skills/embedded-captions/themes/stomp.json +43 -0
- package/.agents/skills/embedded-captions/themes/terminal.json +49 -0
- package/.agents/skills/embedded-captions/themes/thunder.json +44 -0
- package/.agents/skills/embedded-captions/themes/transit.json +44 -0
- package/.agents/skills/embedded-captions/themes/vhs.json +47 -0
- package/.agents/skills/faceless-explainer/SKILL.md +209 -0
- package/.agents/skills/faceless-explainer/references/cut-catalog.md +215 -0
- package/.agents/skills/faceless-explainer/references/motion-language.md +156 -0
- package/.agents/skills/faceless-explainer/references/story-design.md +248 -0
- package/.agents/skills/faceless-explainer/references/visual-design.md +146 -0
- package/.agents/skills/faceless-explainer/scripts/assemble-index.mjs +570 -0
- package/.agents/skills/faceless-explainer/scripts/audio.mjs +260 -0
- package/.agents/skills/faceless-explainer/scripts/build-frame.mjs +536 -0
- package/.agents/skills/faceless-explainer/scripts/captions.mjs +508 -0
- package/.agents/skills/faceless-explainer/scripts/lib/assets.mjs +55 -0
- package/.agents/skills/faceless-explainer/scripts/lib/dimensions.mjs +45 -0
- package/.agents/skills/faceless-explainer/scripts/lib/storyboard.mjs +249 -0
- package/.agents/skills/faceless-explainer/scripts/lib/tokens.mjs +204 -0
- package/.agents/skills/faceless-explainer/scripts/lib/transition-registry.mjs +38 -0
- package/.agents/skills/faceless-explainer/scripts/lib/transitions.json +71 -0
- package/.agents/skills/faceless-explainer/scripts/transitions.mjs +320 -0
- package/.agents/skills/faceless-explainer/sub-agents/frame-worker.md +75 -0
- package/.agents/skills/flockposter/LICENSE +17 -0
- package/.agents/skills/flockposter/README.md +72 -0
- package/.agents/skills/flockposter/SKILL.md +562 -0
- package/.agents/skills/flockposter/examples/cli-instagram-reel.sh +21 -0
- package/.agents/skills/flockposter/examples/cli-multi-platform.json +69 -0
- package/.agents/skills/flockposter/examples/cli-tiktok-upload-only.sh +22 -0
- package/.agents/skills/flockposter/examples/cli-x-thread.sh +17 -0
- package/.agents/skills/flockposter/examples/cli-youtube-short.sh +21 -0
- package/.agents/skills/flockposter/examples/public-api-instagram-reel.json +28 -0
- package/.agents/skills/general-video/SKILL.md +143 -0
- package/.agents/skills/hyperframes/SKILL.md +160 -0
- package/.agents/skills/hyperframes-animation/SKILL.md +84 -0
- package/.agents/skills/hyperframes-animation/adapters/animate-text.md +64 -0
- package/.agents/skills/hyperframes-animation/adapters/animejs.md +114 -0
- package/.agents/skills/hyperframes-animation/adapters/css-animations.md +143 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-easing-and-stagger.md +118 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-timeline-and-labels.md +96 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-transforms-and-perf.md +96 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap.md +105 -0
- package/.agents/skills/hyperframes-animation/adapters/html-in-canvas-patterns.md +507 -0
- package/.agents/skills/hyperframes-animation/adapters/lottie.md +117 -0
- package/.agents/skills/hyperframes-animation/adapters/three.md +131 -0
- package/.agents/skills/hyperframes-animation/adapters/typegpu.md +178 -0
- package/.agents/skills/hyperframes-animation/adapters/waapi.md +101 -0
- package/.agents/skills/hyperframes-animation/blueprints/comparison-split.md +27 -0
- package/.agents/skills/hyperframes-animation/blueprints/constellation-hub.md +44 -0
- package/.agents/skills/hyperframes-animation/blueprints/cta-morph-press.md +28 -0
- package/.agents/skills/hyperframes-animation/blueprints/cursor-ui-demo.md +57 -0
- package/.agents/skills/hyperframes-animation/blueprints/dataviz-countup.md +46 -0
- package/.agents/skills/hyperframes-animation/blueprints/device-surface-showcase.md +53 -0
- package/.agents/skills/hyperframes-animation/blueprints/grid-card-assemble.md +66 -0
- package/.agents/skills/hyperframes-animation/blueprints/kinetic-type-beats.md +78 -0
- package/.agents/skills/hyperframes-animation/blueprints/logo-assemble-lockup.md +69 -0
- package/.agents/skills/hyperframes-animation/blueprints/overwhelm-surround.md +28 -0
- package/.agents/skills/hyperframes-animation/blueprints/spatial-pan-stations.md +37 -0
- package/.agents/skills/hyperframes-animation/blueprints/ticker-takeover.md +29 -0
- package/.agents/skills/hyperframes-animation/blueprints/titlecard-reveal.md +42 -0
- package/.agents/skills/hyperframes-animation/blueprints/typewriter-reveal.md +51 -0
- package/.agents/skills/hyperframes-animation/blueprints/video-text-pivot.md +30 -0
- package/.agents/skills/hyperframes-animation/blueprints-index.md +146 -0
- package/.agents/skills/hyperframes-animation/examples/assets/avatars/02.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/github.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/nvidia.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/visa.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/zoominfo.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/brand-reveal-assemble-zoom.html +382 -0
- package/.agents/skills/hyperframes-animation/examples/comparison-split-cards.html +649 -0
- package/.agents/skills/hyperframes-animation/examples/concept-demo-decode-pan.html +520 -0
- package/.agents/skills/hyperframes-animation/examples/cta-morph-press.html +468 -0
- package/.agents/skills/hyperframes-animation/examples/cta-orbit-collapse.html +1298 -0
- package/.agents/skills/hyperframes-animation/examples/demo-page-scroll-spotlight.html +759 -0
- package/.agents/skills/hyperframes-animation/examples/hook-counter-burst.html +729 -0
- package/.agents/skills/hyperframes-animation/examples/messaging-multi-phrase.html +352 -0
- package/.agents/skills/hyperframes-animation/examples/metric-video-text-pivot.html +779 -0
- package/.agents/skills/hyperframes-animation/examples/problem-mockup-overwhelm.html +1374 -0
- package/.agents/skills/hyperframes-animation/examples/proof-logo-chain.html +861 -0
- package/.agents/skills/hyperframes-animation/examples/takeover-ticker-displace.html +347 -0
- package/.agents/skills/hyperframes-animation/examples/workflow-approve-press.html +606 -0
- package/.agents/skills/hyperframes-animation/rules/3d-page-scroll.md +227 -0
- package/.agents/skills/hyperframes-animation/rules/3d-text-depth-layers.md +297 -0
- package/.agents/skills/hyperframes-animation/rules/ai-tracking-box.md +382 -0
- package/.agents/skills/hyperframes-animation/rules/ambient-glow-bloom.md +305 -0
- package/.agents/skills/hyperframes-animation/rules/asr-keyword-glow.md +286 -0
- package/.agents/skills/hyperframes-animation/rules/avatar-cloud-network.md +371 -0
- package/.agents/skills/hyperframes-animation/rules/camera-cursor-tracking.md +246 -0
- package/.agents/skills/hyperframes-animation/rules/card-morph-anchor.md +267 -0
- package/.agents/skills/hyperframes-animation/rules/center-outward-expansion.md +227 -0
- package/.agents/skills/hyperframes-animation/rules/context-sensitive-cursor.md +257 -0
- package/.agents/skills/hyperframes-animation/rules/coordinate-target-zoom.md +332 -0
- package/.agents/skills/hyperframes-animation/rules/counting-dynamic-scale.md +283 -0
- package/.agents/skills/hyperframes-animation/rules/css-marker-patterns.md +373 -0
- package/.agents/skills/hyperframes-animation/rules/cursor-click-ripple.md +262 -0
- package/.agents/skills/hyperframes-animation/rules/depth-of-field-blur.md +313 -0
- package/.agents/skills/hyperframes-animation/rules/depth-scatter-assemble.md +303 -0
- package/.agents/skills/hyperframes-animation/rules/discrete-text-sequence.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +307 -0
- package/.agents/skills/hyperframes-animation/rules/gsap-effects.md +299 -0
- package/.agents/skills/hyperframes-animation/rules/hacker-flip-3d.md +223 -0
- package/.agents/skills/hyperframes-animation/rules/kinetic-beat-slam.md +183 -0
- package/.agents/skills/hyperframes-animation/rules/motion-blur-streak.md +328 -0
- package/.agents/skills/hyperframes-animation/rules/multi-phase-camera.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/orbit-3d-entry.md +301 -0
- package/.agents/skills/hyperframes-animation/rules/physics-press-reaction.md +350 -0
- package/.agents/skills/hyperframes-animation/rules/press-release-spring.md +296 -0
- package/.agents/skills/hyperframes-animation/rules/reactive-displacement.md +277 -0
- package/.agents/skills/hyperframes-animation/rules/scale-swap-transition.md +298 -0
- package/.agents/skills/hyperframes-animation/rules/sine-wave-loop.md +278 -0
- package/.agents/skills/hyperframes-animation/rules/split-tilt-cards.md +277 -0
- package/.agents/skills/hyperframes-animation/rules/spring-pop-entrance.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/stat-bars-and-fills.md +156 -0
- package/.agents/skills/hyperframes-animation/rules/svg-icon-enrichment.md +329 -0
- package/.agents/skills/hyperframes-animation/rules/svg-path-draw.md +274 -0
- package/.agents/skills/hyperframes-animation/rules/vertical-spring-ticker.md +239 -0
- package/.agents/skills/hyperframes-animation/rules/viewport-change.md +349 -0
- package/.agents/skills/hyperframes-animation/rules-index.md +86 -0
- package/.agents/skills/hyperframes-animation/scripts/animation-map.mjs +606 -0
- package/.agents/skills/hyperframes-animation/scripts/package-loader.mjs +288 -0
- package/.agents/skills/hyperframes-animation/scripts/package-loader.test.mjs +62 -0
- package/.agents/skills/hyperframes-animation/techniques.md +507 -0
- package/.agents/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +167 -0
- package/.agents/skills/hyperframes-animation/transitions/catalog.md +127 -0
- package/.agents/skills/hyperframes-animation/transitions/css-3d.md +12 -0
- package/.agents/skills/hyperframes-animation/transitions/css-blur.md +51 -0
- package/.agents/skills/hyperframes-animation/transitions/css-cover.md +43 -0
- package/.agents/skills/hyperframes-animation/transitions/css-destruction.md +95 -0
- package/.agents/skills/hyperframes-animation/transitions/css-dissolve.md +66 -0
- package/.agents/skills/hyperframes-animation/transitions/css-distortion.md +45 -0
- package/.agents/skills/hyperframes-animation/transitions/css-grid.md +10 -0
- package/.agents/skills/hyperframes-animation/transitions/css-light.md +49 -0
- package/.agents/skills/hyperframes-animation/transitions/css-mechanical.md +30 -0
- package/.agents/skills/hyperframes-animation/transitions/css-other.md +25 -0
- package/.agents/skills/hyperframes-animation/transitions/css-push.md +41 -0
- package/.agents/skills/hyperframes-animation/transitions/css-radial.md +37 -0
- package/.agents/skills/hyperframes-animation/transitions/css-scale.md +24 -0
- package/.agents/skills/hyperframes-animation/transitions/overview.md +153 -0
- package/.agents/skills/hyperframes-cli/SKILL.md +113 -0
- package/.agents/skills/hyperframes-cli/references/doctor-browser.md +45 -0
- package/.agents/skills/hyperframes-cli/references/init-and-scaffold.md +55 -0
- package/.agents/skills/hyperframes-cli/references/lambda.md +132 -0
- package/.agents/skills/hyperframes-cli/references/lint-validate-inspect.md +121 -0
- package/.agents/skills/hyperframes-cli/references/preview-render.md +149 -0
- package/.agents/skills/hyperframes-cli/references/upgrade-info-misc.md +75 -0
- package/.agents/skills/hyperframes-core/SKILL.md +78 -0
- package/.agents/skills/hyperframes-core/references/composition-patterns.md +263 -0
- package/.agents/skills/hyperframes-core/references/data-attributes.md +70 -0
- package/.agents/skills/hyperframes-core/references/determinism-rules.md +68 -0
- package/.agents/skills/hyperframes-core/references/full-screen-motion.md +62 -0
- package/.agents/skills/hyperframes-core/references/minimal-composition.md +66 -0
- package/.agents/skills/hyperframes-core/references/script-format.md +49 -0
- package/.agents/skills/hyperframes-core/references/storyboard-format.md +95 -0
- package/.agents/skills/hyperframes-core/references/sub-compositions.md +237 -0
- package/.agents/skills/hyperframes-core/references/subagent-dispatch.md +41 -0
- package/.agents/skills/hyperframes-core/references/tailwind.md +125 -0
- package/.agents/skills/hyperframes-core/references/tracks-and-clips.md +76 -0
- package/.agents/skills/hyperframes-core/references/variables-and-media.md +90 -0
- package/.agents/skills/hyperframes-creative/SKILL.md +70 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/FRAME.md +289 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/caption-skin.html +221 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/FRAME.md +275 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/frame-showcase.html +1347 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/FRAME.md +307 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/caption-skin.html +223 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/frame-showcase.html +1372 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/FRAME.md +275 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/caption-skin.html +230 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/frame-showcase.html +1140 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/FRAME.md +284 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/caption-skin.html +225 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/frame-showcase.html +1166 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/FRAME.md +284 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/frame-showcase.html +1465 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/FRAME.md +278 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/caption-skin.html +222 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/frame-showcase.html +1263 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/FRAME.md +277 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/frame-showcase.html +1439 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/FRAME.md +265 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/caption-skin.html +238 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/FRAME.md +314 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/caption-skin.html +226 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/frame-showcase.html +1268 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/FRAME.md +333 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/caption-skin.html +227 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/frame-showcase.html +1330 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/FRAME.md +274 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/caption-skin.html +230 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/frame-showcase.html +1444 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/FRAME.md +265 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/caption-skin.html +223 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/frame-showcase.html +1273 -0
- package/.agents/skills/hyperframes-creative/palettes/bold-energetic.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/clean-corporate.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/dark-premium.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/jewel-rich.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/monochrome.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/nature-earth.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/neon-electric.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/pastel-soft.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/warm-editorial.md +14 -0
- package/.agents/skills/hyperframes-creative/references/audio-reactive.md +76 -0
- package/.agents/skills/hyperframes-creative/references/beat-direction.md +164 -0
- package/.agents/skills/hyperframes-creative/references/composition-patterns.md +199 -0
- package/.agents/skills/hyperframes-creative/references/data-in-motion.md +19 -0
- package/.agents/skills/hyperframes-creative/references/design-adherence.md +19 -0
- package/.agents/skills/hyperframes-creative/references/design-picker.md +123 -0
- package/.agents/skills/hyperframes-creative/references/design-spec.md +55 -0
- package/.agents/skills/hyperframes-creative/references/house-style.md +73 -0
- package/.agents/skills/hyperframes-creative/references/motion-principles.md +150 -0
- package/.agents/skills/hyperframes-creative/references/narration.md +92 -0
- package/.agents/skills/hyperframes-creative/references/prompt-expansion.md +68 -0
- package/.agents/skills/hyperframes-creative/references/typography.md +218 -0
- package/.agents/skills/hyperframes-creative/references/video-composition.md +63 -0
- package/.agents/skills/hyperframes-creative/references/visual-styles.md +457 -0
- package/.agents/skills/hyperframes-creative/scripts/contrast-report.mjs +353 -0
- package/.agents/skills/hyperframes-creative/scripts/extract-audio-data.py +188 -0
- package/.agents/skills/hyperframes-creative/scripts/package-loader.mjs +288 -0
- package/.agents/skills/hyperframes-creative/scripts/package-loader.test.mjs +62 -0
- package/.agents/skills/hyperframes-creative/templates/design-picker.html +1432 -0
- package/.agents/skills/hyperframes-keyframes/SKILL.md +237 -0
- package/.agents/skills/hyperframes-keyframes/agents/openai.yaml +4 -0
- package/.agents/skills/hyperframes-keyframes/references/keyframe-patterns.md +106 -0
- package/.agents/skills/motion-graphics/SKILL.md +172 -0
- package/.agents/skills/motion-graphics/agents/builder.md +40 -0
- package/.agents/skills/motion-graphics/agents/director.md +53 -0
- package/.agents/skills/motion-graphics/agents/finalize.md +17 -0
- package/.agents/skills/motion-graphics/catalog-map.md +40 -0
- package/.agents/skills/motion-graphics/categories/asset-fusion/module.md +37 -0
- package/.agents/skills/motion-graphics/categories/charts/module.md +21 -0
- package/.agents/skills/motion-graphics/categories/kinetic-type/module.md +19 -0
- package/.agents/skills/motion-graphics/categories/logo-reveal/module.md +17 -0
- package/.agents/skills/motion-graphics/categories/lower-thirds/module.md +16 -0
- package/.agents/skills/motion-graphics/categories/maps/bake-basemap.mjs +273 -0
- package/.agents/skills/motion-graphics/categories/maps/module.md +61 -0
- package/.agents/skills/motion-graphics/categories/news/module.md +56 -0
- package/.agents/skills/motion-graphics/categories/stat/module.md +21 -0
- package/.agents/skills/motion-graphics/categories/tweet/module.md +16 -0
- package/.agents/skills/motion-graphics/categories/webpage/module.md +21 -0
- package/.agents/skills/motion-graphics/grounding/PROTOCOL.md +64 -0
- package/.agents/skills/motion-graphics/grounding/locate.mjs +227 -0
- package/.agents/skills/motion-graphics/phases/source/guide.md +21 -0
- package/.agents/skills/motion-graphics/references/builder-contract.md +38 -0
- package/.agents/skills/motion-graphics/references/motion-vocabulary.md +43 -0
- package/.agents/skills/motion-graphics/references/shot-plan-ir.md +54 -0
- package/.agents/skills/motion-graphics/samples/asset-fusion/_ref-circle-highlight.html +306 -0
- package/.agents/skills/product-launch-video/SKILL.md +208 -0
- package/.agents/skills/product-launch-video/references/cut-catalog.md +220 -0
- package/.agents/skills/product-launch-video/references/motion-language.md +156 -0
- package/.agents/skills/product-launch-video/references/story-design.md +373 -0
- package/.agents/skills/product-launch-video/references/visual-design.md +126 -0
- package/.agents/skills/product-launch-video/scripts/assemble-index.mjs +570 -0
- package/.agents/skills/product-launch-video/scripts/audio.mjs +260 -0
- package/.agents/skills/product-launch-video/scripts/build-frame.mjs +536 -0
- package/.agents/skills/product-launch-video/scripts/captions.mjs +508 -0
- package/.agents/skills/product-launch-video/scripts/lib/assets.mjs +55 -0
- package/.agents/skills/product-launch-video/scripts/lib/dimensions.mjs +45 -0
- package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.mjs +36 -0
- package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.test.mjs +76 -0
- package/.agents/skills/product-launch-video/scripts/lib/storyboard.mjs +249 -0
- package/.agents/skills/product-launch-video/scripts/lib/tokens.mjs +204 -0
- package/.agents/skills/product-launch-video/scripts/lib/transition-registry.mjs +38 -0
- package/.agents/skills/product-launch-video/scripts/lib/transitions.json +71 -0
- package/.agents/skills/product-launch-video/scripts/stage-assets.mjs +39 -0
- package/.agents/skills/product-launch-video/scripts/transitions.mjs +327 -0
- package/.agents/skills/product-launch-video/sub-agents/frame-worker.md +75 -0
- package/.agents/skills/slideshow/SKILL.md +550 -0
- package/.agents/skills/slideshow/references/standalone-harness.md +1020 -0
- package/.agents/skills/talking-head-recut/NOTICE.md +39 -0
- package/.agents/skills/talking-head-recut/SKILL.md +1195 -0
- package/.agents/skills/talking-head-recut/assets/vendor/gsap.min.js +10 -0
- package/.agents/skills/talking-head-recut/references/DESIGN_INDEX.md +145 -0
- package/.agents/skills/talking-head-recut/references/frames/clean.html +92 -0
- package/.agents/skills/talking-head-recut/references/frames/hairline.html +171 -0
- package/.agents/skills/talking-head-recut/references/frames/polaroid.html +131 -0
- package/.agents/skills/talking-head-recut/references/layouts/overlay.html +164 -0
- package/.agents/skills/talking-head-recut/references/layouts/pip.html +143 -0
- package/.agents/skills/talking-head-recut/references/layouts/split.html +121 -0
- package/.agents/skills/talking-head-recut/references/layouts/stack.html +109 -0
- package/.agents/skills/talking-head-recut/references/styles/academic.html +172 -0
- package/.agents/skills/talking-head-recut/references/styles/audit.html +170 -0
- package/.agents/skills/talking-head-recut/references/styles/editorial.html +189 -0
- package/.agents/skills/talking-head-recut/references/styles/geom.html +181 -0
- package/.agents/skills/talking-head-recut/references/styles/minimal.html +130 -0
- package/.agents/skills/talking-head-recut/references/styles/spotlight.html +142 -0
- package/.agents/skills/talking-head-recut/references/styles/swiss.html +188 -0
- package/.agents/skills/talking-head-recut/references/styles/terminal.html +196 -0
- package/.agents/skills/talking-head-recut/references/styles/whiteboard.html +170 -0
- package/.agents/skills/talking-head-recut/references/styles/xhs.html +206 -0
- package/.agents/skills/vidfarm-media/SKILL.md +85 -0
- package/.agents/skills/vidfarm-media/references/tts.md +54 -0
- package/.agents/skills/vidfarm-media/scripts/audio.mjs +628 -0
- package/.agents/skills/vidfarm-media/scripts/wait-bgm.mjs +31 -0
- package/.agents/skills/website-to-video/SKILL.md +145 -0
- package/.agents/skills/website-to-video/assets/sfx/CREDITS.md +35 -0
- package/.agents/skills/website-to-video/assets/sfx/manifest.json +97 -0
- package/.agents/skills/website-to-video/references/beat-builder-guide.md +263 -0
- package/.agents/skills/website-to-video/references/capabilities.md +713 -0
- package/.agents/skills/website-to-video/references/step-0-capture.md +55 -0
- package/.agents/skills/website-to-video/references/step-1-design.md +333 -0
- package/.agents/skills/website-to-video/references/step-2-brief.md +178 -0
- package/.agents/skills/website-to-video/references/step-3-storyboard.md +572 -0
- package/.agents/skills/website-to-video/references/step-4-vo.md +225 -0
- package/.agents/skills/website-to-video/references/step-5-build.md +483 -0
- package/.agents/skills/website-to-video/references/step-6-validate.md +341 -0
- package/.agents/skills/website-to-video/scripts/w2h-verify.mjs +759 -0
- package/SKILL.director.md +60 -4
- package/SKILL.platform.md +7 -2
- package/demo/dist/app.css +1 -1
- package/demo/dist/app.js +485 -86
- package/dist/src/account-pages-legacy.js +9 -14
- package/dist/src/app.js +659 -159
- package/dist/src/cli.js +618 -17
- package/dist/src/composition-runtime.js +286 -6
- package/dist/src/devcli/composition-edit.js +176 -8
- package/dist/src/devcli/doctor.js +192 -0
- package/dist/src/devcli/hyperframes-cli.js +118 -0
- package/dist/src/devcli/skills.js +476 -0
- package/dist/src/devcli/stills.js +249 -0
- package/dist/src/devcli/transitions.js +205 -0
- package/dist/src/editor-chat.js +260 -4
- package/dist/src/frontend/template-editor-chat.js +6 -5
- package/dist/src/homepage.js +2 -48
- package/dist/src/hyperframes/composition.js +188 -7
- package/dist/src/services/composition-lint.js +199 -0
- package/dist/src/services/hyperframes.js +127 -28
- package/dist/src/services/serverless-records.js +7 -0
- package/dist/src/template-editor-shell.js +87 -48
- package/package.json +2 -1
- package/public/assets/page-runtime-client-app.js +31 -31
|
@@ -98,10 +98,16 @@ export function normalizeKenBurns(value) {
|
|
|
98
98
|
export const TRANSITION_PRESETS = [
|
|
99
99
|
"crossfade",
|
|
100
100
|
"fade-black",
|
|
101
|
+
"fade-white",
|
|
102
|
+
"flash",
|
|
103
|
+
"smoke",
|
|
104
|
+
"blur",
|
|
101
105
|
"slide-left",
|
|
102
106
|
"slide-right",
|
|
103
107
|
"slide-up",
|
|
104
108
|
"slide-down",
|
|
109
|
+
"whip-left",
|
|
110
|
+
"whip-right",
|
|
105
111
|
"wipe-left",
|
|
106
112
|
"wipe-right",
|
|
107
113
|
"wipe-up",
|
|
@@ -110,14 +116,49 @@ export const TRANSITION_PRESETS = [
|
|
|
110
116
|
"zoom-out",
|
|
111
117
|
"circle-open"
|
|
112
118
|
];
|
|
119
|
+
// Exit transitions: the clip animates AWAY over its last data-transition-out-
|
|
120
|
+
// duration seconds. Same declarative contract as the entrance presets; the
|
|
121
|
+
// keyframes omit the `from` state so the animation departs from the element's
|
|
122
|
+
// own inline styles, and the inline --vf-tr-out-delay var (clip duration minus
|
|
123
|
+
// out duration) positions the animation window at the clip's tail so the
|
|
124
|
+
// time-based scrub in the producer and preview runtimes needs no extra logic.
|
|
125
|
+
export const TRANSITION_OUT_PRESETS = [
|
|
126
|
+
"fade",
|
|
127
|
+
"fade-black",
|
|
128
|
+
"fade-white",
|
|
129
|
+
"flash",
|
|
130
|
+
"smoke",
|
|
131
|
+
"blur",
|
|
132
|
+
"slide-left",
|
|
133
|
+
"slide-right",
|
|
134
|
+
"slide-up",
|
|
135
|
+
"slide-down",
|
|
136
|
+
"wipe-left",
|
|
137
|
+
"wipe-right",
|
|
138
|
+
"wipe-up",
|
|
139
|
+
"wipe-down",
|
|
140
|
+
"zoom-in",
|
|
141
|
+
"zoom-out",
|
|
142
|
+
"circle-close"
|
|
143
|
+
];
|
|
113
144
|
export const TRANSITION_DEFAULT_DURATION = 0.5;
|
|
114
145
|
export const TRANSITION_MIN_DURATION = 0.1;
|
|
115
146
|
export const TRANSITION_MAX_DURATION = 2.5;
|
|
116
147
|
// Two butt-cut clips can drift by a few ms through timeline edits; treat ends
|
|
117
148
|
// within this window as adjacent when granting the outgoing clip's hold.
|
|
118
149
|
export const TRANSITION_ADJACENCY_EPSILON = 0.05;
|
|
119
|
-
|
|
120
|
-
|
|
150
|
+
// V2: entrance AND exit animations compose on one element via cascading custom
|
|
151
|
+
// properties (--vf-tr-in-name / --vf-tr-out-name) feeding a two-slot animation
|
|
152
|
+
// list — per-preset attribute selectors can't merge two animation-names, vars
|
|
153
|
+
// can. The [data-kenburns] combo rules below fix a V1 latent clash where Ken
|
|
154
|
+
// Burns and a transition on the same <img> fought over animation-name (equal
|
|
155
|
+
// specificity, last stylesheet won); the (0,2,0) combo selectors prepend the
|
|
156
|
+
// vf-kb animation to the list instead.
|
|
157
|
+
export const TRANSITION_STYLE_MARKER = "__VF_TRANSITIONS_V2__";
|
|
158
|
+
// The exact V1 block previous builds baked into stored compositions. Injectors
|
|
159
|
+
// string-replace this with the current TRANSITION_CSS so old drafts/publishes
|
|
160
|
+
// upgrade in place instead of accumulating duplicate style blocks.
|
|
161
|
+
export const LEGACY_TRANSITION_CSS_V1 = `/*__VF_TRANSITIONS_V1__*/
|
|
121
162
|
@keyframes vf-tr-crossfade { from { opacity: 0; } }
|
|
122
163
|
@keyframes vf-tr-fade-black { 0% { opacity: 0; filter: brightness(0); } 35% { opacity: 1; filter: brightness(0); } }
|
|
123
164
|
@keyframes vf-tr-slide-left { from { translate: 100% 0; } }
|
|
@@ -151,12 +192,119 @@ export const TRANSITION_CSS = `/*${TRANSITION_STYLE_MARKER}*/
|
|
|
151
192
|
[data-transition="zoom-out"] { animation-name: vf-tr-zoom-out; }
|
|
152
193
|
[data-transition="circle-open"] { animation-name: vf-tr-circle-open; }
|
|
153
194
|
`;
|
|
195
|
+
export const TRANSITION_CSS = `/*${TRANSITION_STYLE_MARKER}*/
|
|
196
|
+
@keyframes vf-tr-crossfade { from { opacity: 0; } }
|
|
197
|
+
@keyframes vf-tr-fade-black { 0% { opacity: 0; filter: brightness(0); } 35% { opacity: 1; filter: brightness(0); } }
|
|
198
|
+
@keyframes vf-tr-fade-white { 0% { opacity: 0; filter: saturate(0.55) brightness(3); } 45% { opacity: 1; filter: saturate(0.7) brightness(2.1); } }
|
|
199
|
+
@keyframes vf-tr-flash { 0% { filter: saturate(0.3) brightness(5); } 55% { filter: saturate(0.9) brightness(1.6); } }
|
|
200
|
+
@keyframes vf-tr-smoke { 0% { opacity: 0; filter: blur(26px) saturate(0.65) brightness(1.55); } 55% { opacity: 1; } }
|
|
201
|
+
@keyframes vf-tr-blur { from { opacity: 0; filter: blur(16px); } }
|
|
202
|
+
@keyframes vf-tr-slide-left { from { translate: 100% 0; } }
|
|
203
|
+
@keyframes vf-tr-slide-right { from { translate: -100% 0; } }
|
|
204
|
+
@keyframes vf-tr-slide-up { from { translate: 0 100%; } }
|
|
205
|
+
@keyframes vf-tr-slide-down { from { translate: 0 -100%; } }
|
|
206
|
+
@keyframes vf-tr-whip-left { 0% { translate: 110% 0; filter: blur(14px); } 60% { filter: blur(5px); } }
|
|
207
|
+
@keyframes vf-tr-whip-right { 0% { translate: -110% 0; filter: blur(14px); } 60% { filter: blur(5px); } }
|
|
208
|
+
@keyframes vf-tr-wipe-left { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 0); } }
|
|
209
|
+
@keyframes vf-tr-wipe-right { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
|
|
210
|
+
@keyframes vf-tr-wipe-up { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
|
|
211
|
+
@keyframes vf-tr-wipe-down { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
|
|
212
|
+
@keyframes vf-tr-zoom-in { from { opacity: 0; scale: 1.18; } }
|
|
213
|
+
@keyframes vf-tr-zoom-out { from { opacity: 0; scale: 0.82; } }
|
|
214
|
+
@keyframes vf-tr-circle-open { from { clip-path: circle(0% at 50% 50%); } to { clip-path: circle(75% at 50% 50%); } }
|
|
215
|
+
@keyframes vf-tr-out-fade { to { opacity: 0; } }
|
|
216
|
+
@keyframes vf-tr-out-fade-black { to { filter: brightness(0); } }
|
|
217
|
+
@keyframes vf-tr-out-fade-white { to { filter: saturate(0.35) brightness(6); } }
|
|
218
|
+
@keyframes vf-tr-out-flash { 65% { filter: brightness(1); } 100% { filter: saturate(0.3) brightness(5); } }
|
|
219
|
+
@keyframes vf-tr-out-smoke { to { opacity: 0; filter: blur(24px) saturate(0.7) brightness(1.5); } }
|
|
220
|
+
@keyframes vf-tr-out-blur { to { opacity: 0; filter: blur(16px); } }
|
|
221
|
+
@keyframes vf-tr-out-slide-left { to { translate: -100% 0; } }
|
|
222
|
+
@keyframes vf-tr-out-slide-right { to { translate: 100% 0; } }
|
|
223
|
+
@keyframes vf-tr-out-slide-up { to { translate: 0 -100%; } }
|
|
224
|
+
@keyframes vf-tr-out-slide-down { to { translate: 0 100%; } }
|
|
225
|
+
@keyframes vf-tr-out-wipe-left { from { clip-path: inset(0 0 0 0); } to { clip-path: inset(0 100% 0 0); } }
|
|
226
|
+
@keyframes vf-tr-out-wipe-right { from { clip-path: inset(0 0 0 0); } to { clip-path: inset(0 0 0 100%); } }
|
|
227
|
+
@keyframes vf-tr-out-wipe-up { from { clip-path: inset(0 0 0 0); } to { clip-path: inset(0 0 100% 0); } }
|
|
228
|
+
@keyframes vf-tr-out-wipe-down { from { clip-path: inset(0 0 0 0); } to { clip-path: inset(100% 0 0 0); } }
|
|
229
|
+
@keyframes vf-tr-out-zoom-in { to { opacity: 0; scale: 1.18; } }
|
|
230
|
+
@keyframes vf-tr-out-zoom-out { to { opacity: 0; scale: 0.82; } }
|
|
231
|
+
@keyframes vf-tr-out-circle-close { from { clip-path: circle(75% at 50% 50%); } to { clip-path: circle(0% at 50% 50%); } }
|
|
232
|
+
[data-transition], [data-transition-out] {
|
|
233
|
+
animation-name: var(--vf-tr-in-name, none), var(--vf-tr-out-name, none);
|
|
234
|
+
animation-duration: var(--vf-tr-dur, 0.5s), var(--vf-tr-out-dur, 0.5s);
|
|
235
|
+
animation-delay: 0s, var(--vf-tr-out-delay, 0s);
|
|
236
|
+
animation-timing-function: var(--vf-tr-ease, ease-in-out), var(--vf-tr-out-ease, ease-in-out);
|
|
237
|
+
animation-fill-mode: both, both;
|
|
238
|
+
animation-play-state: paused, paused;
|
|
239
|
+
}
|
|
240
|
+
[data-kenburns][data-transition], [data-kenburns][data-transition-out] {
|
|
241
|
+
animation-name: var(--vf-kb-name, none), var(--vf-tr-in-name, none), var(--vf-tr-out-name, none);
|
|
242
|
+
animation-duration: var(--vf-kb-dur, 5s), var(--vf-tr-dur, 0.5s), var(--vf-tr-out-dur, 0.5s);
|
|
243
|
+
animation-delay: 0s, 0s, var(--vf-tr-out-delay, 0s);
|
|
244
|
+
animation-timing-function: var(--vf-kb-ease, linear), var(--vf-tr-ease, ease-in-out), var(--vf-tr-out-ease, ease-in-out);
|
|
245
|
+
animation-fill-mode: both, both, both;
|
|
246
|
+
animation-play-state: paused, paused, paused;
|
|
247
|
+
}
|
|
248
|
+
[data-kenburns="zoom-in"] { --vf-kb-name: vf-kb-zoom-in; }
|
|
249
|
+
[data-kenburns="zoom-out"] { --vf-kb-name: vf-kb-zoom-out; }
|
|
250
|
+
[data-kenburns="pan-left"] { --vf-kb-name: vf-kb-pan-left; }
|
|
251
|
+
[data-kenburns="pan-right"] { --vf-kb-name: vf-kb-pan-right; }
|
|
252
|
+
[data-kenburns="pan-up"] { --vf-kb-name: vf-kb-pan-up; }
|
|
253
|
+
[data-kenburns="pan-down"] { --vf-kb-name: vf-kb-pan-down; }
|
|
254
|
+
[data-kenburns="zoom-in-left"] { --vf-kb-name: vf-kb-zoom-in-left; }
|
|
255
|
+
[data-kenburns="zoom-in-right"] { --vf-kb-name: vf-kb-zoom-in-right; }
|
|
256
|
+
[data-transition="crossfade"] { --vf-tr-in-name: vf-tr-crossfade; }
|
|
257
|
+
[data-transition="fade-black"] { --vf-tr-in-name: vf-tr-fade-black; }
|
|
258
|
+
[data-transition="fade-white"] { --vf-tr-in-name: vf-tr-fade-white; }
|
|
259
|
+
[data-transition="flash"] { --vf-tr-in-name: vf-tr-flash; --vf-tr-ease: cubic-bezier(0.3, 0, 0.55, 1); }
|
|
260
|
+
[data-transition="smoke"] { --vf-tr-in-name: vf-tr-smoke; --vf-tr-ease: cubic-bezier(0.25, 0.4, 0.3, 1); }
|
|
261
|
+
[data-transition="blur"] { --vf-tr-in-name: vf-tr-blur; }
|
|
262
|
+
[data-transition="slide-left"] { --vf-tr-in-name: vf-tr-slide-left; --vf-tr-ease: cubic-bezier(0.22, 1, 0.36, 1); }
|
|
263
|
+
[data-transition="slide-right"] { --vf-tr-in-name: vf-tr-slide-right; --vf-tr-ease: cubic-bezier(0.22, 1, 0.36, 1); }
|
|
264
|
+
[data-transition="slide-up"] { --vf-tr-in-name: vf-tr-slide-up; --vf-tr-ease: cubic-bezier(0.22, 1, 0.36, 1); }
|
|
265
|
+
[data-transition="slide-down"] { --vf-tr-in-name: vf-tr-slide-down; --vf-tr-ease: cubic-bezier(0.22, 1, 0.36, 1); }
|
|
266
|
+
[data-transition="whip-left"] { --vf-tr-in-name: vf-tr-whip-left; --vf-tr-ease: cubic-bezier(0.16, 1, 0.3, 1); }
|
|
267
|
+
[data-transition="whip-right"] { --vf-tr-in-name: vf-tr-whip-right; --vf-tr-ease: cubic-bezier(0.16, 1, 0.3, 1); }
|
|
268
|
+
[data-transition="wipe-left"] { --vf-tr-in-name: vf-tr-wipe-left; --vf-tr-ease: cubic-bezier(0.45, 0.05, 0.35, 0.95); }
|
|
269
|
+
[data-transition="wipe-right"] { --vf-tr-in-name: vf-tr-wipe-right; --vf-tr-ease: cubic-bezier(0.45, 0.05, 0.35, 0.95); }
|
|
270
|
+
[data-transition="wipe-up"] { --vf-tr-in-name: vf-tr-wipe-up; --vf-tr-ease: cubic-bezier(0.45, 0.05, 0.35, 0.95); }
|
|
271
|
+
[data-transition="wipe-down"] { --vf-tr-in-name: vf-tr-wipe-down; --vf-tr-ease: cubic-bezier(0.45, 0.05, 0.35, 0.95); }
|
|
272
|
+
[data-transition="zoom-in"] { --vf-tr-in-name: vf-tr-zoom-in; --vf-tr-ease: cubic-bezier(0.16, 1, 0.3, 1); }
|
|
273
|
+
[data-transition="zoom-out"] { --vf-tr-in-name: vf-tr-zoom-out; --vf-tr-ease: cubic-bezier(0.16, 1, 0.3, 1); }
|
|
274
|
+
[data-transition="circle-open"] { --vf-tr-in-name: vf-tr-circle-open; --vf-tr-ease: cubic-bezier(0.3, 0.6, 0.3, 1); }
|
|
275
|
+
[data-transition-out="fade"] { --vf-tr-out-name: vf-tr-out-fade; }
|
|
276
|
+
[data-transition-out="fade-black"] { --vf-tr-out-name: vf-tr-out-fade-black; }
|
|
277
|
+
[data-transition-out="fade-white"] { --vf-tr-out-name: vf-tr-out-fade-white; }
|
|
278
|
+
[data-transition-out="flash"] { --vf-tr-out-name: vf-tr-out-flash; --vf-tr-out-ease: cubic-bezier(0.45, 0, 0.7, 0.4); }
|
|
279
|
+
[data-transition-out="smoke"] { --vf-tr-out-name: vf-tr-out-smoke; --vf-tr-out-ease: cubic-bezier(0.7, 0, 0.75, 0.6); }
|
|
280
|
+
[data-transition-out="blur"] { --vf-tr-out-name: vf-tr-out-blur; }
|
|
281
|
+
[data-transition-out="slide-left"] { --vf-tr-out-name: vf-tr-out-slide-left; --vf-tr-out-ease: cubic-bezier(0.55, 0.06, 0.68, 0.19); }
|
|
282
|
+
[data-transition-out="slide-right"] { --vf-tr-out-name: vf-tr-out-slide-right; --vf-tr-out-ease: cubic-bezier(0.55, 0.06, 0.68, 0.19); }
|
|
283
|
+
[data-transition-out="slide-up"] { --vf-tr-out-name: vf-tr-out-slide-up; --vf-tr-out-ease: cubic-bezier(0.55, 0.06, 0.68, 0.19); }
|
|
284
|
+
[data-transition-out="slide-down"] { --vf-tr-out-name: vf-tr-out-slide-down; --vf-tr-out-ease: cubic-bezier(0.55, 0.06, 0.68, 0.19); }
|
|
285
|
+
[data-transition-out="wipe-left"] { --vf-tr-out-name: vf-tr-out-wipe-left; --vf-tr-out-ease: cubic-bezier(0.45, 0.05, 0.35, 0.95); }
|
|
286
|
+
[data-transition-out="wipe-right"] { --vf-tr-out-name: vf-tr-out-wipe-right; --vf-tr-out-ease: cubic-bezier(0.45, 0.05, 0.35, 0.95); }
|
|
287
|
+
[data-transition-out="wipe-up"] { --vf-tr-out-name: vf-tr-out-wipe-up; --vf-tr-out-ease: cubic-bezier(0.45, 0.05, 0.35, 0.95); }
|
|
288
|
+
[data-transition-out="wipe-down"] { --vf-tr-out-name: vf-tr-out-wipe-down; --vf-tr-out-ease: cubic-bezier(0.45, 0.05, 0.35, 0.95); }
|
|
289
|
+
[data-transition-out="zoom-in"] { --vf-tr-out-name: vf-tr-out-zoom-in; --vf-tr-out-ease: cubic-bezier(0.5, 0, 0.75, 0.4); }
|
|
290
|
+
[data-transition-out="zoom-out"] { --vf-tr-out-name: vf-tr-out-zoom-out; --vf-tr-out-ease: cubic-bezier(0.5, 0, 0.75, 0.4); }
|
|
291
|
+
[data-transition-out="circle-close"] { --vf-tr-out-name: vf-tr-out-circle-close; --vf-tr-out-ease: cubic-bezier(0.6, 0, 0.7, 0.4); }
|
|
292
|
+
`;
|
|
154
293
|
export function clampTransitionDuration(value) {
|
|
155
294
|
const next = Number(value);
|
|
156
295
|
if (!Number.isFinite(next) || next <= 0)
|
|
157
296
|
return TRANSITION_DEFAULT_DURATION;
|
|
158
297
|
return Math.max(TRANSITION_MIN_DURATION, Math.min(TRANSITION_MAX_DURATION, next));
|
|
159
298
|
}
|
|
299
|
+
// Seconds into the clip at which its exit animation must start so it finishes
|
|
300
|
+
// exactly at the clip's end. Written as the inline --vf-tr-out-delay var.
|
|
301
|
+
export function transitionOutDelaySeconds(layerDurationSeconds, outDurationSeconds) {
|
|
302
|
+
const layerDuration = Number(layerDurationSeconds);
|
|
303
|
+
const outDuration = Number(outDurationSeconds);
|
|
304
|
+
if (!Number.isFinite(layerDuration) || !Number.isFinite(outDuration))
|
|
305
|
+
return 0;
|
|
306
|
+
return Math.max(0, Number((layerDuration - outDuration).toFixed(3)));
|
|
307
|
+
}
|
|
160
308
|
export function normalizeTransition(value) {
|
|
161
309
|
if (!value)
|
|
162
310
|
return null;
|
|
@@ -168,6 +316,28 @@ export function normalizeTransition(value) {
|
|
|
168
316
|
duration: raw.duration !== undefined ? clampTransitionDuration(raw.duration) : undefined
|
|
169
317
|
};
|
|
170
318
|
}
|
|
319
|
+
export function normalizeTransitionOut(value) {
|
|
320
|
+
if (!value)
|
|
321
|
+
return null;
|
|
322
|
+
const raw = typeof value === "string" ? { preset: value } : value;
|
|
323
|
+
if (!TRANSITION_OUT_PRESETS.includes(raw.preset))
|
|
324
|
+
return null;
|
|
325
|
+
return {
|
|
326
|
+
preset: raw.preset,
|
|
327
|
+
duration: raw.duration !== undefined ? clampTransitionDuration(raw.duration) : undefined
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
// Upgrades stored composition HTML that still carries the V1 transition
|
|
331
|
+
// stylesheet: exact-replaces the legacy block with the current one. If the V1
|
|
332
|
+
// marker is present but the block has drifted, callers' normal marker-guarded
|
|
333
|
+
// injection appends the V2 block AFTER it, which also wins (equal-specificity
|
|
334
|
+
// rules, later source order) — this replace just avoids duplicate blocks in
|
|
335
|
+
// the common case.
|
|
336
|
+
export function upgradeLegacyTransitionCss(html) {
|
|
337
|
+
if (!html || html.includes(TRANSITION_STYLE_MARKER) || !html.includes("__VF_TRANSITIONS_V1__"))
|
|
338
|
+
return html;
|
|
339
|
+
return html.split(LEGACY_TRANSITION_CSS_V1).join(TRANSITION_CSS);
|
|
340
|
+
}
|
|
171
341
|
// ---------------------------------------------------------------------------
|
|
172
342
|
// Animated captions. Same declarative contract as Ken Burns: the caption layer
|
|
173
343
|
// <div> (the element that owns data-start/data-duration) carries
|
|
@@ -405,12 +575,12 @@ function renderLayer(layer) {
|
|
|
405
575
|
// data-start) and it plays across exactly the clip's span.
|
|
406
576
|
const vars = kenBurnsInlineVars(kenBurns, positiveNumber(layer.duration, 0));
|
|
407
577
|
const kbStyle = vars ? `${style};${vars}` : style;
|
|
408
|
-
return `<img ${attrs} data-kenburns="${escapeAttr(kenBurns.preset)}" src="${escapeAttr(layer.src || "")}" alt="" style="${escapeAttr(kbStyle)}" />`;
|
|
578
|
+
return `<img class="clip" ${attrs} data-kenburns="${escapeAttr(kenBurns.preset)}" src="${escapeAttr(layer.src || "")}" alt="" style="${escapeAttr(kbStyle)}" />`;
|
|
409
579
|
}
|
|
410
|
-
return `<img ${attrs} src="${escapeAttr(layer.src || "")}" alt="" style="${escapeAttr(style)}" />`;
|
|
580
|
+
return `<img class="clip" ${attrs} src="${escapeAttr(layer.src || "")}" alt="" style="${escapeAttr(style)}" />`;
|
|
411
581
|
}
|
|
412
582
|
if (layer.kind === "html") {
|
|
413
|
-
return `<div ${attrs} style="${escapeAttr(style)}">${layer.html || ""}</div>`;
|
|
583
|
+
return `<div class="clip" ${attrs} style="${escapeAttr(style)}">${layer.html || ""}</div>`;
|
|
414
584
|
}
|
|
415
585
|
const text = layer.text ?? layer.label ?? "";
|
|
416
586
|
const inlineStyle = textInlineCss(layer.textBackgroundStyle || "plain", layer.color || "#ffffff", layer.background || "#000000", layer.fontFamily || "TikTok Sans", positiveInteger(layer.fontWeight, 700));
|
|
@@ -435,10 +605,10 @@ function renderLayer(layer) {
|
|
|
435
605
|
const upper = captionConfig.uppercase ? ";text-transform:uppercase" : "";
|
|
436
606
|
const divStyle = `${style}${vars ? `;${vars}` : ""}${upper};overflow:visible`;
|
|
437
607
|
const captionAttrs = `${attrs} data-caption-animation="${escapeAttr(captionConfig.animation)}"${captionConfig.uppercase ? " data-caption-uppercase=\"1\"" : ""}`;
|
|
438
|
-
return `<div ${captionAttrs} style="${escapeAttr(divStyle)}"><span data-vf-text-lines="true" style="${escapeAttr(linesStyle)}"><span data-vf-text-inline="true" style="${escapeAttr(inlineStyle)}">${captionWordSpansHtml(words)}</span></span></div>`;
|
|
608
|
+
return `<div class="clip" ${captionAttrs} style="${escapeAttr(divStyle)}"><span data-vf-text-lines="true" style="${escapeAttr(linesStyle)}"><span data-vf-text-inline="true" style="${escapeAttr(inlineStyle)}">${captionWordSpansHtml(words)}</span></span></div>`;
|
|
439
609
|
}
|
|
440
610
|
}
|
|
441
|
-
return `<div ${attrs} style="${escapeAttr(style)}"><span data-vf-text-lines="true" style="${escapeAttr(linesStyle)}"><span data-vf-text-inline="true" style="${escapeAttr(inlineStyle)}">${escapeHtml(text)}</span></span></div>`;
|
|
611
|
+
return `<div class="clip" ${attrs} style="${escapeAttr(style)}"><span data-vf-text-lines="true" style="${escapeAttr(linesStyle)}"><span data-vf-text-inline="true" style="${escapeAttr(inlineStyle)}">${escapeHtml(text)}</span></span></div>`;
|
|
442
612
|
}
|
|
443
613
|
// Serializes word windows into the <span data-cap-word> run that the caption
|
|
444
614
|
// stylesheet animates. Delay/duration are the word window relative to the
|
|
@@ -476,6 +646,10 @@ function timedAttrs(layer) {
|
|
|
476
646
|
if (transition) {
|
|
477
647
|
attrs.push(`data-transition="${escapeAttr(transition.preset)}"`, `data-transition-duration="${num(clampTransitionDuration(transition.duration ?? TRANSITION_DEFAULT_DURATION))}"`);
|
|
478
648
|
}
|
|
649
|
+
const transitionOut = normalizeTransitionOut(layer.transitionOut);
|
|
650
|
+
if (transitionOut) {
|
|
651
|
+
attrs.push(`data-transition-out="${escapeAttr(transitionOut.preset)}"`, `data-transition-out-duration="${num(clampTransitionDuration(transitionOut.duration ?? TRANSITION_DEFAULT_DURATION))}"`);
|
|
652
|
+
}
|
|
479
653
|
}
|
|
480
654
|
if (["caption", "text", "shape", "html"].includes(layer.kind)) {
|
|
481
655
|
attrs.push(`data-text-background-style="${escapeAttr(layer.textBackgroundStyle || "plain")}"`, `data-text-background-color="${escapeAttr(layer.background || "#000000")}"`, `data-font-family="${escapeAttr(layer.fontFamily || "TikTok Sans")}"`);
|
|
@@ -504,6 +678,13 @@ function layerStyle(layer) {
|
|
|
504
678
|
if (transition) {
|
|
505
679
|
styles.push(`--vf-tr-dur:${num(clampTransitionDuration(transition.duration ?? TRANSITION_DEFAULT_DURATION))}s`);
|
|
506
680
|
}
|
|
681
|
+
// Exit transitions additionally need the delay var so the animation window
|
|
682
|
+
// sits at the clip's tail (duration − out duration).
|
|
683
|
+
const transitionOut = normalizeTransitionOut(layer.transitionOut);
|
|
684
|
+
if (transitionOut) {
|
|
685
|
+
const outDur = clampTransitionDuration(transitionOut.duration ?? TRANSITION_DEFAULT_DURATION);
|
|
686
|
+
styles.push(`--vf-tr-out-dur:${num(outDur)}s`, `--vf-tr-out-delay:${num(transitionOutDelaySeconds(positiveNumber(layer.duration, 0), outDur))}s`);
|
|
687
|
+
}
|
|
507
688
|
}
|
|
508
689
|
if (["caption", "text", "shape", "html"].includes(layer.kind)) {
|
|
509
690
|
const fontFamily = layer.fontFamily || "TikTok Sans";
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// Static composition validation shared by the /editor chat copilot
|
|
2
|
+
// (replace_composition_html preflight, both the in-process and Lambda copies),
|
|
3
|
+
// the devcli (`vidfarm lint`), and publish preflights. Mirrors the checks the
|
|
4
|
+
// HyperFrames CLI's `lint` runs against raw projects, adapted to vidfarm's
|
|
5
|
+
// composition vocabulary (data-vf-* proxies, transition holds, caption spans).
|
|
6
|
+
import { parseHTML } from "linkedom";
|
|
7
|
+
import { CAPTION_ANIMATIONS, KEN_BURNS_PRESETS, TRANSITION_OUT_PRESETS, TRANSITION_PRESETS } from "../hyperframes/composition.js";
|
|
8
|
+
const OVERLAP_EPSILON = 0.011;
|
|
9
|
+
function parseNumberAttr(value) {
|
|
10
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const parsed = Number(value);
|
|
14
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
15
|
+
}
|
|
16
|
+
function layerKeyFor(element) {
|
|
17
|
+
return (element.getAttribute("data-hf-id") ||
|
|
18
|
+
element.getAttribute("id") ||
|
|
19
|
+
element.getAttribute("data-hf-slug") ||
|
|
20
|
+
`<${element.tagName.toLowerCase()}>`);
|
|
21
|
+
}
|
|
22
|
+
export function lintCompositionHtml(html) {
|
|
23
|
+
const issues = [];
|
|
24
|
+
const push = (level, code, message, layer) => {
|
|
25
|
+
issues.push({ level, code, message, ...(layer ? { layer } : {}) });
|
|
26
|
+
};
|
|
27
|
+
const trimmed = typeof html === "string" ? html.trim() : "";
|
|
28
|
+
if (!trimmed) {
|
|
29
|
+
push("error", "empty_document", "Composition HTML is empty.");
|
|
30
|
+
return finalize(issues);
|
|
31
|
+
}
|
|
32
|
+
let document;
|
|
33
|
+
try {
|
|
34
|
+
({ document } = parseHTML(trimmed));
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
push("error", "unparseable_document", `Composition HTML could not be parsed: ${error instanceof Error ? error.message : String(error)}`);
|
|
38
|
+
return finalize(issues);
|
|
39
|
+
}
|
|
40
|
+
const root = document.querySelector("[data-composition-id]");
|
|
41
|
+
if (!root) {
|
|
42
|
+
push("error", "missing_composition_root", "No element carries data-composition-id — the composition root is required.");
|
|
43
|
+
return finalize(issues);
|
|
44
|
+
}
|
|
45
|
+
const width = parseNumberAttr(root.getAttribute("data-width"));
|
|
46
|
+
const height = parseNumberAttr(root.getAttribute("data-height"));
|
|
47
|
+
if (width === null || height === null) {
|
|
48
|
+
push("warning", "missing_canvas_size", "Composition root should declare numeric data-width and data-height (px).");
|
|
49
|
+
}
|
|
50
|
+
else if (width <= 0 || height <= 0) {
|
|
51
|
+
push("error", "invalid_canvas", `Composition root data-width/data-height must be positive (got ${width}x${height}).`);
|
|
52
|
+
}
|
|
53
|
+
const fpsRaw = root.getAttribute("data-fps");
|
|
54
|
+
if (fpsRaw !== null && (parseNumberAttr(fpsRaw) === null || parseNumberAttr(fpsRaw) <= 0)) {
|
|
55
|
+
push("warning", "invalid_fps", `Composition root data-fps is not a positive number (got "${fpsRaw}").`);
|
|
56
|
+
}
|
|
57
|
+
const clips = Array.from(document.querySelectorAll("[data-start]")).filter((el) => el !== root);
|
|
58
|
+
const rootDuration = parseNumberAttr(root.getAttribute("data-duration"));
|
|
59
|
+
if (rootDuration === null) {
|
|
60
|
+
if (clips.length === 0) {
|
|
61
|
+
push("error", "missing_root_duration", "Composition root has no data-duration and no timed clips to infer one from.");
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
push("warning", "missing_root_duration", "Composition root has no data-duration; the runtime will infer it from the latest clip end. Declare it explicitly for deterministic renders.");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (rootDuration <= 0) {
|
|
68
|
+
push("error", "invalid_root_duration", `Composition root data-duration must be positive (got ${rootDuration}).`);
|
|
69
|
+
}
|
|
70
|
+
if (clips.length === 0) {
|
|
71
|
+
push("warning", "no_clips", "Composition has no timed clips ([data-start] elements).");
|
|
72
|
+
}
|
|
73
|
+
const timings = [];
|
|
74
|
+
const seenKeys = new Map();
|
|
75
|
+
for (const clip of clips) {
|
|
76
|
+
const key = layerKeyFor(clip);
|
|
77
|
+
const tag = clip.tagName.toLowerCase();
|
|
78
|
+
const isMedia = tag === "video" || tag === "audio";
|
|
79
|
+
const isProxy = clip.hasAttribute("data-vf-timeline-proxy");
|
|
80
|
+
const explicitKey = clip.getAttribute("data-hf-id") || clip.getAttribute("id");
|
|
81
|
+
if (explicitKey) {
|
|
82
|
+
seenKeys.set(explicitKey, (seenKeys.get(explicitKey) ?? 0) + 1);
|
|
83
|
+
}
|
|
84
|
+
const start = parseNumberAttr(clip.getAttribute("data-start"));
|
|
85
|
+
if (start === null || start < 0) {
|
|
86
|
+
push("error", "invalid_clip_timing", `Clip has a non-numeric or negative data-start ("${clip.getAttribute("data-start")}").`, key);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const duration = parseNumberAttr(clip.getAttribute("data-duration"));
|
|
90
|
+
if (duration === null) {
|
|
91
|
+
if (isMedia) {
|
|
92
|
+
push("warning", "media_missing_duration", "Media clip has no data-duration; it will fall back to the source's intrinsic length. Declare it for predictable trims.", key);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
push("error", "missing_clip_duration", "Non-media clip requires a positive data-duration.", key);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else if (duration <= 0) {
|
|
99
|
+
push("error", "invalid_clip_duration", `Clip data-duration must be positive (got ${duration}).`, key);
|
|
100
|
+
}
|
|
101
|
+
const trackRaw = clip.getAttribute("data-track-index");
|
|
102
|
+
const track = parseNumberAttr(trackRaw);
|
|
103
|
+
if (trackRaw === null || track === null || !Number.isInteger(track) || track < 0) {
|
|
104
|
+
push("warning", "missing_track_index", `Clip should declare an integer data-track-index >= 0 (got "${trackRaw ?? "<absent>"}").`, key);
|
|
105
|
+
}
|
|
106
|
+
// Nested clips fight parent visibility toggling and are unregistered in
|
|
107
|
+
// the upstream HyperFrames runtime (clips must be direct children).
|
|
108
|
+
let ancestor = clip.parentElement;
|
|
109
|
+
while (ancestor && ancestor !== root) {
|
|
110
|
+
if (ancestor.hasAttribute("data-start")) {
|
|
111
|
+
push("warning", "nested_clip", "Clip is nested inside another timed clip; move clips to the composition root.", key);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
ancestor = ancestor.parentElement;
|
|
115
|
+
}
|
|
116
|
+
if (isMedia && clip.parentElement && clip.parentElement !== root) {
|
|
117
|
+
push("warning", "nested_media", "video/audio elements should be direct children of the composition root — nested media renders blank/black under the HyperFrames runtime.", key);
|
|
118
|
+
}
|
|
119
|
+
if ((tag === "video" || tag === "img" || tag === "audio") && !isProxy) {
|
|
120
|
+
const src = clip.getAttribute("src") || clip.getAttribute("data-src");
|
|
121
|
+
const hasSourceChild = Boolean(clip.querySelector("source[src]"));
|
|
122
|
+
if (!src && !hasSourceChild) {
|
|
123
|
+
push("error", "media_missing_src", `<${tag}> clip has no src / data-src.`, key);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const kenBurns = clip.getAttribute("data-kenburns") ?? clip.querySelector("img[data-kenburns]")?.getAttribute("data-kenburns");
|
|
127
|
+
if (kenBurns && kenBurns !== "none" && !KEN_BURNS_PRESETS.includes(kenBurns)) {
|
|
128
|
+
push("error", "unknown_ken_burns", `Unknown data-kenburns preset "${kenBurns}".`, key);
|
|
129
|
+
}
|
|
130
|
+
const transition = clip.getAttribute("data-transition");
|
|
131
|
+
if (transition && transition !== "none" && !TRANSITION_PRESETS.includes(transition)) {
|
|
132
|
+
push("error", "unknown_transition", `Unknown data-transition preset "${transition}".`, key);
|
|
133
|
+
}
|
|
134
|
+
const transitionOut = clip.getAttribute("data-transition-out");
|
|
135
|
+
if (transitionOut && transitionOut !== "none" && !TRANSITION_OUT_PRESETS.includes(transitionOut)) {
|
|
136
|
+
push("error", "unknown_transition_out", `Unknown data-transition-out preset "${transitionOut}".`, key);
|
|
137
|
+
}
|
|
138
|
+
const captionAnimation = clip.getAttribute("data-caption-animation");
|
|
139
|
+
if (captionAnimation && captionAnimation !== "none" && !CAPTION_ANIMATIONS.includes(captionAnimation)) {
|
|
140
|
+
push("error", "unknown_caption_animation", `Unknown data-caption-animation preset "${captionAnimation}".`, key);
|
|
141
|
+
}
|
|
142
|
+
const effectiveDuration = duration !== null && duration > 0 ? duration : 0;
|
|
143
|
+
timings.push({
|
|
144
|
+
element: clip,
|
|
145
|
+
key,
|
|
146
|
+
start,
|
|
147
|
+
end: start + effectiveDuration,
|
|
148
|
+
track: track !== null && Number.isInteger(track) && track >= 0 ? track : null,
|
|
149
|
+
hasTransitionHold: clip.hasAttribute("data-transition-hold")
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
for (const [key, count] of seenKeys) {
|
|
153
|
+
if (count > 1) {
|
|
154
|
+
push("warning", "duplicate_layer_id", `Layer id "${key}" appears ${count} times; layer keys must be unique for editor/chat targeting.`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Same-track temporal overlap. Materialized transition holds
|
|
158
|
+
// (data-transition-hold) legitimately overlap their successor.
|
|
159
|
+
const byTrack = new Map();
|
|
160
|
+
for (const timing of timings) {
|
|
161
|
+
if (timing.track === null || timing.end <= timing.start) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const bucket = byTrack.get(timing.track) ?? [];
|
|
165
|
+
bucket.push(timing);
|
|
166
|
+
byTrack.set(timing.track, bucket);
|
|
167
|
+
}
|
|
168
|
+
for (const [track, bucket] of byTrack) {
|
|
169
|
+
bucket.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
170
|
+
for (let i = 1; i < bucket.length; i += 1) {
|
|
171
|
+
const prev = bucket[i - 1];
|
|
172
|
+
const current = bucket[i];
|
|
173
|
+
if (current.start < prev.end - OVERLAP_EPSILON && !prev.hasTransitionHold && !current.hasTransitionHold) {
|
|
174
|
+
push("error", "track_overlap", `Clips "${prev.key}" and "${current.key}" overlap on track ${track} (${prev.start}-${prev.end}s vs ${current.start}s start). Same-track clips must not overlap.`, current.key);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const scripts = document.querySelectorAll("script");
|
|
179
|
+
if (scripts.length > 0) {
|
|
180
|
+
push("warning", "scripts_stripped_on_save", `Composition contains ${scripts.length} <script> tag(s). Scripts survive local serve/disk renders, but every cloud/web editor save strips them (stored-XSS defense) — script-driven animation will be lost there. Prefer the declarative preset vocabulary (data-kenburns, data-transition, data-caption-animation) for compositions that round-trip through the web editor.`);
|
|
181
|
+
}
|
|
182
|
+
return finalize(issues);
|
|
183
|
+
}
|
|
184
|
+
function finalize(issues) {
|
|
185
|
+
const errors = issues.filter((issue) => issue.level === "error");
|
|
186
|
+
const warnings = issues.filter((issue) => issue.level === "warning");
|
|
187
|
+
return { ok: errors.length === 0, errors, warnings };
|
|
188
|
+
}
|
|
189
|
+
export function formatCompositionLintIssues(result) {
|
|
190
|
+
const lines = [];
|
|
191
|
+
for (const issue of result.errors) {
|
|
192
|
+
lines.push(`error ${issue.code}${issue.layer ? ` [${issue.layer}]` : ""}: ${issue.message}`);
|
|
193
|
+
}
|
|
194
|
+
for (const issue of result.warnings) {
|
|
195
|
+
lines.push(`warn ${issue.code}${issue.layer ? ` [${issue.layer}]` : ""}: ${issue.message}`);
|
|
196
|
+
}
|
|
197
|
+
return lines.join("\n");
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=composition-lint.js.map
|