@argo-video/cli 0.1.0 → 0.1.1
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/LICENSE +21 -0
- package/README.md +2 -2
- package/dist/asset-server.d.ts +7 -0
- package/dist/asset-server.d.ts.map +1 -0
- package/dist/asset-server.js +66 -0
- package/dist/asset-server.js.map +1 -0
- package/dist/captions.d.ts +17 -0
- package/dist/captions.d.ts.map +1 -0
- package/dist/captions.js +23 -0
- package/dist/captions.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +87 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +74 -0
- package/dist/config.js.map +1 -0
- package/dist/export.d.ts +18 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +64 -0
- package/dist/export.js.map +1 -0
- package/dist/fixtures.d.ts +13 -0
- package/dist/fixtures.d.ts.map +1 -0
- package/dist/fixtures.js +36 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +2 -0
- package/dist/init.d.ts.map +1 -0
- package/{src/init.ts → dist/init.js} +39 -54
- package/dist/init.js.map +1 -0
- package/dist/narration.d.ts +9 -0
- package/dist/narration.d.ts.map +1 -0
- package/dist/narration.js +27 -0
- package/dist/narration.js.map +1 -0
- package/dist/overlays/index.d.ts +8 -0
- package/dist/overlays/index.d.ts.map +1 -0
- package/dist/overlays/index.js +34 -0
- package/dist/overlays/index.js.map +1 -0
- package/dist/overlays/manifest.d.ts +5 -0
- package/dist/overlays/manifest.d.ts.map +1 -0
- package/dist/overlays/manifest.js +52 -0
- package/dist/overlays/manifest.js.map +1 -0
- package/dist/overlays/motion.d.ts +4 -0
- package/dist/overlays/motion.d.ts.map +1 -0
- package/dist/overlays/motion.js +25 -0
- package/dist/overlays/motion.js.map +1 -0
- package/dist/overlays/templates.d.ts +7 -0
- package/dist/overlays/templates.d.ts.map +1 -0
- package/dist/overlays/templates.js +98 -0
- package/dist/overlays/templates.js.map +1 -0
- package/dist/overlays/types.d.ts +42 -0
- package/dist/overlays/types.d.ts.map +1 -0
- package/dist/overlays/types.js +25 -0
- package/dist/overlays/types.js.map +1 -0
- package/dist/overlays/zones.d.ts +15 -0
- package/dist/overlays/zones.d.ts.map +1 -0
- package/dist/overlays/zones.js +69 -0
- package/dist/overlays/zones.js.map +1 -0
- package/dist/pipeline.d.ts +3 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +93 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/record.d.ts +14 -0
- package/dist/record.d.ts.map +1 -0
- package/dist/record.js +100 -0
- package/dist/record.js.map +1 -0
- package/dist/tts/align.d.ts +17 -0
- package/dist/tts/align.d.ts.map +1 -0
- package/dist/tts/align.js +40 -0
- package/dist/tts/align.js.map +1 -0
- package/dist/tts/cache.d.ts +31 -0
- package/dist/tts/cache.d.ts.map +1 -0
- package/dist/tts/cache.js +51 -0
- package/dist/tts/cache.js.map +1 -0
- package/dist/tts/engine.d.ts +41 -0
- package/dist/tts/engine.d.ts.map +1 -0
- package/dist/tts/engine.js +108 -0
- package/dist/tts/engine.js.map +1 -0
- package/dist/tts/generate.d.ts +20 -0
- package/dist/tts/generate.d.ts.map +1 -0
- package/dist/tts/generate.js +58 -0
- package/dist/tts/generate.js.map +1 -0
- package/dist/tts/kokoro.d.ts +13 -0
- package/dist/tts/kokoro.d.ts.map +1 -0
- package/dist/tts/kokoro.js +46 -0
- package/dist/tts/kokoro.js.map +1 -0
- package/package.json +13 -1
- package/.claude/settings.local.json +0 -34
- package/DESIGN.md +0 -261
- package/docs/enhancement-proposal.md +0 -262
- package/docs/superpowers/plans/2026-03-12-argo.md +0 -208
- package/docs/superpowers/plans/2026-03-12-editorial-overlay-system.md +0 -1560
- package/docs/superpowers/plans/2026-03-13-npm-rename-skill-showcase.md +0 -499
- package/docs/superpowers/specs/2026-03-13-npm-rename-skill-showcase-design.md +0 -109
- package/skills/argo-demo-creator.md +0 -355
- package/src/asset-server.ts +0 -81
- package/src/captions.ts +0 -36
- package/src/cli.ts +0 -97
- package/src/config.ts +0 -125
- package/src/export.ts +0 -93
- package/src/fixtures.ts +0 -50
- package/src/index.ts +0 -41
- package/src/narration.ts +0 -31
- package/src/overlays/index.ts +0 -54
- package/src/overlays/manifest.ts +0 -68
- package/src/overlays/motion.ts +0 -27
- package/src/overlays/templates.ts +0 -121
- package/src/overlays/types.ts +0 -73
- package/src/overlays/zones.ts +0 -82
- package/src/pipeline.ts +0 -120
- package/src/record.ts +0 -123
- package/src/tts/align.ts +0 -75
- package/src/tts/cache.ts +0 -65
- package/src/tts/engine.ts +0 -147
- package/src/tts/generate.ts +0 -83
- package/src/tts/kokoro.ts +0 -51
- package/tests/asset-server.test.ts +0 -67
- package/tests/captions.test.ts +0 -76
- package/tests/cli.test.ts +0 -131
- package/tests/config.test.ts +0 -150
- package/tests/e2e/fake-server.ts +0 -45
- package/tests/e2e/record.e2e.test.ts +0 -131
- package/tests/export.test.ts +0 -155
- package/tests/fixtures.test.ts +0 -74
- package/tests/init.test.ts +0 -77
- package/tests/narration.test.ts +0 -120
- package/tests/overlays/index.test.ts +0 -73
- package/tests/overlays/manifest.test.ts +0 -120
- package/tests/overlays/motion.test.ts +0 -34
- package/tests/overlays/templates.test.ts +0 -69
- package/tests/overlays/types.test.ts +0 -36
- package/tests/overlays/zones.test.ts +0 -49
- package/tests/pipeline.test.ts +0 -177
- package/tests/record.test.ts +0 -87
- package/tests/tts/align.test.ts +0 -118
- package/tests/tts/cache.test.ts +0 -110
- package/tests/tts/engine.test.ts +0 -204
- package/tests/tts/generate.test.ts +0 -177
- package/tests/tts/kokoro.test.ts +0 -25
- package/tsconfig.json +0 -19
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { mkdir, writeFile, access } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
async function writeIfMissing(filePath, content) {
|
|
4
|
+
try {
|
|
5
|
+
await access(filePath);
|
|
6
|
+
console.log(` skip ${filePath} (already exists)`);
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
if (err?.code !== 'ENOENT') {
|
|
11
|
+
throw new Error(`Cannot access ${filePath}: ${err.message}`);
|
|
12
|
+
}
|
|
13
|
+
await writeFile(filePath, content, 'utf-8');
|
|
14
|
+
console.log(` create ${filePath}`);
|
|
15
|
+
return true;
|
|
12
16
|
}
|
|
13
|
-
await writeFile(filePath, content, 'utf-8');
|
|
14
|
-
console.log(` create ${filePath}`);
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
17
|
}
|
|
18
|
-
|
|
19
18
|
const EXAMPLE_DEMO = `import { test } from '@argo-video/cli';
|
|
20
19
|
import { showCaption, withCaption } from '@argo-video/cli';
|
|
21
20
|
|
|
@@ -34,37 +33,26 @@ test('example', async ({ page, narration }) => {
|
|
|
34
33
|
await showCaption(page, 'done', 'All done!', 2000);
|
|
35
34
|
});
|
|
36
35
|
`;
|
|
37
|
-
|
|
38
|
-
const EXAMPLE_VOICEOVER = JSON.stringify(
|
|
39
|
-
[
|
|
36
|
+
const EXAMPLE_VOICEOVER = JSON.stringify([
|
|
40
37
|
{ scene: 'welcome', text: 'Welcome to our app — let me show you around.' },
|
|
41
38
|
{ scene: 'action', text: 'It only takes one click to get started.' },
|
|
42
39
|
{ scene: 'done', text: "And that's it. You're all set.", voice: 'af_heart' },
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
2,
|
|
46
|
-
) + '\n';
|
|
47
|
-
|
|
48
|
-
const EXAMPLE_OVERLAYS = JSON.stringify(
|
|
49
|
-
[
|
|
40
|
+
], null, 2) + '\n';
|
|
41
|
+
const EXAMPLE_OVERLAYS = JSON.stringify([
|
|
50
42
|
{
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
scene: 'welcome',
|
|
44
|
+
type: 'lower-third',
|
|
45
|
+
text: 'Welcome to our app',
|
|
54
46
|
},
|
|
55
47
|
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
scene: 'action',
|
|
49
|
+
type: 'headline-card',
|
|
50
|
+
placement: 'top-left',
|
|
51
|
+
title: 'One-click setup',
|
|
52
|
+
body: 'Just press the button to get started.',
|
|
53
|
+
motion: 'slide-in',
|
|
62
54
|
},
|
|
63
|
-
|
|
64
|
-
null,
|
|
65
|
-
2,
|
|
66
|
-
) + '\n';
|
|
67
|
-
|
|
55
|
+
], null, 2) + '\n';
|
|
68
56
|
const ARGO_CONFIG = `export default {
|
|
69
57
|
baseURL: 'http://localhost:3000',
|
|
70
58
|
demosDir: 'demos/',
|
|
@@ -74,7 +62,6 @@ const ARGO_CONFIG = `export default {
|
|
|
74
62
|
export: { preset: 'slow', crf: 16 },
|
|
75
63
|
};
|
|
76
64
|
`;
|
|
77
|
-
|
|
78
65
|
const PLAYWRIGHT_CONFIG = `import { defineConfig } from '@playwright/test';
|
|
79
66
|
|
|
80
67
|
export default defineConfig({
|
|
@@ -96,19 +83,17 @@ export default defineConfig({
|
|
|
96
83
|
],
|
|
97
84
|
});
|
|
98
85
|
`;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
console.log(' 1. Edit demos/example.demo.ts');
|
|
112
|
-
console.log(' 2. Run: npx argo record example');
|
|
113
|
-
console.log(' 3. Run: npx argo pipeline example');
|
|
86
|
+
export async function init(cwd = process.cwd()) {
|
|
87
|
+
const demosDir = join(cwd, 'demos');
|
|
88
|
+
await mkdir(demosDir, { recursive: true });
|
|
89
|
+
await writeIfMissing(join(demosDir, 'example.demo.ts'), EXAMPLE_DEMO);
|
|
90
|
+
await writeIfMissing(join(demosDir, 'example.voiceover.json'), EXAMPLE_VOICEOVER);
|
|
91
|
+
await writeIfMissing(join(demosDir, 'example.overlays.json'), EXAMPLE_OVERLAYS);
|
|
92
|
+
await writeIfMissing(join(cwd, 'argo.config.js'), ARGO_CONFIG);
|
|
93
|
+
await writeIfMissing(join(cwd, 'playwright.config.ts'), PLAYWRIGHT_CONFIG);
|
|
94
|
+
console.log('\nArgo initialized! Next steps:');
|
|
95
|
+
console.log(' 1. Edit demos/example.demo.ts');
|
|
96
|
+
console.log(' 2. Run: npx argo record example');
|
|
97
|
+
console.log(' 3. Run: npx argo pipeline example');
|
|
114
98
|
}
|
|
99
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"narration.d.ts","sourceRoot":"","sources":["../src/narration.ts"],"names":[],"mappings":"AAGA,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,SAAS,CAAuB;IAExC,KAAK,IAAI,IAAI;IAKb,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAUzB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAI9B,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAI/C"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
export class NarrationTimeline {
|
|
4
|
+
timings = new Map();
|
|
5
|
+
startTime = null;
|
|
6
|
+
start() {
|
|
7
|
+
this.startTime = Date.now();
|
|
8
|
+
this.timings = new Map();
|
|
9
|
+
}
|
|
10
|
+
mark(scene) {
|
|
11
|
+
if (this.startTime === null) {
|
|
12
|
+
throw new Error('Cannot mark before start() has been called');
|
|
13
|
+
}
|
|
14
|
+
if (this.timings.has(scene)) {
|
|
15
|
+
throw new Error(`Duplicate scene name: "${scene}"`);
|
|
16
|
+
}
|
|
17
|
+
this.timings.set(scene, Date.now() - this.startTime);
|
|
18
|
+
}
|
|
19
|
+
getTimings() {
|
|
20
|
+
return Object.fromEntries(this.timings);
|
|
21
|
+
}
|
|
22
|
+
async flush(outputPath) {
|
|
23
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
24
|
+
await writeFile(outputPath, JSON.stringify(this.getTimings(), null, 2), 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=narration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"narration.js","sourceRoot":"","sources":["../src/narration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,OAAO,iBAAiB;IACpB,OAAO,GAAwB,IAAI,GAAG,EAAE,CAAC;IACzC,SAAS,GAAkB,IAAI,CAAC;IAExC,KAAK;QACH,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,KAAa;QAChB,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,GAAG,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,UAAU;QACR,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,UAAkB;QAC5B,MAAM,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACnF,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
|
+
import type { OverlayCue, Zone } from './types.js';
|
|
3
|
+
export type { OverlayCue, OverlayManifestEntry, Zone, TemplateType, MotionPreset } from './types.js';
|
|
4
|
+
export { renderTemplate } from './templates.js';
|
|
5
|
+
export declare function showOverlay(page: Page, _scene: string, cue: OverlayCue, durationMs: number): Promise<void>;
|
|
6
|
+
export declare function hideOverlay(page: Page, zone?: Zone): Promise<void>;
|
|
7
|
+
export declare function withOverlay(page: Page, _scene: string, cue: OverlayCue, action: () => Promise<void>): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/overlays/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAKnD,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACrG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,IAAI,GAAE,IAAsB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC1B,OAAO,CAAC,IAAI,CAAC,CAcf"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { injectIntoZone, removeZone, ZONE_ID_PREFIX } from './zones.js';
|
|
2
|
+
import { renderTemplate } from './templates.js';
|
|
3
|
+
import { getMotionCSS, getMotionStyles } from './motion.js';
|
|
4
|
+
export { renderTemplate } from './templates.js';
|
|
5
|
+
export async function showOverlay(page, _scene, cue, durationMs) {
|
|
6
|
+
const zone = cue.placement ?? 'bottom-center';
|
|
7
|
+
const motion = cue.motion ?? 'none';
|
|
8
|
+
const { contentHtml, styles } = renderTemplate(cue);
|
|
9
|
+
const zoneId = ZONE_ID_PREFIX + zone;
|
|
10
|
+
const motionCSS = getMotionCSS(motion, zoneId);
|
|
11
|
+
const motionStyles = getMotionStyles(motion, zoneId);
|
|
12
|
+
await injectIntoZone(page, zone, contentHtml, { ...styles, ...motionStyles }, motionCSS);
|
|
13
|
+
await page.waitForTimeout(durationMs);
|
|
14
|
+
await removeZone(page, zone);
|
|
15
|
+
}
|
|
16
|
+
export async function hideOverlay(page, zone = 'bottom-center') {
|
|
17
|
+
await removeZone(page, zone);
|
|
18
|
+
}
|
|
19
|
+
export async function withOverlay(page, _scene, cue, action) {
|
|
20
|
+
const zone = cue.placement ?? 'bottom-center';
|
|
21
|
+
const motion = cue.motion ?? 'none';
|
|
22
|
+
const { contentHtml, styles } = renderTemplate(cue);
|
|
23
|
+
const zoneId = ZONE_ID_PREFIX + zone;
|
|
24
|
+
const motionCSS = getMotionCSS(motion, zoneId);
|
|
25
|
+
const motionStyles = getMotionStyles(motion, zoneId);
|
|
26
|
+
await injectIntoZone(page, zone, contentHtml, { ...styles, ...motionStyles }, motionCSS);
|
|
27
|
+
try {
|
|
28
|
+
await action();
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
await removeZone(page, zone);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/overlays/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG5D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAU,EACV,MAAc,EACd,GAAe,EACf,UAAkB;IAElB,MAAM,IAAI,GAAS,GAAG,CAAC,SAAS,IAAI,eAAe,CAAC;IACpD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC;IACpC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IACrC,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErD,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,YAAY,EAAE,EAAE,SAAS,CAAC,CAAC;IACzF,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAU,EACV,OAAa,eAAe;IAE5B,MAAM,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAU,EACV,MAAc,EACd,GAAe,EACf,MAA2B;IAE3B,MAAM,IAAI,GAAS,GAAG,CAAC,SAAS,IAAI,eAAe,CAAC;IACpD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC;IACpC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,cAAc,GAAG,IAAI,CAAC;IACrC,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErD,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,YAAY,EAAE,EAAE,SAAS,CAAC,CAAC;IACzF,IAAI,CAAC;QACH,MAAM,MAAM,EAAE,CAAC;IACjB,CAAC;YAAS,CAAC;QACT,MAAM,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OverlayManifestEntry } from './types.js';
|
|
2
|
+
export declare function loadOverlayManifest(manifestPath: string): Promise<OverlayManifestEntry[] | null>;
|
|
3
|
+
export declare function hasImageAssets(entries: OverlayManifestEntry[]): boolean;
|
|
4
|
+
export declare function resolveAssetURLs(entries: OverlayManifestEntry[], assetBaseURL: string): OverlayManifestEntry[];
|
|
5
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/overlays/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvD,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,oBAAoB,EAAE,GAAG,IAAI,CAAC,CA4CxC;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,OAAO,CAEvE;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,oBAAoB,EAAE,EAC/B,YAAY,EAAE,MAAM,GACnB,oBAAoB,EAAE,CAOxB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { isValidTemplateType, isValidZone, isValidMotion } from './types.js';
|
|
4
|
+
export async function loadOverlayManifest(manifestPath) {
|
|
5
|
+
if (!existsSync(manifestPath))
|
|
6
|
+
return null;
|
|
7
|
+
const raw = await readFile(manifestPath, 'utf-8');
|
|
8
|
+
let parsed;
|
|
9
|
+
try {
|
|
10
|
+
parsed = JSON.parse(raw);
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
throw new Error(`Failed to parse overlay manifest ${manifestPath}: ${err.message}`);
|
|
14
|
+
}
|
|
15
|
+
if (!Array.isArray(parsed)) {
|
|
16
|
+
throw new Error(`Overlay manifest ${manifestPath} must contain a JSON array`);
|
|
17
|
+
}
|
|
18
|
+
const entries = [];
|
|
19
|
+
for (let i = 0; i < parsed.length; i++) {
|
|
20
|
+
const entry = parsed[i];
|
|
21
|
+
const prefix = `Overlay manifest entry ${i}`;
|
|
22
|
+
if (!entry.scene || typeof entry.scene !== 'string') {
|
|
23
|
+
throw new Error(`${prefix}: missing required field "scene"`);
|
|
24
|
+
}
|
|
25
|
+
if (!entry.type || typeof entry.type !== 'string') {
|
|
26
|
+
throw new Error(`${prefix}: missing required field "type"`);
|
|
27
|
+
}
|
|
28
|
+
if (!isValidTemplateType(entry.type)) {
|
|
29
|
+
throw new Error(`${prefix}: unknown overlay type "${entry.type}"`);
|
|
30
|
+
}
|
|
31
|
+
if (entry.placement && !isValidZone(entry.placement)) {
|
|
32
|
+
throw new Error(`${prefix}: unknown placement "${entry.placement}"`);
|
|
33
|
+
}
|
|
34
|
+
if (entry.motion && !isValidMotion(entry.motion)) {
|
|
35
|
+
throw new Error(`${prefix}: unknown motion "${entry.motion}"`);
|
|
36
|
+
}
|
|
37
|
+
entries.push(entry);
|
|
38
|
+
}
|
|
39
|
+
return entries;
|
|
40
|
+
}
|
|
41
|
+
export function hasImageAssets(entries) {
|
|
42
|
+
return entries.some((e) => e.type === 'image-card');
|
|
43
|
+
}
|
|
44
|
+
export function resolveAssetURLs(entries, assetBaseURL) {
|
|
45
|
+
return entries.map((e) => {
|
|
46
|
+
if (e.type === 'image-card' && e.src && !e.src.startsWith('http')) {
|
|
47
|
+
return { ...e, src: `${assetBaseURL}/${e.src.replace(/^assets\//, '')}` };
|
|
48
|
+
}
|
|
49
|
+
return e;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/overlays/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MotionPreset } from './types.js';
|
|
2
|
+
export declare function getMotionCSS(motion: MotionPreset, elementId: string): string;
|
|
3
|
+
export declare function getMotionStyles(motion: MotionPreset, elementId: string): Record<string, string>;
|
|
4
|
+
//# sourceMappingURL=motion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../../src/overlays/motion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAW5E;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAW/F"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function getMotionCSS(motion, elementId) {
|
|
2
|
+
const animName = `argo-${motion}-${elementId}`;
|
|
3
|
+
switch (motion) {
|
|
4
|
+
case 'fade-in':
|
|
5
|
+
return `@keyframes ${animName} { from { opacity: 0; } to { opacity: 1; } }`;
|
|
6
|
+
case 'slide-in':
|
|
7
|
+
return `@keyframes ${animName} { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } }`;
|
|
8
|
+
case 'none':
|
|
9
|
+
default:
|
|
10
|
+
return '';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function getMotionStyles(motion, elementId) {
|
|
14
|
+
const animName = `argo-${motion}-${elementId}`;
|
|
15
|
+
switch (motion) {
|
|
16
|
+
case 'fade-in':
|
|
17
|
+
return { animation: `${animName} 300ms ease-out forwards` };
|
|
18
|
+
case 'slide-in':
|
|
19
|
+
return { animation: `${animName} 400ms ease-out forwards` };
|
|
20
|
+
case 'none':
|
|
21
|
+
default:
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=motion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/overlays/motion.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,MAAoB,EAAE,SAAiB;IAClE,MAAM,QAAQ,GAAG,QAAQ,MAAM,IAAI,SAAS,EAAE,CAAC;IAC/C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,cAAc,QAAQ,8CAA8C,CAAC;QAC9E,KAAK,UAAU;YACb,OAAO,cAAc,QAAQ,sGAAsG,CAAC;QACtI,KAAK,MAAM,CAAC;QACZ;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAoB,EAAE,SAAiB;IACrE,MAAM,QAAQ,GAAG,QAAQ,MAAM,IAAI,SAAS,EAAE,CAAC;IAC/C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,EAAE,SAAS,EAAE,GAAG,QAAQ,0BAA0B,EAAE,CAAC;QAC9D,KAAK,UAAU;YACb,OAAO,EAAE,SAAS,EAAE,GAAG,QAAQ,0BAA0B,EAAE,CAAC;QAC9D,KAAK,MAAM,CAAC;QACZ;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/overlays/templates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAwGD,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,cAAc,CAW9D"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
function escapeHtml(str) {
|
|
2
|
+
return str
|
|
3
|
+
.replace(/&/g, '&')
|
|
4
|
+
.replace(/</g, '<')
|
|
5
|
+
.replace(/>/g, '>')
|
|
6
|
+
.replace(/"/g, '"');
|
|
7
|
+
}
|
|
8
|
+
function lowerThird(text) {
|
|
9
|
+
return {
|
|
10
|
+
contentHtml: `<span>${escapeHtml(text)}</span>`,
|
|
11
|
+
styles: {
|
|
12
|
+
background: 'rgba(0, 0, 0, 0.85)',
|
|
13
|
+
color: '#fff',
|
|
14
|
+
padding: '16px 32px',
|
|
15
|
+
borderRadius: '12px',
|
|
16
|
+
fontSize: '28px',
|
|
17
|
+
fontWeight: '500',
|
|
18
|
+
textAlign: 'center',
|
|
19
|
+
maxWidth: '80vw',
|
|
20
|
+
letterSpacing: '0.01em',
|
|
21
|
+
lineHeight: '1.4',
|
|
22
|
+
boxShadow: '0 4px 24px rgba(0, 0, 0, 0.3)',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function headlineCard(title, kicker, body) {
|
|
27
|
+
const parts = [];
|
|
28
|
+
if (kicker) {
|
|
29
|
+
parts.push(`<div style="font-size:12px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:rgba(255,255,255,0.7);margin-bottom:8px">${escapeHtml(kicker)}</div>`);
|
|
30
|
+
}
|
|
31
|
+
parts.push(`<div style="font-size:26px;font-weight:700;line-height:1.25;color:#fff">${escapeHtml(title)}</div>`);
|
|
32
|
+
if (body) {
|
|
33
|
+
parts.push(`<div style="font-size:16px;line-height:1.5;color:rgba(255,255,255,0.85);margin-top:8px">${escapeHtml(body)}</div>`);
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
contentHtml: parts.join(''),
|
|
37
|
+
styles: {
|
|
38
|
+
background: 'rgba(0, 0, 0, 0.7)',
|
|
39
|
+
backdropFilter: 'blur(16px)',
|
|
40
|
+
WebkitBackdropFilter: 'blur(16px)',
|
|
41
|
+
padding: '24px 28px',
|
|
42
|
+
borderRadius: '16px',
|
|
43
|
+
maxWidth: '420px',
|
|
44
|
+
boxShadow: '0 8px 32px rgba(0, 0, 0, 0.4)',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function callout(text) {
|
|
49
|
+
return {
|
|
50
|
+
contentHtml: `<span>${escapeHtml(text)}</span>`,
|
|
51
|
+
styles: {
|
|
52
|
+
background: 'rgba(0, 0, 0, 0.8)',
|
|
53
|
+
color: '#fff',
|
|
54
|
+
padding: '10px 18px',
|
|
55
|
+
borderRadius: '20px',
|
|
56
|
+
fontSize: '16px',
|
|
57
|
+
fontWeight: '500',
|
|
58
|
+
lineHeight: '1.3',
|
|
59
|
+
maxWidth: '300px',
|
|
60
|
+
boxShadow: '0 2px 12px rgba(0, 0, 0, 0.3)',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function imageCard(src, title, body) {
|
|
65
|
+
const parts = [];
|
|
66
|
+
parts.push(`<img src="${escapeHtml(src)}" style="max-width:100%;border-radius:8px;display:block" />`);
|
|
67
|
+
if (title) {
|
|
68
|
+
parts.push(`<div style="font-size:18px;font-weight:600;color:#fff;margin-top:12px">${escapeHtml(title)}</div>`);
|
|
69
|
+
}
|
|
70
|
+
if (body) {
|
|
71
|
+
parts.push(`<div style="font-size:14px;color:rgba(255,255,255,0.8);margin-top:4px;line-height:1.4">${escapeHtml(body)}</div>`);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
contentHtml: parts.join(''),
|
|
75
|
+
styles: {
|
|
76
|
+
background: 'rgba(0, 0, 0, 0.75)',
|
|
77
|
+
backdropFilter: 'blur(12px)',
|
|
78
|
+
WebkitBackdropFilter: 'blur(12px)',
|
|
79
|
+
padding: '16px',
|
|
80
|
+
borderRadius: '14px',
|
|
81
|
+
maxWidth: '360px',
|
|
82
|
+
boxShadow: '0 6px 24px rgba(0, 0, 0, 0.4)',
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export function renderTemplate(cue) {
|
|
87
|
+
switch (cue.type) {
|
|
88
|
+
case 'lower-third':
|
|
89
|
+
return lowerThird(cue.text);
|
|
90
|
+
case 'headline-card':
|
|
91
|
+
return headlineCard(cue.title, cue.kicker, cue.body);
|
|
92
|
+
case 'callout':
|
|
93
|
+
return callout(cue.text);
|
|
94
|
+
case 'image-card':
|
|
95
|
+
return imageCard(cue.src, cue.title, cue.body);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/overlays/templates.ts"],"names":[],"mappings":"AAOA,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO;QACL,WAAW,EAAE,SAAS,UAAU,CAAC,IAAI,CAAC,SAAS;QAC/C,MAAM,EAAE;YACN,UAAU,EAAE,qBAAqB;YACjC,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,WAAW;YACpB,YAAY,EAAE,MAAM;YACpB,QAAQ,EAAE,MAAM;YAChB,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,QAAQ;YACnB,QAAQ,EAAE,MAAM;YAChB,aAAa,EAAE,QAAQ;YACvB,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,+BAA+B;SAC3C;KACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,MAAe,EAAE,IAAa;IACjE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CACR,4IAA4I,UAAU,CAAC,MAAM,CAAC,QAAQ,CACvK,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CACR,2EAA2E,UAAU,CAAC,KAAK,CAAC,QAAQ,CACrG,CAAC;IACF,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,IAAI,CACR,2FAA2F,UAAU,CAAC,IAAI,CAAC,QAAQ,CACpH,CAAC;IACJ,CAAC;IACD,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,EAAE;YACN,UAAU,EAAE,oBAAoB;YAChC,cAAc,EAAE,YAAY;YAC5B,oBAAoB,EAAE,YAAY;YAClC,OAAO,EAAE,WAAW;YACpB,YAAY,EAAE,MAAM;YACpB,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,+BAA+B;SAC3C;KACF,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO;QACL,WAAW,EAAE,SAAS,UAAU,CAAC,IAAI,CAAC,SAAS;QAC/C,MAAM,EAAE;YACN,UAAU,EAAE,oBAAoB;YAChC,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,WAAW;YACpB,YAAY,EAAE,MAAM;YACpB,QAAQ,EAAE,MAAM;YAChB,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,+BAA+B;SAC3C;KACF,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,GAAW,EAAE,KAAc,EAAE,IAAa;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CACR,aAAa,UAAU,CAAC,GAAG,CAAC,6DAA6D,CAC1F,CAAC;IACF,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,IAAI,CACR,0EAA0E,UAAU,CAAC,KAAK,CAAC,QAAQ,CACpG,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,IAAI,CACR,0FAA0F,UAAU,CAAC,IAAI,CAAC,QAAQ,CACnH,CAAC;IACJ,CAAC;IACD,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,EAAE;YACN,UAAU,EAAE,qBAAqB;YACjC,cAAc,EAAE,YAAY;YAC5B,oBAAoB,EAAE,YAAY;YAClC,OAAO,EAAE,MAAM;YACf,YAAY,EAAE,MAAM;YACpB,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,+BAA+B;SAC3C;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAe;IAC5C,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,aAAa;YAChB,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,KAAK,eAAe;YAClB,OAAO,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACvD,KAAK,SAAS;YACZ,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,YAAY;YACf,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare const ZONES: readonly ["bottom-center", "top-left", "top-right", "bottom-left", "bottom-right", "center"];
|
|
2
|
+
export type Zone = (typeof ZONES)[number];
|
|
3
|
+
export declare const TEMPLATE_TYPES: readonly ["lower-third", "headline-card", "callout", "image-card"];
|
|
4
|
+
export type TemplateType = (typeof TEMPLATE_TYPES)[number];
|
|
5
|
+
export declare const MOTIONS: readonly ["none", "fade-in", "slide-in"];
|
|
6
|
+
export type MotionPreset = (typeof MOTIONS)[number];
|
|
7
|
+
export interface LowerThirdCue {
|
|
8
|
+
type: 'lower-third';
|
|
9
|
+
text: string;
|
|
10
|
+
placement?: Zone;
|
|
11
|
+
motion?: MotionPreset;
|
|
12
|
+
}
|
|
13
|
+
export interface HeadlineCardCue {
|
|
14
|
+
type: 'headline-card';
|
|
15
|
+
title: string;
|
|
16
|
+
kicker?: string;
|
|
17
|
+
body?: string;
|
|
18
|
+
placement?: Zone;
|
|
19
|
+
motion?: MotionPreset;
|
|
20
|
+
}
|
|
21
|
+
export interface CalloutCue {
|
|
22
|
+
type: 'callout';
|
|
23
|
+
text: string;
|
|
24
|
+
placement?: Zone;
|
|
25
|
+
motion?: MotionPreset;
|
|
26
|
+
}
|
|
27
|
+
export interface ImageCardCue {
|
|
28
|
+
type: 'image-card';
|
|
29
|
+
src: string;
|
|
30
|
+
title?: string;
|
|
31
|
+
body?: string;
|
|
32
|
+
placement?: Zone;
|
|
33
|
+
motion?: MotionPreset;
|
|
34
|
+
}
|
|
35
|
+
export type OverlayCue = LowerThirdCue | HeadlineCardCue | CalloutCue | ImageCardCue;
|
|
36
|
+
export type OverlayManifestEntry = OverlayCue & {
|
|
37
|
+
scene: string;
|
|
38
|
+
};
|
|
39
|
+
export declare function isValidZone(value: string): value is Zone;
|
|
40
|
+
export declare function isValidTemplateType(value: string): value is TemplateType;
|
|
41
|
+
export declare function isValidMotion(value: string): value is MotionPreset;
|
|
42
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/overlays/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,8FAOR,CAAC;AAEX,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1C,eAAO,MAAM,cAAc,oEAKjB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,OAAO,0CAA2C,CAAC;AAEhE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,YAAY,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,eAAe,GAAG,UAAU,GAAG,YAAY,CAAC;AAErF,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAC9C,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,IAAI,CAExD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,YAAY,CAExE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,YAAY,CAElE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const ZONES = [
|
|
2
|
+
'bottom-center',
|
|
3
|
+
'top-left',
|
|
4
|
+
'top-right',
|
|
5
|
+
'bottom-left',
|
|
6
|
+
'bottom-right',
|
|
7
|
+
'center',
|
|
8
|
+
];
|
|
9
|
+
export const TEMPLATE_TYPES = [
|
|
10
|
+
'lower-third',
|
|
11
|
+
'headline-card',
|
|
12
|
+
'callout',
|
|
13
|
+
'image-card',
|
|
14
|
+
];
|
|
15
|
+
export const MOTIONS = ['none', 'fade-in', 'slide-in'];
|
|
16
|
+
export function isValidZone(value) {
|
|
17
|
+
return ZONES.includes(value);
|
|
18
|
+
}
|
|
19
|
+
export function isValidTemplateType(value) {
|
|
20
|
+
return TEMPLATE_TYPES.includes(value);
|
|
21
|
+
}
|
|
22
|
+
export function isValidMotion(value) {
|
|
23
|
+
return MOTIONS.includes(value);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/overlays/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,eAAe;IACf,UAAU;IACV,WAAW;IACX,aAAa;IACb,cAAc;IACd,QAAQ;CACA,CAAC;AAIX,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,aAAa;IACb,eAAe;IACf,SAAS;IACT,YAAY;CACJ,CAAC;AAIX,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AA0ChE,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAQ,KAA2B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAQ,cAAoC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAQ,OAA6B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
|
+
import type { Zone } from './types.js';
|
|
3
|
+
export declare const ZONE_ID_PREFIX = "argo-overlay-";
|
|
4
|
+
/**
|
|
5
|
+
* Inject content into a zone. Replaces any existing overlay in that zone.
|
|
6
|
+
* Security: contentHtml is generated by template renderers which escape all
|
|
7
|
+
* text fields via escapeHtml(). Content originates from author-controlled
|
|
8
|
+
* manifest files, not end-user input.
|
|
9
|
+
*/
|
|
10
|
+
export declare function injectIntoZone(page: Page, zone: Zone, contentHtml: string, containerStyles: Record<string, string>, animationCSS?: string): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Remove the overlay in the specified zone, if any.
|
|
13
|
+
*/
|
|
14
|
+
export declare function removeZone(page: Page, zone: Zone): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=zones.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zones.d.ts","sourceRoot":"","sources":["../../src/overlays/zones.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,cAAc,kBAAkB,CAAC;AAuB9C;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACvC,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAgCf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtE"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export const ZONE_ID_PREFIX = 'argo-overlay-';
|
|
2
|
+
const ZONE_POSITIONS = {
|
|
3
|
+
'bottom-center': {
|
|
4
|
+
position: 'fixed', bottom: '60px', left: '50%', transform: 'translateX(-50%)',
|
|
5
|
+
},
|
|
6
|
+
'top-left': {
|
|
7
|
+
position: 'fixed', top: '40px', left: '40px',
|
|
8
|
+
},
|
|
9
|
+
'top-right': {
|
|
10
|
+
position: 'fixed', top: '40px', right: '40px',
|
|
11
|
+
},
|
|
12
|
+
'bottom-left': {
|
|
13
|
+
position: 'fixed', bottom: '60px', left: '40px',
|
|
14
|
+
},
|
|
15
|
+
'bottom-right': {
|
|
16
|
+
position: 'fixed', bottom: '60px', right: '40px',
|
|
17
|
+
},
|
|
18
|
+
'center': {
|
|
19
|
+
position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Inject content into a zone. Replaces any existing overlay in that zone.
|
|
24
|
+
* Security: contentHtml is generated by template renderers which escape all
|
|
25
|
+
* text fields via escapeHtml(). Content originates from author-controlled
|
|
26
|
+
* manifest files, not end-user input.
|
|
27
|
+
*/
|
|
28
|
+
export async function injectIntoZone(page, zone, contentHtml, containerStyles, animationCSS) {
|
|
29
|
+
const zoneId = ZONE_ID_PREFIX + zone;
|
|
30
|
+
const positionStyles = ZONE_POSITIONS[zone];
|
|
31
|
+
const baseStyles = {
|
|
32
|
+
...positionStyles,
|
|
33
|
+
zIndex: '999999',
|
|
34
|
+
pointerEvents: 'none',
|
|
35
|
+
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
36
|
+
...containerStyles,
|
|
37
|
+
};
|
|
38
|
+
await page.evaluate(([id, html, styles, css]) => {
|
|
39
|
+
const existing = document.getElementById(id);
|
|
40
|
+
if (existing)
|
|
41
|
+
existing.remove();
|
|
42
|
+
if (css) {
|
|
43
|
+
const styleId = id + '-style';
|
|
44
|
+
let styleEl = document.getElementById(styleId);
|
|
45
|
+
if (!styleEl) {
|
|
46
|
+
styleEl = document.createElement('style');
|
|
47
|
+
styleEl.id = styleId;
|
|
48
|
+
document.head.appendChild(styleEl);
|
|
49
|
+
}
|
|
50
|
+
styleEl.textContent = css;
|
|
51
|
+
}
|
|
52
|
+
const container = document.createElement('div');
|
|
53
|
+
container.id = id;
|
|
54
|
+
container.innerHTML = html;
|
|
55
|
+
Object.assign(container.style, styles);
|
|
56
|
+
document.body.appendChild(container);
|
|
57
|
+
}, [zoneId, contentHtml, baseStyles, animationCSS ?? '']);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Remove the overlay in the specified zone, if any.
|
|
61
|
+
*/
|
|
62
|
+
export async function removeZone(page, zone) {
|
|
63
|
+
const zoneId = ZONE_ID_PREFIX + zone;
|
|
64
|
+
await page.evaluate((id) => {
|
|
65
|
+
document.getElementById(id)?.remove();
|
|
66
|
+
document.getElementById(id + '-style')?.remove();
|
|
67
|
+
}, zoneId);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=zones.js.map
|