@gannochenko/staticstripes 0.0.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.
Files changed (86) hide show
  1. package/.prettierrc +8 -0
  2. package/Makefile +69 -0
  3. package/dist/asset-manager.d.ts +16 -0
  4. package/dist/asset-manager.d.ts.map +1 -0
  5. package/dist/asset-manager.js +50 -0
  6. package/dist/asset-manager.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +257 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/container-renderer.d.ts +21 -0
  12. package/dist/container-renderer.d.ts.map +1 -0
  13. package/dist/container-renderer.js +149 -0
  14. package/dist/container-renderer.js.map +1 -0
  15. package/dist/expression-parser.d.ts +63 -0
  16. package/dist/expression-parser.d.ts.map +1 -0
  17. package/dist/expression-parser.js +145 -0
  18. package/dist/expression-parser.js.map +1 -0
  19. package/dist/ffmpeg.d.ts +375 -0
  20. package/dist/ffmpeg.d.ts.map +1 -0
  21. package/dist/ffmpeg.js +997 -0
  22. package/dist/ffmpeg.js.map +1 -0
  23. package/dist/ffprobe.d.ts +2 -0
  24. package/dist/ffprobe.d.ts.map +1 -0
  25. package/dist/ffprobe.js +31 -0
  26. package/dist/ffprobe.js.map +1 -0
  27. package/dist/html-parser.d.ts +56 -0
  28. package/dist/html-parser.d.ts.map +1 -0
  29. package/dist/html-parser.js +208 -0
  30. package/dist/html-parser.js.map +1 -0
  31. package/dist/html-project-parser.d.ts +169 -0
  32. package/dist/html-project-parser.d.ts.map +1 -0
  33. package/dist/html-project-parser.js +954 -0
  34. package/dist/html-project-parser.js.map +1 -0
  35. package/dist/index.d.ts +6 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +18 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/label-generator.d.ts +35 -0
  40. package/dist/label-generator.d.ts.map +1 -0
  41. package/dist/label-generator.js +69 -0
  42. package/dist/label-generator.js.map +1 -0
  43. package/dist/project.d.ts +29 -0
  44. package/dist/project.d.ts.map +1 -0
  45. package/dist/project.js +137 -0
  46. package/dist/project.js.map +1 -0
  47. package/dist/sample-sequences.d.ts +5 -0
  48. package/dist/sample-sequences.d.ts.map +1 -0
  49. package/dist/sample-sequences.js +199 -0
  50. package/dist/sample-sequences.js.map +1 -0
  51. package/dist/sample-streams.d.ts +2 -0
  52. package/dist/sample-streams.d.ts.map +1 -0
  53. package/dist/sample-streams.js +109 -0
  54. package/dist/sample-streams.js.map +1 -0
  55. package/dist/sequence.d.ts +21 -0
  56. package/dist/sequence.d.ts.map +1 -0
  57. package/dist/sequence.js +269 -0
  58. package/dist/sequence.js.map +1 -0
  59. package/dist/stream.d.ts +135 -0
  60. package/dist/stream.d.ts.map +1 -0
  61. package/dist/stream.js +779 -0
  62. package/dist/stream.js.map +1 -0
  63. package/dist/type.d.ts +73 -0
  64. package/dist/type.d.ts.map +1 -0
  65. package/dist/type.js +3 -0
  66. package/dist/type.js.map +1 -0
  67. package/eslint.config.js +44 -0
  68. package/package.json +50 -0
  69. package/src/asset-manager.ts +55 -0
  70. package/src/cli.ts +306 -0
  71. package/src/container-renderer.ts +190 -0
  72. package/src/expression-parser.test.ts +459 -0
  73. package/src/expression-parser.ts +199 -0
  74. package/src/ffmpeg.ts +1403 -0
  75. package/src/ffprobe.ts +29 -0
  76. package/src/html-parser.ts +221 -0
  77. package/src/html-project-parser.ts +1195 -0
  78. package/src/index.ts +9 -0
  79. package/src/label-generator.ts +74 -0
  80. package/src/project.ts +180 -0
  81. package/src/sample-sequences.ts +225 -0
  82. package/src/sample-streams.ts +142 -0
  83. package/src/sequence.ts +330 -0
  84. package/src/stream.ts +1012 -0
  85. package/src/type.ts +81 -0
  86. package/tsconfig.json +24 -0
package/.prettierrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "semi": true,
3
+ "trailingComma": "all",
4
+ "singleQuote": true,
5
+ "printWidth": 80,
6
+ "tabWidth": 2,
7
+ "arrowParens": "always"
8
+ }
package/Makefile ADDED
@@ -0,0 +1,69 @@
1
+ .PHONY: install build link unlink lint lint-fix format format-check clean test test-ui demo demo-all demo-prod demo-all-prod help
2
+
3
+ # Install dependencies
4
+ install:
5
+ npm install
6
+
7
+ # Build the project
8
+ build:
9
+ npm run build
10
+
11
+ # Link the package globally (makes 'staticstripes' command available)
12
+ link:
13
+ npm link
14
+
15
+ # Unlink the package globally (removes 'staticstripes' command)
16
+ unlink:
17
+ npm unlink -g
18
+
19
+ # Run linter
20
+ lint:
21
+ npm run lint
22
+
23
+ # Run linter with auto-fix
24
+ lint-fix:
25
+ npm run lint:fix
26
+
27
+ # Format code
28
+ format:
29
+ npm run format
30
+
31
+ # Check code formatting
32
+ format-check:
33
+ npm run format:check
34
+
35
+ # Run tests
36
+ test:
37
+ npm run test:run
38
+
39
+ # Run tests with UI
40
+ test-ui:
41
+ npm run test:ui
42
+
43
+ # Generate demo video (youtube output) with fast preset for development
44
+ demo:
45
+ node dist/cli.js generate -p ../../examples/demo -o youtube -d
46
+
47
+ # Generate demo video with production quality (medium preset)
48
+ demo-prod:
49
+ node dist/cli.js generate -p ../../examples/demo -o youtube
50
+
51
+ # Generate all demo outputs with fast preset
52
+ demo-all:
53
+ node dist/cli.js generate -p ../../examples/demo -d
54
+
55
+ # Generate all demo outputs with production quality
56
+ demo-all-prod:
57
+ node dist/cli.js generate -p ../../examples/demo
58
+
59
+ # Clean build artifacts and dependencies
60
+ clean:
61
+ rm -rf node_modules dist *.tsbuildinfo
62
+ rm -f package-lock.json
63
+
64
+ # Clean cache in demo project
65
+ clean-cache:
66
+ rm -rf ../../examples/demo/.cache
67
+
68
+ # Full build
69
+ all: install build
@@ -0,0 +1,16 @@
1
+ import { Label } from './ffmpeg';
2
+ import { Asset } from './type';
3
+ export declare class AssetManager {
4
+ private assets;
5
+ private assetIndexMap;
6
+ constructor(assets: Asset[]);
7
+ getAssetIndexMap(): Map<string, number>;
8
+ getAssetByName(name: string): Asset | undefined;
9
+ getVideoInputLabelByAssetName(name: string): Label;
10
+ getAudioInputLabelByAssetName(name: string): Label;
11
+ /**
12
+ * Adds a virtual asset (e.g., rendered container screenshot)
13
+ */
14
+ addVirtualAsset(asset: Asset): void;
15
+ }
16
+ //# sourceMappingURL=asset-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-manager.d.ts","sourceRoot":"","sources":["../src/asset-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,qBAAa,YAAY;IAGX,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,aAAa,CAAkC;gBAEnC,MAAM,EAAE,KAAK,EAAE;IAO5B,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;IAalD,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK;IASzD;;OAEG;IACI,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAQ3C"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AssetManager = void 0;
4
+ class AssetManager {
5
+ assets;
6
+ assetIndexMap = new Map();
7
+ constructor(assets) {
8
+ this.assets = assets;
9
+ let index = 0;
10
+ for (const asset of assets) {
11
+ this.assetIndexMap.set(asset.name, index++);
12
+ }
13
+ }
14
+ getAssetIndexMap() {
15
+ return this.assetIndexMap;
16
+ }
17
+ getAssetByName(name) {
18
+ return this.assets.find((assetItem) => assetItem.name === name);
19
+ }
20
+ getVideoInputLabelByAssetName(name) {
21
+ const assetIndex = this.assetIndexMap.get(name);
22
+ const asset = this.getAssetByName(name);
23
+ if (asset && asset.type === 'audio') {
24
+ throw new Error('trying to get video stream from an audio only asset');
25
+ }
26
+ return {
27
+ tag: `${assetIndex}:v`,
28
+ isAudio: false,
29
+ };
30
+ }
31
+ getAudioInputLabelByAssetName(name) {
32
+ const assetIndex = this.assetIndexMap.get(name);
33
+ return {
34
+ tag: `${assetIndex}:a`,
35
+ isAudio: true,
36
+ };
37
+ }
38
+ /**
39
+ * Adds a virtual asset (e.g., rendered container screenshot)
40
+ */
41
+ addVirtualAsset(asset) {
42
+ // Add to assets array
43
+ this.assets.push(asset);
44
+ // Assign next available index
45
+ const nextIndex = this.assetIndexMap.size;
46
+ this.assetIndexMap.set(asset.name, nextIndex);
47
+ }
48
+ }
49
+ exports.AssetManager = AssetManager;
50
+ //# sourceMappingURL=asset-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-manager.js","sourceRoot":"","sources":["../src/asset-manager.ts"],"names":[],"mappings":";;;AAGA,MAAa,YAAY;IAGH;IAFZ,aAAa,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEvD,YAAoB,MAAe;QAAf,WAAM,GAAN,MAAM,CAAS;QACjC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAEM,gBAAgB;QACrB,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAEM,cAAc,CAAC,IAAY;QAChC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAClE,CAAC;IAEM,6BAA6B,CAAC,IAAY;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QAED,OAAO;YACL,GAAG,EAAE,GAAG,UAAU,IAAI;YACtB,OAAO,EAAE,KAAK;SACf,CAAC;IACJ,CAAC;IAEM,6BAA6B,CAAC,IAAY;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEhD,OAAO;YACL,GAAG,EAAE,GAAG,UAAU,IAAI;YACtB,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,eAAe,CAAC,KAAY;QACjC,sBAAsB;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAExB,8BAA8B;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;QAC1C,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAChD,CAAC;CACF;AAnDD,oCAmDC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,257 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const path_1 = require("path");
6
+ const fs_1 = require("fs");
7
+ const path_2 = require("path");
8
+ const html_parser_js_1 = require("./html-parser.js");
9
+ const html_project_parser_js_1 = require("./html-project-parser.js");
10
+ const ffmpeg_js_1 = require("./ffmpeg.js");
11
+ const ffprobe_js_1 = require("./ffprobe.js");
12
+ const program = new commander_1.Command();
13
+ program
14
+ .name('staticstripes')
15
+ .description('CLI tool for rendering video projects')
16
+ .version('0.1.0');
17
+ program
18
+ .command('generate')
19
+ .description('Generate video output from a project')
20
+ .option('-p, --project <path>', 'Path to project directory', '.')
21
+ .option('-o, --output <name>', 'Output name to render (renders all if not specified)')
22
+ .option('-d, --dev', 'Use fast encoding preset for development (ultrafast)')
23
+ .action(async (options) => {
24
+ try {
25
+ // Check if FFmpeg is installed
26
+ console.log('🔍 Checking for FFmpeg...');
27
+ await (0, ffmpeg_js_1.checkFFmpegInstalled)();
28
+ console.log('✅ FFmpeg found\n');
29
+ // Resolve project path
30
+ const projectPath = (0, path_1.resolve)(process.cwd(), options.project);
31
+ const projectFilePath = (0, path_1.resolve)(projectPath, 'project.html');
32
+ // Validate project.html exists
33
+ if (!(0, fs_1.existsSync)(projectFilePath)) {
34
+ console.error(`Error: project.html not found in ${projectPath}`);
35
+ process.exit(1);
36
+ }
37
+ console.log(`📁 Project: ${projectPath}`);
38
+ console.log(`📄 Loading: ${projectFilePath}\n`);
39
+ // Parse the project HTML file
40
+ const parser = new html_project_parser_js_1.HTMLProjectParser(await new html_parser_js_1.HTMLParser().parseFile(projectFilePath), projectFilePath);
41
+ const project = await parser.parse();
42
+ // Determine which outputs to render
43
+ const allOutputs = Array.from(project.getOutputs().keys());
44
+ const outputsToRender = options.output ? [options.output] : allOutputs;
45
+ if (outputsToRender.length === 0) {
46
+ console.error('Error: No outputs defined in project.html');
47
+ process.exit(1);
48
+ }
49
+ // Validate requested output exists
50
+ if (options.output && !allOutputs.includes(options.output)) {
51
+ console.error(`Error: Output "${options.output}" not found in project.html`);
52
+ console.error(`Available outputs: ${allOutputs.join(', ')}`);
53
+ process.exit(1);
54
+ }
55
+ // Determine encoding preset based on -d flag
56
+ const preset = options.dev ? 'ultrafast' : 'medium';
57
+ console.log(`⚡ Encoding preset: ${preset}`);
58
+ console.log(`🎬 Rendering outputs: ${outputsToRender.join(', ')}\n`);
59
+ // Render each output
60
+ for (const outputName of outputsToRender) {
61
+ console.log(`\n${'='.repeat(60)}`);
62
+ console.log(`📹 Rendering: ${outputName}`);
63
+ console.log(`${'='.repeat(60)}\n`);
64
+ // Get output info and ensure output directory exists
65
+ const output = project.getOutput(outputName);
66
+ if (!output) {
67
+ throw new Error(`Output "${outputName}" not found`);
68
+ }
69
+ const outputDir = (0, path_1.dirname)(output.path);
70
+ if (!(0, fs_1.existsSync)(outputDir)) {
71
+ console.log(`📂 Creating output directory: ${outputDir}`);
72
+ (0, fs_1.mkdirSync)(outputDir, { recursive: true });
73
+ }
74
+ // Render containers for this output
75
+ await project.renderContainers(outputName);
76
+ // Print project statistics
77
+ project.printStats();
78
+ // Build filter graph
79
+ const filterBuf = await project.build(outputName);
80
+ const filter = filterBuf.render();
81
+ console.log('\n=== Filter Graph ===\n');
82
+ console.log(filter);
83
+ // Generate FFmpeg command with appropriate preset
84
+ const ffmpegCommand = (0, ffmpeg_js_1.makeFFmpegCommand)(project, filter, outputName, preset);
85
+ console.log('\n=== Starting Render ===\n');
86
+ // Run FFmpeg
87
+ await (0, ffmpeg_js_1.runFFMpeg)(ffmpegCommand);
88
+ const resultPath = output.path;
89
+ console.log(`\n✅ Output file: ${resultPath}`);
90
+ const resultDuration = await (0, ffprobe_js_1.getAssetDuration)(resultPath);
91
+ console.log(`⏱️ Duration: ${resultDuration}ms`);
92
+ }
93
+ console.log('\n🎉 All outputs rendered successfully!\n');
94
+ }
95
+ catch (error) {
96
+ console.error('\n❌ Error:', error);
97
+ process.exit(1);
98
+ }
99
+ });
100
+ program
101
+ .command('upload')
102
+ .description('Upload video to platforms (not yet implemented)')
103
+ .option('-p, --project <path>', 'Path to project directory', '.')
104
+ .option('-u, --upload <platform>', 'Platform to upload to (e.g., youtube)')
105
+ .action(() => {
106
+ console.log('Upload command is not yet implemented.');
107
+ console.log('This feature will allow uploading videos to platforms like YouTube.');
108
+ process.exit(0);
109
+ });
110
+ program
111
+ .command('bootstrap')
112
+ .description('Create a new project from template')
113
+ .requiredOption('-n, --name <name>', 'Name of the new project')
114
+ .action((options) => {
115
+ try {
116
+ const projectName = options.name;
117
+ const targetPath = (0, path_1.resolve)(process.cwd(), projectName);
118
+ // Check if target directory already exists
119
+ if ((0, fs_1.existsSync)(targetPath)) {
120
+ console.error(`Error: Directory "${projectName}" already exists`);
121
+ process.exit(1);
122
+ }
123
+ // Get the template path (relative to the CLI script location)
124
+ // When built, cli.js is in apps/renderer/dist/, and template is at ../../../examples/template
125
+ // Use realpathSync to resolve symlinks when globally linked via npm link
126
+ const scriptPath = (0, fs_1.realpathSync)(process.argv[1]);
127
+ const scriptDir = (0, path_1.dirname)(scriptPath);
128
+ const templatePath = (0, path_1.resolve)(scriptDir, '../../../examples/template');
129
+ // Validate template exists
130
+ if (!(0, fs_1.existsSync)(templatePath)) {
131
+ console.error(`Error: Template directory not found at ${templatePath}`);
132
+ process.exit(1);
133
+ }
134
+ console.log(`📦 Creating new project "${projectName}"...`);
135
+ console.log(`📂 Template: ${templatePath}`);
136
+ console.log(`🎯 Target: ${targetPath}\n`);
137
+ // Create target directory and copy template contents
138
+ (0, fs_1.mkdirSync)(targetPath, { recursive: true });
139
+ (0, fs_1.cpSync)(templatePath, targetPath, { recursive: true });
140
+ console.log(`✅ Project "${projectName}" created successfully!\n`);
141
+ console.log('Next steps:');
142
+ console.log(` cd ${projectName}`);
143
+ console.log(' # Edit project.html to customize your video');
144
+ console.log(` staticstripes generate -p . -o youtube -d\n`);
145
+ }
146
+ catch (error) {
147
+ console.error('\n❌ Error:', error);
148
+ process.exit(1);
149
+ }
150
+ });
151
+ program
152
+ .command('add-assets')
153
+ .description('Scan for media files and add them as assets to project.html')
154
+ .option('-p, --project <path>', 'Path to project directory', '.')
155
+ .action((options) => {
156
+ try {
157
+ // Resolve project path
158
+ const projectPath = (0, path_1.resolve)(process.cwd(), options.project);
159
+ const projectFilePath = (0, path_1.resolve)(projectPath, 'project.html');
160
+ // Validate project.html exists
161
+ if (!(0, fs_1.existsSync)(projectFilePath)) {
162
+ console.error(`Error: project.html not found in ${projectPath}`);
163
+ process.exit(1);
164
+ }
165
+ console.log(`📁 Project: ${projectPath}`);
166
+ console.log(`📄 Scanning for media files...\n`);
167
+ // Find all media files recursively
168
+ const mediaFiles = [];
169
+ const scanDirectory = (dir) => {
170
+ const entries = (0, fs_1.readdirSync)(dir);
171
+ for (const entry of entries) {
172
+ const fullPath = (0, path_2.join)(dir, entry);
173
+ const stat = (0, fs_1.statSync)(fullPath);
174
+ if (stat.isDirectory()) {
175
+ scanDirectory(fullPath);
176
+ }
177
+ else {
178
+ const ext = entry.toLowerCase().split('.').pop();
179
+ let type = null;
180
+ if (ext === 'mp4') {
181
+ type = 'video';
182
+ }
183
+ else if (ext === 'mp3') {
184
+ type = 'audio';
185
+ }
186
+ else if (ext === 'jpg' || ext === 'png') {
187
+ type = 'image';
188
+ }
189
+ if (type) {
190
+ const relativePath = (0, path_1.relative)(projectPath, fullPath);
191
+ mediaFiles.push({ path: fullPath, relativePath, type });
192
+ }
193
+ }
194
+ }
195
+ };
196
+ scanDirectory(projectPath);
197
+ // Sort by relative path (name)
198
+ mediaFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
199
+ // Group by type and assign names
200
+ const videos = mediaFiles.filter(f => f.type === 'video');
201
+ const audios = mediaFiles.filter(f => f.type === 'audio');
202
+ const images = mediaFiles.filter(f => f.type === 'image');
203
+ console.log(`Found ${videos.length} video(s), ${audios.length} audio(s), ${images.length} image(s)\n`);
204
+ if (mediaFiles.length === 0) {
205
+ console.log('No media files found.');
206
+ process.exit(0);
207
+ }
208
+ // Generate asset tags
209
+ const assetTags = [];
210
+ videos.forEach((file, index) => {
211
+ const name = `clip_${index + 1}`;
212
+ assetTags.push(` <asset data-name="${name}" data-path="./${file.relativePath}" />`);
213
+ console.log(`${name}: ${file.relativePath}`);
214
+ });
215
+ audios.forEach((file, index) => {
216
+ const name = `track_${index + 1}`;
217
+ assetTags.push(` <asset data-name="${name}" data-path="./${file.relativePath}" />`);
218
+ console.log(`${name}: ${file.relativePath}`);
219
+ });
220
+ images.forEach((file, index) => {
221
+ const name = `image_${index + 1}`;
222
+ assetTags.push(` <asset data-name="${name}" data-path="./${file.relativePath}" />`);
223
+ console.log(`${name}: ${file.relativePath}`);
224
+ });
225
+ // Read project.html
226
+ let content = (0, fs_1.readFileSync)(projectFilePath, 'utf-8');
227
+ // Check if <assets> section exists
228
+ const assetsMatch = content.match(/<assets>([\s\S]*?)<\/assets>/);
229
+ if (assetsMatch) {
230
+ // Replace existing assets section
231
+ const newAssetsSection = `<assets>\n${assetTags.join('\n')}\n</assets>`;
232
+ content = content.replace(/<assets>[\s\S]*?<\/assets>/, newAssetsSection);
233
+ }
234
+ else {
235
+ // Add assets section before </project> or at the end
236
+ const newAssetsSection = `\n<assets>\n${assetTags.join('\n')}\n</assets>\n`;
237
+ if (content.includes('</outputs>')) {
238
+ content = content.replace('</outputs>', `</outputs>${newAssetsSection}`);
239
+ }
240
+ else if (content.includes('</style>')) {
241
+ content = content.replace('</style>', `</style>${newAssetsSection}`);
242
+ }
243
+ else {
244
+ content += newAssetsSection;
245
+ }
246
+ }
247
+ // Write back to project.html
248
+ (0, fs_1.writeFileSync)(projectFilePath, content, 'utf-8');
249
+ console.log(`\n✅ Assets added to ${projectFilePath}`);
250
+ }
251
+ catch (error) {
252
+ console.error('\n❌ Error:', error);
253
+ process.exit(1);
254
+ }
255
+ });
256
+ program.parse(process.argv);
257
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { Container } from './type';
2
+ export interface RenderContainerOptions {
3
+ container: Container;
4
+ cssText: string;
5
+ width: number;
6
+ height: number;
7
+ projectDir: string;
8
+ }
9
+ export interface ContainerRenderResult {
10
+ container: Container;
11
+ screenshotPath: string;
12
+ }
13
+ /**
14
+ * Renders a container to a PNG screenshot using Puppeteer
15
+ */
16
+ export declare function renderContainer(options: RenderContainerOptions): Promise<ContainerRenderResult>;
17
+ /**
18
+ * Renders multiple containers in sequence
19
+ */
20
+ export declare function renderContainers(containers: Container[], cssText: string, width: number, height: number, projectDir: string): Promise<ContainerRenderResult[]>;
21
+ //# sourceMappingURL=container-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-renderer.d.ts","sourceRoot":"","sources":["../src/container-renderer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAYD;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAyFhC;AAgCD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,SAAS,EAAE,EACvB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAwBlC"}
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.renderContainer = renderContainer;
7
+ exports.renderContainers = renderContainers;
8
+ const puppeteer_1 = __importDefault(require("puppeteer"));
9
+ const promises_1 = require("fs/promises");
10
+ const path_1 = require("path");
11
+ const fs_1 = require("fs");
12
+ const crypto_1 = require("crypto");
13
+ /**
14
+ * Generates a hash from container content and CSS
15
+ */
16
+ function generateCacheKey(containerHtml, cssText) {
17
+ const hash = (0, crypto_1.createHash)('sha256');
18
+ hash.update(containerHtml);
19
+ hash.update(cssText);
20
+ return hash.digest('hex').substring(0, 16);
21
+ }
22
+ /**
23
+ * Renders a container to a PNG screenshot using Puppeteer
24
+ */
25
+ async function renderContainer(options) {
26
+ const { container, cssText, width, height, projectDir } = options;
27
+ // Create cache directory
28
+ const cacheDir = (0, path_1.resolve)(projectDir, '.cache', 'containers');
29
+ if (!(0, fs_1.existsSync)(cacheDir)) {
30
+ await (0, promises_1.mkdir)(cacheDir, { recursive: true });
31
+ }
32
+ // Generate cache key from content hash
33
+ const cacheKey = generateCacheKey(container.htmlContent, cssText);
34
+ const screenshotPath = (0, path_1.resolve)(cacheDir, `${cacheKey}.png`);
35
+ // Check if cached version exists
36
+ if ((0, fs_1.existsSync)(screenshotPath)) {
37
+ console.log(`Using cached container "${container.id}" (hash: ${cacheKey}) from ${screenshotPath}`);
38
+ return {
39
+ container,
40
+ screenshotPath,
41
+ };
42
+ }
43
+ // Build complete HTML document
44
+ const html = `
45
+ <!DOCTYPE html>
46
+ <html>
47
+ <head>
48
+ <meta charset="UTF-8">
49
+ <style>
50
+ * {
51
+ margin: 0;
52
+ padding: 0;
53
+ box-sizing: border-box;
54
+ }
55
+ body {
56
+ width: ${width}px;
57
+ height: ${height}px;
58
+ overflow: hidden;
59
+ background: transparent;
60
+ font-size: 16px;
61
+ }
62
+ ${cssText}
63
+ </style>
64
+ </head>
65
+ <body>
66
+ ${container.htmlContent}
67
+ </body>
68
+ </html>
69
+ `.trim();
70
+ // Launch browser and render
71
+ const browser = await puppeteer_1.default.launch({
72
+ headless: true,
73
+ args: ['--no-sandbox', '--disable-setuid-sandbox'],
74
+ });
75
+ try {
76
+ const page = await browser.newPage();
77
+ await page.setViewport({ width, height });
78
+ await page.setContent(html, { waitUntil: 'networkidle0' });
79
+ // Take screenshot with transparent background
80
+ const screenshot = await page.screenshot({
81
+ type: 'png',
82
+ omitBackground: true,
83
+ clip: {
84
+ x: 0,
85
+ y: 0,
86
+ width,
87
+ height,
88
+ },
89
+ });
90
+ // Save to file
91
+ await (0, promises_1.writeFile)(screenshotPath, screenshot);
92
+ console.log(`Rendered container "${container.id}" (hash: ${cacheKey}) to ${screenshotPath}`);
93
+ return {
94
+ container,
95
+ screenshotPath,
96
+ };
97
+ }
98
+ finally {
99
+ await browser.close();
100
+ }
101
+ }
102
+ /**
103
+ * Cleans up stale cache entries that are not in the active set
104
+ */
105
+ async function cleanupStaleCache(cacheDir, activeCacheKeys) {
106
+ if (!(0, fs_1.existsSync)(cacheDir)) {
107
+ return;
108
+ }
109
+ const files = await (0, promises_1.readdir)(cacheDir);
110
+ const pngFiles = files.filter((file) => file.endsWith('.png'));
111
+ let removedCount = 0;
112
+ for (const file of pngFiles) {
113
+ const cacheKey = file.replace('.png', '');
114
+ if (!activeCacheKeys.has(cacheKey)) {
115
+ const filePath = (0, path_1.resolve)(cacheDir, file);
116
+ await (0, promises_1.unlink)(filePath);
117
+ console.log(`Removed stale cache entry: ${file}`);
118
+ removedCount++;
119
+ }
120
+ }
121
+ if (removedCount > 0) {
122
+ console.log(`Cleaned up ${removedCount} stale cache entries`);
123
+ }
124
+ }
125
+ /**
126
+ * Renders multiple containers in sequence
127
+ */
128
+ async function renderContainers(containers, cssText, width, height, projectDir) {
129
+ const results = [];
130
+ const activeCacheKeys = new Set();
131
+ // Render all containers and collect active cache keys
132
+ for (const container of containers) {
133
+ const cacheKey = generateCacheKey(container.htmlContent, cssText);
134
+ activeCacheKeys.add(cacheKey);
135
+ const result = await renderContainer({
136
+ container,
137
+ cssText,
138
+ width,
139
+ height,
140
+ projectDir,
141
+ });
142
+ results.push(result);
143
+ }
144
+ // Clean up stale cache entries
145
+ const cacheDir = (0, path_1.resolve)(projectDir, '.cache', 'containers');
146
+ await cleanupStaleCache(cacheDir, activeCacheKeys);
147
+ return results;
148
+ }
149
+ //# sourceMappingURL=container-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-renderer.js","sourceRoot":"","sources":["../src/container-renderer.ts"],"names":[],"mappings":"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"}