@gannochenko/staticstripes 0.0.17 → 0.0.19

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/dist/project.d.ts CHANGED
@@ -10,11 +10,12 @@ export declare class Project {
10
10
  private aiProviders;
11
11
  private title;
12
12
  private date;
13
+ private tags;
13
14
  private cssText;
14
15
  private projectPath;
15
16
  private assetManager;
16
17
  private expressionContext;
17
- constructor(sequencesDefinitions: SequenceDefinition[], assets: Asset[], outputs: Map<string, Output>, ffmpegOptions: Map<string, FFmpegOption>, uploads: Map<string, Upload>, aiProviders: Map<string, AIProvider>, title: string, date: string | undefined, cssText: string, projectPath: string);
18
+ constructor(sequencesDefinitions: SequenceDefinition[], assets: Asset[], outputs: Map<string, Output>, ffmpegOptions: Map<string, FFmpegOption>, uploads: Map<string, Upload>, aiProviders: Map<string, AIProvider>, title: string, date: string | undefined, tags: string[], cssText: string, projectPath: string);
18
19
  build(outputName: string): Promise<FilterBuffer>;
19
20
  printStats(): void;
20
21
  getAssetManager(): AssetManager;
@@ -30,6 +31,7 @@ export declare class Project {
30
31
  getAIProvider(name: string): AIProvider | undefined;
31
32
  getTitle(): string;
32
33
  getDate(): string | undefined;
34
+ getTags(): string[];
33
35
  getCssText(): string;
34
36
  /**
35
37
  * Collects timecodes from fragments with timecodeLabel
@@ -42,6 +44,12 @@ export declare class Project {
42
44
  getAssetByName(name: string): Asset | undefined;
43
45
  getVideoInputLabelByAssetName(name: string): Label;
44
46
  getAudioInputLabelByAssetName(name: string): Label;
47
+ /**
48
+ * Renders all apps and creates virtual assets for them.
49
+ * Apps must dispatch "sts-render-complete" on document when ready,
50
+ * or rendering will fail after a 5-second timeout.
51
+ */
52
+ renderApps(outputName: string, activeCacheKeys?: Set<string>): Promise<void>;
45
53
  /**
46
54
  * Renders all containers and creates virtual assets for them
47
55
  */
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,MAAM,EACN,kBAAkB,EAClB,YAAY,EACZ,MAAM,EACN,UAAU,EACX,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAKxC,qBAAa,OAAO;IAKhB,OAAO,CAAC,oBAAoB;IAE5B,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,WAAW;IAbrB,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,iBAAiB,CAAoB;gBAGnC,oBAAoB,EAAE,kBAAkB,EAAE,EAClD,MAAM,EAAE,KAAK,EAAE,EACP,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EACxC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACpC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM;IAQhB,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA6CtD,UAAU;IAYV,eAAe,IAAI,YAAY;IAI/B,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIjD,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIjC,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC;IAI7C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIvD,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIjC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK3C,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIxC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIlD,cAAc,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;IAIzC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAInD,QAAQ,IAAI,MAAM;IAIlB,OAAO,IAAI,MAAM,GAAG,SAAS;IAI7B,UAAU,IAAI,MAAM;IAI3B;;;;OAIG;IACI,YAAY,IAAI,MAAM,EAAE;IAoCxB,sBAAsB,IAAI,kBAAkB,EAAE;IAK9C,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAIvC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAI/C,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IAIlD,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IAIzD;;OAEG;IACU,gBAAgB,CAC3B,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAC5B,OAAO,CAAC,IAAI,CAAC;CA0DjB"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
package/dist/project.js CHANGED
@@ -5,6 +5,7 @@ const asset_manager_1 = require("./asset-manager");
5
5
  const sequence_1 = require("./sequence");
6
6
  const stream_1 = require("./stream");
7
7
  const container_renderer_1 = require("./container-renderer");
8
+ const app_renderer_1 = require("./app-renderer");
8
9
  const path_1 = require("path");
9
10
  class Project {
10
11
  sequencesDefinitions;
@@ -14,11 +15,12 @@ class Project {
14
15
  aiProviders;
15
16
  title;
16
17
  date;
18
+ tags;
17
19
  cssText;
18
20
  projectPath;
19
21
  assetManager;
20
22
  expressionContext;
21
- constructor(sequencesDefinitions, assets, outputs, ffmpegOptions, uploads, aiProviders, title, date, cssText, projectPath) {
23
+ constructor(sequencesDefinitions, assets, outputs, ffmpegOptions, uploads, aiProviders, title, date, tags, cssText, projectPath) {
22
24
  this.sequencesDefinitions = sequencesDefinitions;
23
25
  this.outputs = outputs;
24
26
  this.ffmpegOptions = ffmpegOptions;
@@ -26,6 +28,7 @@ class Project {
26
28
  this.aiProviders = aiProviders;
27
29
  this.title = title;
28
30
  this.date = date;
31
+ this.tags = tags;
29
32
  this.cssText = cssText;
30
33
  this.projectPath = projectPath;
31
34
  this.assetManager = new asset_manager_1.AssetManager(assets);
@@ -114,6 +117,9 @@ class Project {
114
117
  getDate() {
115
118
  return this.date;
116
119
  }
120
+ getTags() {
121
+ return this.tags;
122
+ }
117
123
  getCssText() {
118
124
  return this.cssText;
119
125
  }
@@ -169,6 +175,45 @@ class Project {
169
175
  getAudioInputLabelByAssetName(name) {
170
176
  return this.assetManager.getAudioInputLabelByAssetName(name);
171
177
  }
178
+ /**
179
+ * Renders all apps and creates virtual assets for them.
180
+ * Apps must dispatch "sts-render-complete" on document when ready,
181
+ * or rendering will fail after a 5-second timeout.
182
+ */
183
+ async renderApps(outputName, activeCacheKeys) {
184
+ const output = this.getOutput(outputName);
185
+ if (!output) {
186
+ throw new Error(`Output "${outputName}" not found`);
187
+ }
188
+ const fragmentsWithApps = this.sequencesDefinitions.flatMap((seq) => seq.fragments.filter((frag) => frag.app));
189
+ if (fragmentsWithApps.length === 0) {
190
+ return;
191
+ }
192
+ console.log('\n=== Rendering Apps ===\n');
193
+ const apps = fragmentsWithApps.map((frag) => frag.app);
194
+ const projectDir = (0, path_1.dirname)(this.projectPath);
195
+ const results = await (0, app_renderer_1.renderApps)(apps, output.resolution.width, output.resolution.height, projectDir, outputName, this.title, this.date, this.tags, activeCacheKeys);
196
+ // Create virtual assets and update fragment assetNames
197
+ for (const result of results) {
198
+ const virtualAssetName = result.app.id;
199
+ const virtualAsset = {
200
+ name: virtualAssetName,
201
+ path: result.screenshotPath,
202
+ type: 'image',
203
+ duration: 0,
204
+ width: output.resolution.width,
205
+ height: output.resolution.height,
206
+ rotation: 0,
207
+ hasVideo: true,
208
+ hasAudio: false,
209
+ };
210
+ this.assetManager.addVirtualAsset(virtualAsset);
211
+ const fragment = fragmentsWithApps.find((frag) => frag.app?.id === result.app.id);
212
+ if (fragment) {
213
+ fragment.assetName = virtualAssetName;
214
+ }
215
+ }
216
+ }
172
217
  /**
173
218
  * Renders all containers and creates virtual assets for them
174
219
  */
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
package/dist/type.d.ts CHANGED
@@ -9,6 +9,11 @@ export type Container = {
9
9
  id: string;
10
10
  htmlContent: string;
11
11
  };
12
+ export type App = {
13
+ id: string;
14
+ src: string;
15
+ parameters: Record<string, string>;
16
+ };
12
17
  export type ParsedHtml = {
13
18
  ast: Document;
14
19
  css: Map<Element, CSSProperties>;
@@ -55,6 +60,7 @@ export type Fragment = {
55
60
  chromakeyColor: string;
56
61
  visualFilter?: string;
57
62
  container?: Container;
63
+ app?: App;
58
64
  timecodeLabel?: string;
59
65
  };
60
66
  export type SequenceDefinition = {
@@ -1 +1 @@
1
- {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC;AAC9B,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAElC,MAAM,MAAM,aAAa,GAAG;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,QAAQ,CAAC;IACd,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,EAAE,CAAC,EAAE;QACH,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAAC;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,gBAAgB,EAAE,SAAS,GAAG,WAAW,CAAC;IAC1C,mCAAmC,EAAE,MAAM,CAAC;IAC5C,iCAAiC,EAAE,MAAM,CAAC;IAC1C,iCAAiC,EAAE,MAAM,CAAC;IAC1C,8BAA8B,EAAE,MAAM,CAAC;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,QAAQ,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,EAAE,CAAC,EAAE;QACH,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IAEF,SAAS,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,OAAO,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAGF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,kBAAkB,EAAE,CAAC;IAChC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC3B,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC"}
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gannochenko/staticstripes",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "description": "HTML/CSS wrapper around ffmpeg",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -0,0 +1,229 @@
1
+ import puppeteer, { Browser } from 'puppeteer';
2
+ import { writeFile, mkdir } from 'fs/promises';
3
+ import { resolve, isAbsolute } from 'path';
4
+ import { existsSync } from 'fs';
5
+ import { createHash } from 'crypto';
6
+ import { App } from './type';
7
+
8
+ const RENDER_TIMEOUT_MS = 5000;
9
+
10
+ export interface RenderAppOptions {
11
+ app: App;
12
+ width: number;
13
+ height: number;
14
+ projectDir: string;
15
+ outputName: string;
16
+ title: string;
17
+ date?: string;
18
+ tags: string[];
19
+ browser?: Browser; // optional shared browser instance
20
+ }
21
+
22
+ export interface AppRenderResult {
23
+ app: App;
24
+ screenshotPath: string;
25
+ }
26
+
27
+ function generateAppCacheKey(
28
+ src: string,
29
+ parameters: Record<string, string>,
30
+ title: string,
31
+ date: string | undefined,
32
+ tags: string[],
33
+ outputName: string,
34
+ ): string {
35
+ const hash = createHash('sha256');
36
+ hash.update(src);
37
+ hash.update(JSON.stringify(parameters));
38
+ hash.update(title);
39
+ hash.update(date ?? '');
40
+ hash.update(tags.join(','));
41
+ hash.update(outputName);
42
+ return hash.digest('hex').substring(0, 16);
43
+ }
44
+
45
+ /**
46
+ * Renders a React (or any SPA) app to a PNG screenshot using Puppeteer.
47
+ * The app must dispatch a "sts-render-complete" custom event on document
48
+ * when it is fully rendered. If the event is not received within
49
+ * RENDER_TIMEOUT_MS, an error is thrown.
50
+ */
51
+ export async function renderApp(options: RenderAppOptions): Promise<AppRenderResult> {
52
+ const { app, width, height, projectDir, outputName, title, date, tags, browser: sharedBrowser } = options;
53
+
54
+ // Create cache directory
55
+ const cacheDir = resolve(projectDir, 'cache', 'apps');
56
+ if (!existsSync(cacheDir)) {
57
+ await mkdir(cacheDir, { recursive: true });
58
+ }
59
+
60
+ // Generate cache key from all inputs that affect output
61
+ const cacheKey = generateAppCacheKey(
62
+ app.src,
63
+ app.parameters,
64
+ title,
65
+ date,
66
+ tags,
67
+ outputName,
68
+ );
69
+ const screenshotPath = resolve(cacheDir, `${cacheKey}.png`);
70
+
71
+ // Return cached result if available
72
+ if (existsSync(screenshotPath)) {
73
+ console.log(
74
+ `Using cached app "${app.id}" (hash: ${cacheKey}) from ${screenshotPath}`,
75
+ );
76
+ return { app, screenshotPath };
77
+ }
78
+
79
+ // Resolve index.html
80
+ const appDir = isAbsolute(app.src)
81
+ ? app.src
82
+ : resolve(projectDir, app.src);
83
+ const indexPath = resolve(appDir, 'index.html');
84
+
85
+ if (!existsSync(indexPath)) {
86
+ throw new Error(`App "${app.id}": index.html not found at ${indexPath}`);
87
+ }
88
+
89
+ // Build URL with query parameters.
90
+ // Metadata (title, date, tags) is always injected; extra parameters from
91
+ // data-parameters are merged in afterwards and can override metadata keys.
92
+ const searchParams = new URLSearchParams({ rendering: '' });
93
+ searchParams.set('title', title);
94
+ if (date) searchParams.set('date', date);
95
+ if (tags.length > 0) searchParams.set('tags', tags.join(','));
96
+ for (const [key, value] of Object.entries(app.parameters)) {
97
+ searchParams.set(key, value);
98
+ }
99
+
100
+ const url = `file://${indexPath}?${searchParams.toString()}`;
101
+
102
+ console.log(`\nRendering app "${app.id}" from ${url}`);
103
+
104
+ const ownBrowser = sharedBrowser
105
+ ? null
106
+ : await puppeteer.launch({
107
+ headless: true,
108
+ args: ['--no-sandbox', '--disable-setuid-sandbox'],
109
+ });
110
+ const browser = sharedBrowser ?? ownBrowser!;
111
+
112
+ const page = await browser.newPage();
113
+
114
+ try {
115
+ await page.setViewport({ width, height });
116
+
117
+ page.on('console', (msg) =>
118
+ console.log(`[app:${app.id}] console.${msg.type()}: ${msg.text()}`),
119
+ );
120
+ page.on('pageerror', (err) =>
121
+ console.error(`[app:${app.id}] page error: ${String(err)}`),
122
+ );
123
+ page.on('requestfailed', (req) =>
124
+ console.error(`[app:${app.id}] request failed: ${req.url()} — ${req.failure()?.errorText}`),
125
+ );
126
+
127
+ // Initialise the flag before navigation. The app sets it to true directly
128
+ // via window.__stsRenderComplete = true inside its useEffect, so no event
129
+ // listener is needed on this side.
130
+ await page.evaluateOnNewDocument(
131
+ `window.__stsRenderComplete = false;`,
132
+ );
133
+
134
+ await page.goto(url, { waitUntil: 'networkidle0' });
135
+
136
+ // Wait for the app to signal it is done rendering
137
+ await page
138
+ .waitForFunction('window.__stsRenderComplete === true', {
139
+ timeout: RENDER_TIMEOUT_MS,
140
+ })
141
+ .catch(() => {
142
+ throw new Error(
143
+ `App "${app.id}" did not set window.__stsRenderComplete within ${RENDER_TIMEOUT_MS}ms`,
144
+ );
145
+ });
146
+
147
+ // Screenshot with transparent background
148
+ const screenshot = await page.screenshot({
149
+ type: 'png',
150
+ omitBackground: true,
151
+ clip: { x: 0, y: 0, width, height },
152
+ });
153
+
154
+ await writeFile(screenshotPath, screenshot);
155
+
156
+ console.log(
157
+ `Rendered app "${app.id}" (hash: ${cacheKey}) to ${screenshotPath}`,
158
+ );
159
+
160
+ return { app, screenshotPath };
161
+ } finally {
162
+ await page.close();
163
+ if (ownBrowser) await ownBrowser.close();
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Renders multiple apps in sequence, reusing a single browser instance.
169
+ */
170
+ export async function renderApps(
171
+ apps: App[],
172
+ width: number,
173
+ height: number,
174
+ projectDir: string,
175
+ outputName: string,
176
+ title: string,
177
+ date: string | undefined,
178
+ tags: string[],
179
+ activeCacheKeys?: Set<string>,
180
+ ): Promise<AppRenderResult[]> {
181
+ const results: AppRenderResult[] = [];
182
+
183
+ // Launch once and reuse across all apps.
184
+ // --allow-file-access-from-files is required so Chromium allows
185
+ // <script type="module"> and <link> tags to load sibling files
186
+ // when the page itself is served via file://.
187
+ const browser = await puppeteer.launch({
188
+ headless: true,
189
+ args: [
190
+ '--no-sandbox',
191
+ '--disable-setuid-sandbox',
192
+ '--allow-file-access-from-files',
193
+ ],
194
+ });
195
+
196
+ try {
197
+ for (const app of apps) {
198
+ const cacheKey = generateAppCacheKey(
199
+ app.src,
200
+ app.parameters,
201
+ title,
202
+ date,
203
+ tags,
204
+ outputName,
205
+ );
206
+
207
+ if (activeCacheKeys) {
208
+ activeCacheKeys.add(cacheKey);
209
+ }
210
+
211
+ const result = await renderApp({
212
+ app,
213
+ width,
214
+ height,
215
+ projectDir,
216
+ outputName,
217
+ title,
218
+ date,
219
+ tags,
220
+ browser,
221
+ });
222
+ results.push(result);
223
+ }
224
+ } finally {
225
+ await browser.close();
226
+ }
227
+
228
+ return results;
229
+ }
@@ -158,8 +158,9 @@ export function registerGenerateCommand(
158
158
  mkdirSync(outputDir, { recursive: true });
159
159
  }
160
160
 
161
- // Render containers for this output (accumulate cache keys)
161
+ // Render containers and apps for this output (accumulate cache keys)
162
162
  await project.renderContainers(outputName, activeCacheKeys);
163
+ await project.renderApps(outputName, activeCacheKeys);
163
164
 
164
165
  // Print project statistics
165
166
  project.printStats();
@@ -7,6 +7,7 @@ import {
7
7
  SequenceDefinition,
8
8
  Fragment,
9
9
  Container,
10
+ App,
10
11
  FFmpegOption,
11
12
  Upload,
12
13
  AIProvider,
@@ -120,6 +121,7 @@ export class HTMLProjectParser {
120
121
  aiProviders,
121
122
  title,
122
123
  date,
124
+ globalTags,
123
125
  cssText,
124
126
  this.projectPath,
125
127
  );
@@ -722,7 +724,11 @@ export class HTMLProjectParser {
722
724
  globalTags,
723
725
  );
724
726
  } else if (childElement.name === 's3') {
725
- upload = this.parseS3Element(childElement);
727
+ upload = this.parseS3Element(
728
+ childElement,
729
+ projectTitle,
730
+ globalTags,
731
+ );
726
732
  } else if (childElement.name === 'instagram') {
727
733
  upload = this.parseInstagramElement(
728
734
  childElement,
@@ -881,7 +887,11 @@ export class HTMLProjectParser {
881
887
  /**
882
888
  * Parses a single <s3> element
883
889
  */
884
- private parseS3Element(element: Element): Upload | null {
890
+ private parseS3Element(
891
+ element: Element,
892
+ _projectTitle: string,
893
+ globalTags: string[],
894
+ ): Upload | null {
885
895
  const attrs = getAttrs(element);
886
896
 
887
897
  const name = attrs.get('name');
@@ -899,6 +909,7 @@ export class HTMLProjectParser {
899
909
  const paths = new Map<string, string>();
900
910
  let acl: string | undefined;
901
911
  let thumbnailTimecode: number | undefined;
912
+ const localTags: string[] = [];
902
913
 
903
914
  if ('children' in element && element.children) {
904
915
  for (const child of element.children) {
@@ -956,6 +967,13 @@ export class HTMLProjectParser {
956
967
  }
957
968
  break;
958
969
  }
970
+ case 'tag': {
971
+ const tagName = childAttrs.get('name');
972
+ if (tagName) {
973
+ localTags.push(tagName);
974
+ }
975
+ break;
976
+ }
959
977
  }
960
978
  }
961
979
  }
@@ -967,13 +985,16 @@ export class HTMLProjectParser {
967
985
  return null;
968
986
  }
969
987
 
988
+ // Merge global tags + local tags (global first)
989
+ const allTags = [...globalTags, ...localTags];
990
+
970
991
  return {
971
992
  name,
972
993
  tag: element.name, // "s3"
973
994
  outputName,
974
995
  privacy: 'private', // Default values for S3 (not used but required by Upload type)
975
996
  madeForKids: false,
976
- tags: [],
997
+ tags: allTags,
977
998
  category: '',
978
999
  language: '',
979
1000
  description: '',
@@ -1590,8 +1611,9 @@ export class HTMLProjectParser {
1590
1611
  // 3. Check enabled flag from display property
1591
1612
  const enabled = this.parseEnabled(styles['display']);
1592
1613
 
1593
- // 4. Extract container if present (first one only)
1614
+ // 4. Extract container or app if present (first one only, mutually exclusive)
1594
1615
  const container = this.extractFragmentContainer(element);
1616
+ const app = container ? undefined : this.extractFragmentApp(element);
1595
1617
 
1596
1618
  // 5. Parse trimLeft from -trim-start property
1597
1619
  const trimLeft = this.parseTrimStart(styles['-trim-start']);
@@ -1668,6 +1690,7 @@ export class HTMLProjectParser {
1668
1690
  chromakeyColor: chromakeyData.chromakeyColor,
1669
1691
  ...(visualFilter && { visualFilter }), // Add visualFilter if present
1670
1692
  ...(container && { container }), // Add container if present
1693
+ ...(app && { app }), // Add app if present
1671
1694
  ...(timecodeLabel && { timecodeLabel }), // Add timecode label if present
1672
1695
  };
1673
1696
  }
@@ -1722,6 +1745,49 @@ export class HTMLProjectParser {
1722
1745
  return undefined;
1723
1746
  }
1724
1747
 
1748
+ /**
1749
+ * Extracts the first <app> child from a fragment element.
1750
+ * The src attribute points to the app's dst directory (relative to project).
1751
+ * The data-parameters attribute is parsed as JSON and merged into query params.
1752
+ */
1753
+ private extractFragmentApp(element: Element): App | undefined {
1754
+ if (!('children' in element) || !element.children) {
1755
+ return undefined;
1756
+ }
1757
+
1758
+ for (const child of element.children) {
1759
+ if (child.type === 'tag' && child.name === 'app') {
1760
+ const appElement = child as Element;
1761
+
1762
+ const id =
1763
+ appElement.attribs?.id ||
1764
+ `app_${Math.random().toString(36).substring(2, 11)}`;
1765
+
1766
+ const src = appElement.attribs?.src ?? '';
1767
+
1768
+ let parameters: Record<string, string> = {};
1769
+ const dataParameters = appElement.attribs?.['data-parameters'];
1770
+ if (dataParameters) {
1771
+ try {
1772
+ const parsed = JSON.parse(dataParameters);
1773
+ // Convert all values to strings for query parameters
1774
+ for (const [key, value] of Object.entries(parsed)) {
1775
+ parameters[key] = String(value);
1776
+ }
1777
+ } catch {
1778
+ console.warn(
1779
+ `Warning: invalid JSON in data-parameters for app "${id}": ${dataParameters}`,
1780
+ );
1781
+ }
1782
+ }
1783
+
1784
+ return { id, src, parameters };
1785
+ }
1786
+ }
1787
+
1788
+ return undefined;
1789
+ }
1790
+
1725
1791
  /**
1726
1792
  * Serializes an element's children to HTML string
1727
1793
  */