@gannochenko/staticstripes 0.0.12 ā 0.0.15
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/Makefile +20 -0
- package/dist/asset-manager.d.ts +1 -0
- package/dist/asset-manager.d.ts.map +1 -1
- package/dist/asset-manager.js +3 -0
- package/dist/asset-manager.js.map +1 -1
- package/dist/cli/ai-generation-strategy-factory.d.ts +23 -0
- package/dist/cli/ai-generation-strategy-factory.d.ts.map +1 -0
- package/dist/cli/ai-generation-strategy-factory.js +44 -0
- package/dist/cli/ai-generation-strategy-factory.js.map +1 -0
- package/dist/cli/ai-generation-strategy.d.ts +33 -0
- package/dist/cli/ai-generation-strategy.d.ts.map +1 -0
- package/dist/cli/ai-generation-strategy.js +3 -0
- package/dist/cli/ai-generation-strategy.js.map +1 -0
- package/dist/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.d.ts +38 -0
- package/dist/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.d.ts.map +1 -0
- package/dist/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.js +174 -0
- package/dist/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.js.map +1 -0
- package/dist/cli/auth-strategy-factory.d.ts +31 -0
- package/dist/cli/auth-strategy-factory.d.ts.map +1 -0
- package/dist/cli/auth-strategy-factory.js +61 -0
- package/dist/cli/auth-strategy-factory.js.map +1 -0
- package/dist/cli/auth-strategy.d.ts +31 -0
- package/dist/cli/auth-strategy.d.ts.map +1 -0
- package/dist/cli/auth-strategy.js +3 -0
- package/dist/cli/auth-strategy.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +6 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +103 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +69 -2
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/instagram/instagram-auth-strategy.d.ts +31 -0
- package/dist/cli/instagram/instagram-auth-strategy.d.ts.map +1 -0
- package/dist/cli/instagram/instagram-auth-strategy.js +505 -0
- package/dist/cli/instagram/instagram-auth-strategy.js.map +1 -0
- package/dist/cli/instagram/instagram-upload-strategy.d.ts +45 -0
- package/dist/cli/instagram/instagram-upload-strategy.d.ts.map +1 -0
- package/dist/cli/instagram/instagram-upload-strategy.js +303 -0
- package/dist/cli/instagram/instagram-upload-strategy.js.map +1 -0
- package/dist/cli/s3/s3-upload-strategy.d.ts.map +1 -1
- package/dist/cli/s3/s3-upload-strategy.js +7 -3
- package/dist/cli/s3/s3-upload-strategy.js.map +1 -1
- package/dist/cli/upload-strategy-factory.d.ts +1 -1
- package/dist/cli/upload-strategy-factory.d.ts.map +1 -1
- package/dist/cli/upload-strategy-factory.js +5 -5
- package/dist/cli/upload-strategy-factory.js.map +1 -1
- package/dist/cli/youtube/youtube-auth-strategy.d.ts +11 -0
- package/dist/cli/youtube/youtube-auth-strategy.d.ts.map +1 -0
- package/dist/cli/youtube/youtube-auth-strategy.js +320 -0
- package/dist/cli/youtube/youtube-auth-strategy.js.map +1 -0
- package/dist/cli/youtube/youtube-upload-strategy.d.ts +10 -3
- package/dist/cli/youtube/youtube-upload-strategy.d.ts.map +1 -1
- package/dist/cli/youtube/youtube-upload-strategy.js +96 -16
- package/dist/cli/youtube/youtube-upload-strategy.js.map +1 -1
- package/dist/cli.js +2 -3
- package/dist/cli.js.map +1 -1
- package/dist/html-project-parser.d.ts +40 -1
- package/dist/html-project-parser.d.ts.map +1 -1
- package/dist/html-project-parser.js +343 -9
- package/dist/html-project-parser.js.map +1 -1
- package/dist/lib/file.d.ts +2 -0
- package/dist/lib/file.d.ts.map +1 -0
- package/dist/lib/file.js +13 -0
- package/dist/lib/file.js.map +1 -0
- package/dist/lib/net.d.ts +19 -0
- package/dist/lib/net.d.ts.map +1 -0
- package/dist/lib/net.js +101 -0
- package/dist/lib/net.js.map +1 -0
- package/dist/project.d.ts +5 -2
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +9 -1
- package/dist/project.js.map +1 -1
- package/dist/type.d.ts +17 -0
- package/dist/type.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/asset-manager.ts +4 -0
- package/src/cli/ai-generation-strategy-factory.ts +48 -0
- package/src/cli/ai-generation-strategy.ts +35 -0
- package/src/cli/ai-music-api-ai/ai-music-api-ai-generation-strategy.ts +266 -0
- package/src/cli/auth-strategy-factory.ts +67 -0
- package/src/cli/auth-strategy.ts +37 -0
- package/src/cli/commands/auth.ts +120 -0
- package/src/cli/commands/generate.ts +55 -2
- package/src/cli/instagram/instagram-auth-strategy.ts +569 -0
- package/src/cli/instagram/instagram-upload-strategy.ts +398 -0
- package/src/cli/s3/s3-upload-strategy.ts +7 -3
- package/src/cli/upload-strategy-factory.ts +6 -9
- package/src/cli/youtube/youtube-auth-strategy.ts +323 -0
- package/src/cli/youtube/youtube-upload-strategy.ts +147 -16
- package/src/cli.ts +2 -4
- package/src/html-project-parser.ts +429 -8
- package/src/lib/file.ts +11 -0
- package/src/lib/net.ts +120 -0
- package/src/project.ts +10 -0
- package/src/type.ts +19 -0
- package/dist/cli/youtube/auth-commands.d.ts +0 -3
- package/dist/cli/youtube/auth-commands.d.ts.map +0 -1
- package/dist/cli/youtube/auth-commands.js +0 -273
- package/dist/cli/youtube/auth-commands.js.map +0 -1
- package/dist/cli/youtube/cli.d.ts +0 -7
- package/dist/cli/youtube/cli.d.ts.map +0 -1
- package/dist/cli/youtube/cli.js +0 -13
- package/dist/cli/youtube/cli.js.map +0 -1
- package/dist/cli/youtube/upload-handler.d.ts +0 -12
- package/dist/cli/youtube/upload-handler.d.ts.map +0 -1
- package/dist/cli/youtube/upload-handler.js +0 -66
- package/dist/cli/youtube/upload-handler.js.map +0 -1
- package/src/cli/youtube/auth-commands.ts +0 -312
- package/src/cli/youtube/cli.ts +0 -11
- package/src/cli/youtube/upload-handler.ts +0 -101
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.YouTubeAuthStrategy = void 0;
|
|
40
|
+
const youtube_uploader_js_1 = require("../../youtube-uploader.js");
|
|
41
|
+
const open_1 = __importDefault(require("open"));
|
|
42
|
+
const http_1 = __importDefault(require("http"));
|
|
43
|
+
const url_1 = require("url");
|
|
44
|
+
const readline = __importStar(require("readline"));
|
|
45
|
+
const fs_1 = require("fs");
|
|
46
|
+
const path_1 = require("path");
|
|
47
|
+
/**
|
|
48
|
+
* YouTube authentication strategy
|
|
49
|
+
* Uses OAuth 2.0 flow with local callback server
|
|
50
|
+
*/
|
|
51
|
+
class YouTubeAuthStrategy {
|
|
52
|
+
getTag() {
|
|
53
|
+
return 'youtube';
|
|
54
|
+
}
|
|
55
|
+
async execute(uploadName, projectPath, _options) {
|
|
56
|
+
console.log(`š YouTube Authentication Setup\n`);
|
|
57
|
+
const rl = readline.createInterface({
|
|
58
|
+
input: process.stdin,
|
|
59
|
+
output: process.stdout,
|
|
60
|
+
});
|
|
61
|
+
const question = (prompt) => {
|
|
62
|
+
return new Promise((resolve) => {
|
|
63
|
+
rl.question(prompt, (answer) => {
|
|
64
|
+
resolve(answer);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
try {
|
|
69
|
+
console.log('ā'.repeat(60));
|
|
70
|
+
console.log('STEP 1: Enter YouTube API Credentials');
|
|
71
|
+
console.log('ā'.repeat(60));
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log('š” Run `staticstripes auth-help youtube` for setup instructions\n');
|
|
74
|
+
const clientId = await question('Enter your OAuth Client ID: ');
|
|
75
|
+
if (!clientId || clientId.trim().length < 10) {
|
|
76
|
+
throw new Error('Invalid Client ID');
|
|
77
|
+
}
|
|
78
|
+
const clientSecret = await question('Enter your OAuth Client Secret: ');
|
|
79
|
+
if (!clientSecret || clientSecret.trim().length < 10) {
|
|
80
|
+
throw new Error('Invalid Client Secret');
|
|
81
|
+
}
|
|
82
|
+
console.log('\nā'.repeat(60));
|
|
83
|
+
console.log('STEP 2: Authorize with Google');
|
|
84
|
+
console.log('ā'.repeat(60));
|
|
85
|
+
console.log('');
|
|
86
|
+
rl.close();
|
|
87
|
+
// Create uploader instance
|
|
88
|
+
const uploader = new youtube_uploader_js_1.YouTubeUploader(clientId.trim(), clientSecret.trim());
|
|
89
|
+
// Get authorization URL
|
|
90
|
+
const authUrl = uploader.getAuthUrl();
|
|
91
|
+
console.log('š Starting local server on http://localhost:3000...\n');
|
|
92
|
+
// Create a promise that resolves when we get the OAuth callback
|
|
93
|
+
const authPromise = new Promise((resolve, reject) => {
|
|
94
|
+
// Track all connections to force-close them
|
|
95
|
+
const connections = new Set();
|
|
96
|
+
const server = http_1.default.createServer((req, res) => {
|
|
97
|
+
const url = (0, url_1.parse)(req.url || '', true);
|
|
98
|
+
if (url.pathname === '/oauth2callback') {
|
|
99
|
+
const code = url.query.code;
|
|
100
|
+
const error = url.query.error;
|
|
101
|
+
const closeServer = () => {
|
|
102
|
+
// Destroy all connections
|
|
103
|
+
connections.forEach((socket) => {
|
|
104
|
+
socket.destroy();
|
|
105
|
+
});
|
|
106
|
+
connections.clear();
|
|
107
|
+
server.close();
|
|
108
|
+
};
|
|
109
|
+
if (error) {
|
|
110
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
111
|
+
res.end(`
|
|
112
|
+
<html>
|
|
113
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
114
|
+
<h1>ā Authorization Failed</h1>
|
|
115
|
+
<p>Error: ${error}</p>
|
|
116
|
+
<p>You can close this window.</p>
|
|
117
|
+
</body>
|
|
118
|
+
</html>
|
|
119
|
+
`);
|
|
120
|
+
res.on('finish', closeServer);
|
|
121
|
+
reject(new Error(`Authorization failed: ${error}`));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (code) {
|
|
125
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
126
|
+
res.end(`
|
|
127
|
+
<html>
|
|
128
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
129
|
+
<h1>Authorization Successful!</h1>
|
|
130
|
+
<p>You can close this window and return to the terminal.</p>
|
|
131
|
+
</body>
|
|
132
|
+
</html>
|
|
133
|
+
`);
|
|
134
|
+
res.on('finish', closeServer);
|
|
135
|
+
resolve(code);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
139
|
+
res.end(`
|
|
140
|
+
<html>
|
|
141
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
142
|
+
<h1>ā No Authorization Code</h1>
|
|
143
|
+
<p>No code was received from Google.</p>
|
|
144
|
+
<p>You can close this window.</p>
|
|
145
|
+
</body>
|
|
146
|
+
</html>
|
|
147
|
+
`);
|
|
148
|
+
res.on('finish', closeServer);
|
|
149
|
+
reject(new Error('No authorization code received'));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
res.writeHead(404);
|
|
154
|
+
res.end('Not found');
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// Track connections
|
|
158
|
+
server.on('connection', (socket) => {
|
|
159
|
+
connections.add(socket);
|
|
160
|
+
socket.on('close', () => {
|
|
161
|
+
connections.delete(socket);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
server.listen(3000, () => {
|
|
165
|
+
console.log('ā
Server started successfully\n');
|
|
166
|
+
});
|
|
167
|
+
// Set timeout to avoid hanging forever
|
|
168
|
+
setTimeout(() => {
|
|
169
|
+
connections.forEach((socket) => {
|
|
170
|
+
socket.destroy();
|
|
171
|
+
});
|
|
172
|
+
connections.clear();
|
|
173
|
+
server.close();
|
|
174
|
+
reject(new Error('Authentication timeout (5 minutes)'));
|
|
175
|
+
}, 5 * 60 * 1000);
|
|
176
|
+
});
|
|
177
|
+
console.log('š Opening browser for authorization...\n');
|
|
178
|
+
// Open browser automatically
|
|
179
|
+
try {
|
|
180
|
+
await (0, open_1.default)(authUrl);
|
|
181
|
+
console.log('ā
Browser opened successfully\n');
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
console.log('ā ļø Could not open browser automatically');
|
|
185
|
+
console.log('š Please visit this URL to authorize:\n');
|
|
186
|
+
console.log(authUrl);
|
|
187
|
+
console.log();
|
|
188
|
+
}
|
|
189
|
+
console.log('ā³ Waiting for authorization...\n');
|
|
190
|
+
// Wait for the OAuth callback
|
|
191
|
+
const code = await authPromise;
|
|
192
|
+
console.log('š Authorization code received\n');
|
|
193
|
+
console.log('š¾ Saving authentication tokens...\n');
|
|
194
|
+
// Complete authentication - saves OAuth tokens to .auth file
|
|
195
|
+
await uploader.authenticate(code, uploadName, projectPath);
|
|
196
|
+
// Now add clientId and clientSecret to the saved file
|
|
197
|
+
const authDir = (0, path_1.resolve)(projectPath, '.auth');
|
|
198
|
+
const credentialsPath = (0, path_1.resolve)(authDir, `${uploadName}.json`);
|
|
199
|
+
// Read the tokens that were just saved
|
|
200
|
+
const { readFileSync } = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
201
|
+
const savedTokens = JSON.parse(readFileSync(credentialsPath, 'utf-8'));
|
|
202
|
+
// Add clientId and clientSecret
|
|
203
|
+
const fullCredentials = {
|
|
204
|
+
clientId: clientId.trim(),
|
|
205
|
+
clientSecret: clientSecret.trim(),
|
|
206
|
+
...savedTokens,
|
|
207
|
+
};
|
|
208
|
+
// Save back with all credentials
|
|
209
|
+
(0, fs_1.writeFileSync)(credentialsPath, JSON.stringify(fullCredentials, null, 2), 'utf-8');
|
|
210
|
+
console.log(`ā
Authentication complete for ${uploadName}!\n`);
|
|
211
|
+
console.log(`š Credentials saved to: ${credentialsPath}\n`);
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
getSetupInstructions() {
|
|
218
|
+
return `
|
|
219
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
220
|
+
YouTube Authentication Setup
|
|
221
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
222
|
+
|
|
223
|
+
Interactive OAuth 2.0 flow - no environment variables needed!
|
|
224
|
+
|
|
225
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
226
|
+
STEP 1: Go to Google Cloud Console
|
|
227
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
228
|
+
URL: https://console.cloud.google.com/
|
|
229
|
+
|
|
230
|
+
1. Create or select a project
|
|
231
|
+
|
|
232
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
233
|
+
STEP 2: Enable YouTube Data API v3
|
|
234
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
235
|
+
1. Go to "APIs & Services" > "Library"
|
|
236
|
+
2. Search for "YouTube Data API v3"
|
|
237
|
+
3. Click "Enable"
|
|
238
|
+
|
|
239
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
240
|
+
STEP 3: Configure OAuth Consent Screen
|
|
241
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
242
|
+
1. Go to "APIs & Services" > "OAuth consent screen"
|
|
243
|
+
2. Choose "External" user type
|
|
244
|
+
3. Fill in:
|
|
245
|
+
⢠App name: "My YouTube Uploader"
|
|
246
|
+
⢠User support email: your.email@example.com
|
|
247
|
+
⢠Developer contact email: your.email@example.com
|
|
248
|
+
4. Click "Save and Continue"
|
|
249
|
+
5. Add scope: https://www.googleapis.com/auth/youtube.upload
|
|
250
|
+
6. Click "Save and Continue"
|
|
251
|
+
7. Add your email as a test user
|
|
252
|
+
8. Click "Save and Continue"
|
|
253
|
+
|
|
254
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
255
|
+
STEP 4: Create OAuth 2.0 Credentials
|
|
256
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
257
|
+
1. Go to "APIs & Services" > "Credentials"
|
|
258
|
+
2. Click "Create Credentials" > "OAuth client ID"
|
|
259
|
+
3. Choose "Web application"
|
|
260
|
+
4. Name: "YouTube Uploader"
|
|
261
|
+
5. Add redirect URI: http://localhost:3000/oauth2callback
|
|
262
|
+
(Make sure it's exactly this - no trailing slash!)
|
|
263
|
+
6. Click "Create"
|
|
264
|
+
7. Copy your Client ID (looks like: xxx.apps.googleusercontent.com)
|
|
265
|
+
8. Copy your Client Secret
|
|
266
|
+
|
|
267
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
268
|
+
STEP 5: Publish Your OAuth App (IMPORTANT!)
|
|
269
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
270
|
+
1. Go to "APIs & Services" > "OAuth consent screen"
|
|
271
|
+
2. Click "PUBLISH APP" button
|
|
272
|
+
3. This makes refresh tokens permanent (otherwise they expire in 7 days)
|
|
273
|
+
4. Note: For personal use, you don't need Google verification
|
|
274
|
+
|
|
275
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
276
|
+
STEP 6: Run Authentication Wizard
|
|
277
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
278
|
+
Run:
|
|
279
|
+
staticstripes auth --upload-name YOUR_UPLOAD_NAME
|
|
280
|
+
|
|
281
|
+
The wizard will:
|
|
282
|
+
1. Ask you to enter your OAuth Client ID
|
|
283
|
+
2. Ask you to enter your OAuth Client Secret
|
|
284
|
+
3. Start local server on port 3000
|
|
285
|
+
4. Open browser automatically for Google authorization
|
|
286
|
+
5. Automatically exchange authorization code for tokens
|
|
287
|
+
6. Save ALL credentials to .auth/YOUR_UPLOAD_NAME.json
|
|
288
|
+
|
|
289
|
+
Done! Interactive and secure - no environment variables needed!
|
|
290
|
+
|
|
291
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
292
|
+
TROUBLESHOOTING
|
|
293
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
294
|
+
ā "redirect_uri_mismatch"
|
|
295
|
+
ā Make sure redirect URI is exactly: http://localhost:3000/oauth2callback
|
|
296
|
+
ā No trailing slash, no typos!
|
|
297
|
+
|
|
298
|
+
ā "Invalid client" error
|
|
299
|
+
ā Double-check your Client ID and Client Secret
|
|
300
|
+
ā Make sure you copied them correctly
|
|
301
|
+
|
|
302
|
+
ā Tokens expire after 7 days
|
|
303
|
+
ā Publish your OAuth app (Step 5)
|
|
304
|
+
ā This makes refresh tokens last indefinitely
|
|
305
|
+
|
|
306
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
307
|
+
REFERENCE LINKS
|
|
308
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
309
|
+
⢠Google Cloud Console:
|
|
310
|
+
https://console.cloud.google.com/
|
|
311
|
+
|
|
312
|
+
⢠YouTube Data API docs:
|
|
313
|
+
https://developers.google.com/youtube/v3
|
|
314
|
+
|
|
315
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
316
|
+
`;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
exports.YouTubeAuthStrategy = YouTubeAuthStrategy;
|
|
320
|
+
//# sourceMappingURL=youtube-auth-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"youtube-auth-strategy.js","sourceRoot":"","sources":["../../../src/cli/youtube/youtube-auth-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { UploadStrategy } from '../upload-strategy';
|
|
2
2
|
import { Project } from '../../project';
|
|
3
3
|
import { YouTubeUpload } from '../../type';
|
|
4
|
+
export interface YouTubeUploadOptions {
|
|
5
|
+
uploadName: string;
|
|
6
|
+
projectPath: string;
|
|
7
|
+
clientId: string;
|
|
8
|
+
clientSecret: string;
|
|
9
|
+
}
|
|
4
10
|
/**
|
|
5
11
|
* YouTube upload strategy implementation
|
|
6
12
|
*/
|
|
7
13
|
export declare class YouTubeUploadStrategy implements UploadStrategy {
|
|
8
|
-
private clientId;
|
|
9
|
-
private clientSecret;
|
|
10
|
-
constructor(clientId: string, clientSecret: string);
|
|
11
14
|
getTag(): string;
|
|
12
15
|
validate(): void;
|
|
13
16
|
execute(project: Project, upload: YouTubeUpload, projectPath: string): Promise<void>;
|
|
14
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Handles YouTube video upload process
|
|
20
|
+
*/
|
|
21
|
+
export declare function handleYouTubeUpload(project: Project, options: YouTubeUploadOptions): Promise<void>;
|
|
15
22
|
//# sourceMappingURL=youtube-upload-strategy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube-upload-strategy.d.ts","sourceRoot":"","sources":["../../../src/cli/youtube/youtube-upload-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"youtube-upload-strategy.d.ts","sourceRoot":"","sources":["../../../src/cli/youtube/youtube-upload-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAM3C,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,IAAI;IAIV,OAAO,CACX,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,aAAa,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;CAwCjB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA8Ff"}
|
|
@@ -1,37 +1,117 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.YouTubeUploadStrategy = void 0;
|
|
4
|
-
|
|
7
|
+
exports.handleYouTubeUpload = handleYouTubeUpload;
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const youtube_uploader_1 = require("../../youtube-uploader");
|
|
10
|
+
const ejs_1 = __importDefault(require("ejs"));
|
|
11
|
+
const fs_1 = require("fs");
|
|
5
12
|
/**
|
|
6
13
|
* YouTube upload strategy implementation
|
|
7
14
|
*/
|
|
8
15
|
class YouTubeUploadStrategy {
|
|
9
|
-
clientId;
|
|
10
|
-
clientSecret;
|
|
11
|
-
constructor(clientId, clientSecret) {
|
|
12
|
-
this.clientId = clientId;
|
|
13
|
-
this.clientSecret = clientSecret;
|
|
14
|
-
}
|
|
15
16
|
getTag() {
|
|
16
17
|
return 'youtube';
|
|
17
18
|
}
|
|
18
19
|
validate() {
|
|
19
|
-
|
|
20
|
-
const error = new Error('ā Error: STATICSTRIPES_GOOGLE_CLIENT_ID and STATICSTRIPES_GOOGLE_CLIENT_SECRET environment variables are not set\n\n' +
|
|
21
|
-
'š” Run: staticstripes auth --help\n' +
|
|
22
|
-
' for complete setup instructions');
|
|
23
|
-
throw error;
|
|
24
|
-
}
|
|
20
|
+
// Validation now happens in execute() when we read credentials
|
|
25
21
|
}
|
|
26
22
|
async execute(project, upload, projectPath) {
|
|
23
|
+
// Read credentials from .auth file
|
|
24
|
+
const authDir = (0, path_1.resolve)(projectPath, '.auth');
|
|
25
|
+
const credentialsPath = (0, path_1.resolve)(authDir, `${upload.name}.json`);
|
|
26
|
+
if (!(0, fs_1.existsSync)(credentialsPath)) {
|
|
27
|
+
throw new Error(`ā Error: YouTube credentials not found\n\n` +
|
|
28
|
+
`Expected location: ${credentialsPath}\n\n` +
|
|
29
|
+
`š” Run authentication wizard:\n` +
|
|
30
|
+
` staticstripes auth --upload-name ${upload.name}\n\n` +
|
|
31
|
+
`š Or view setup instructions:\n` +
|
|
32
|
+
` staticstripes auth-help youtube\n`);
|
|
33
|
+
}
|
|
34
|
+
let credentials;
|
|
35
|
+
try {
|
|
36
|
+
const credentialsJson = (0, fs_1.readFileSync)(credentialsPath, 'utf-8');
|
|
37
|
+
credentials = JSON.parse(credentialsJson);
|
|
38
|
+
if (!credentials.clientId || !credentials.clientSecret) {
|
|
39
|
+
throw new Error('Missing clientId or clientSecret');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw new Error(`ā Error: Failed to parse YouTube credentials from ${credentialsPath}\n` +
|
|
44
|
+
`Ensure the file contains clientId and clientSecret.\n` +
|
|
45
|
+
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
|
+
}
|
|
27
47
|
// Delegate to existing handler
|
|
28
|
-
await
|
|
48
|
+
await handleYouTubeUpload(project, {
|
|
29
49
|
uploadName: upload.name,
|
|
30
50
|
projectPath,
|
|
31
|
-
clientId:
|
|
32
|
-
clientSecret:
|
|
51
|
+
clientId: credentials.clientId,
|
|
52
|
+
clientSecret: credentials.clientSecret,
|
|
33
53
|
});
|
|
34
54
|
}
|
|
35
55
|
}
|
|
36
56
|
exports.YouTubeUploadStrategy = YouTubeUploadStrategy;
|
|
57
|
+
/**
|
|
58
|
+
* Handles YouTube video upload process
|
|
59
|
+
*/
|
|
60
|
+
async function handleYouTubeUpload(project, options) {
|
|
61
|
+
// Get upload configuration
|
|
62
|
+
const upload = project.getYouTubeUpload(options.uploadName);
|
|
63
|
+
if (!upload) {
|
|
64
|
+
const availableUploads = Array.from(project.getYouTubeUploads().keys());
|
|
65
|
+
throw new Error(`Upload "${options.uploadName}" not found in project.html\n` +
|
|
66
|
+
(availableUploads.length > 0
|
|
67
|
+
? `Available uploads: ${availableUploads.join(', ')}`
|
|
68
|
+
: 'No uploads defined in project.html'));
|
|
69
|
+
}
|
|
70
|
+
// Get the output file
|
|
71
|
+
const output = project.getOutput(upload.outputName);
|
|
72
|
+
if (!output) {
|
|
73
|
+
throw new Error(`Output "${upload.outputName}" not found`);
|
|
74
|
+
}
|
|
75
|
+
console.log(`š¹ Video file: ${output.path}`);
|
|
76
|
+
console.log(`š¬ Upload config: ${options.uploadName}\n`);
|
|
77
|
+
// Create uploader and load tokens
|
|
78
|
+
const uploader = new youtube_uploader_1.YouTubeUploader(options.clientId, options.clientSecret);
|
|
79
|
+
const hasTokens = uploader.loadTokens(options.uploadName, options.projectPath);
|
|
80
|
+
if (!hasTokens) {
|
|
81
|
+
throw new Error(`Not authenticated. Please run: staticstripes auth --upload-name ${options.uploadName}`);
|
|
82
|
+
}
|
|
83
|
+
// Determine title (use upload-specific title or fall back to project title)
|
|
84
|
+
const title = upload.title || project.getTitle();
|
|
85
|
+
console.log(`š Title: ${title}\n`);
|
|
86
|
+
// Build the project to populate fragment times (needed for timecodes)
|
|
87
|
+
console.log('šØ Building project to calculate timecodes...');
|
|
88
|
+
await project.build(upload.outputName);
|
|
89
|
+
// Get timecodes and process description with EJS
|
|
90
|
+
const timecodes = project.getTimecodes();
|
|
91
|
+
// Format tags (space-separated, no hashtags for YouTube)
|
|
92
|
+
const formattedTags = upload.tags.join(' ');
|
|
93
|
+
// Convert ${variable} syntax to <%= variable %> for EJS compatibility
|
|
94
|
+
const ejsDescription = upload.description.replace(/\$\{(\w+)\}/g, '<%= $1 %>');
|
|
95
|
+
const processedDescription = ejs_1.default.render(ejsDescription, {
|
|
96
|
+
title,
|
|
97
|
+
tags: formattedTags,
|
|
98
|
+
timecodes: timecodes.join('\n'),
|
|
99
|
+
});
|
|
100
|
+
// Create a processed upload object with rendered description
|
|
101
|
+
const processedUpload = {
|
|
102
|
+
...upload,
|
|
103
|
+
description: processedDescription,
|
|
104
|
+
};
|
|
105
|
+
// Upload video
|
|
106
|
+
const videoId = await uploader.uploadVideo(output.path, processedUpload, title);
|
|
107
|
+
// Handle thumbnail if specified
|
|
108
|
+
if (upload.thumbnailTimecode !== undefined) {
|
|
109
|
+
console.log(`\nš¼ļø Extracting thumbnail at ${upload.thumbnailTimecode}ms...`);
|
|
110
|
+
const thumbnailPath = (0, path_1.resolve)(options.projectPath, '.cache', 'thumbnail.png');
|
|
111
|
+
await uploader.extractThumbnail(output.path, upload.thumbnailTimecode, thumbnailPath);
|
|
112
|
+
await uploader.uploadThumbnail(videoId, thumbnailPath);
|
|
113
|
+
}
|
|
114
|
+
// TODO: Update project.html with video ID
|
|
115
|
+
console.log('\nā
Upload complete!');
|
|
116
|
+
}
|
|
37
117
|
//# sourceMappingURL=youtube-upload-strategy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube-upload-strategy.js","sourceRoot":"","sources":["../../../src/cli/youtube/youtube-upload-strategy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"youtube-upload-strategy.js","sourceRoot":"","sources":["../../../src/cli/youtube/youtube-upload-strategy.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ const generate_js_1 = require("./cli/commands/generate.js");
|
|
|
8
8
|
const bootstrap_js_1 = require("./cli/commands/bootstrap.js");
|
|
9
9
|
const add_assets_js_1 = require("./cli/commands/add-assets.js");
|
|
10
10
|
const upload_js_1 = require("./cli/commands/upload.js");
|
|
11
|
-
const
|
|
11
|
+
const auth_js_1 = require("./cli/commands/auth.js");
|
|
12
12
|
// Read version from package.json
|
|
13
13
|
// In built code, this file is at dist/cli.js, package.json is at ../package.json
|
|
14
14
|
const packageJsonPath = (0, path_1.resolve)(__dirname, '../package.json');
|
|
@@ -56,7 +56,6 @@ program
|
|
|
56
56
|
(0, bootstrap_js_1.registerBootstrapCommand)(program, handleError);
|
|
57
57
|
(0, add_assets_js_1.registerAddAssetsCommand)(program, handleError);
|
|
58
58
|
(0, upload_js_1.registerUploadCommand)(program, handleError);
|
|
59
|
-
|
|
60
|
-
(0, cli_js_1.registerYouTubeCommands)(program);
|
|
59
|
+
(0, auth_js_1.registerAuthCommand)(program, handleError);
|
|
61
60
|
program.parse(process.argv);
|
|
62
61
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,+BAA+B;AAC/B,2BAAkC;AAClC,4DAAqE;AACrE,8DAAuE;AACvE,gEAAwE;AACxE,wDAAiE;AACjE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,+BAA+B;AAC/B,2BAAkC;AAClC,4DAAqE;AACrE,8DAAuE;AACvE,gEAAwE;AACxE,wDAAiE;AACjE,oDAA6D;AAE7D,iCAAiC;AACjC,iFAAiF;AACjF,MAAM,eAAe,GAAG,IAAA,cAAO,EAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,iBAAY,EAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;AACvE,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;AAEpC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,oBAAoB;AACpB,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB;;GAEG;AACH,SAAS,WAAW,CAAC,KAAU,EAAE,SAAiB;IAChD,OAAO,CAAC,KAAK,CAAC,OAAO,SAAS,WAAW,CAAC,CAAC;IAE3C,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;QAC3C,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YAChC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CACX,gEAAgE,CACjE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,aAAa,EAAE,gDAAgD,CAAC;KACvE,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;IACjC,8CAA8C;IAC9C,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,WAAW,GAAG,IAAI,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACzC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,wBAAwB;AACxB,IAAA,qCAAuB,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AACjE,IAAA,uCAAwB,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC/C,IAAA,wCAAwB,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC/C,IAAA,iCAAqB,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC5C,IAAA,6BAAmB,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAE1C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -1,14 +1,29 @@
|
|
|
1
|
-
import { ParsedHtml } from './type';
|
|
1
|
+
import { ParsedHtml, AIProvider } from './type';
|
|
2
2
|
import { Project } from './project';
|
|
3
3
|
export declare class HTMLProjectParser {
|
|
4
4
|
private html;
|
|
5
5
|
private projectPath;
|
|
6
6
|
private projectDir;
|
|
7
7
|
constructor(html: ParsedHtml, projectPath: string);
|
|
8
|
+
/**
|
|
9
|
+
* Extracts AI asset generation requirements without full parsing
|
|
10
|
+
* Used to generate AI assets before full project parsing
|
|
11
|
+
*/
|
|
12
|
+
extractAIGenerationRequirements(): {
|
|
13
|
+
providers: Map<string, AIProvider>;
|
|
14
|
+
assetsToGenerate: Array<{
|
|
15
|
+
name: string;
|
|
16
|
+
path: string;
|
|
17
|
+
integrationName: string;
|
|
18
|
+
prompt: string;
|
|
19
|
+
duration?: number;
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
8
22
|
parse(): Promise<Project>;
|
|
9
23
|
/**
|
|
10
24
|
* Validates that all asset files exist on the filesystem
|
|
11
25
|
* Throws an error with a list of missing files if any are not found
|
|
26
|
+
* Note: Assets with AI configuration are skipped if they don't exist (will be generated)
|
|
12
27
|
*/
|
|
13
28
|
private validateAssetFiles;
|
|
14
29
|
/**
|
|
@@ -23,6 +38,10 @@ export declare class HTMLProjectParser {
|
|
|
23
38
|
* Extracts asset information from an element
|
|
24
39
|
*/
|
|
25
40
|
private extractAssetFromElement;
|
|
41
|
+
/**
|
|
42
|
+
* Extracts AI configuration from an asset's child <ai> element
|
|
43
|
+
*/
|
|
44
|
+
private extractAssetAIConfig;
|
|
26
45
|
/**
|
|
27
46
|
* Infers asset type from tag name or file path
|
|
28
47
|
*/
|
|
@@ -91,6 +110,26 @@ export declare class HTMLProjectParser {
|
|
|
91
110
|
* Parses a single <s3> element
|
|
92
111
|
*/
|
|
93
112
|
private parseS3Element;
|
|
113
|
+
/**
|
|
114
|
+
* Parses a single <instagram> element
|
|
115
|
+
*/
|
|
116
|
+
private parseInstagramElement;
|
|
117
|
+
/**
|
|
118
|
+
* Processes all AI providers from the parsed HTML
|
|
119
|
+
*/
|
|
120
|
+
private processAIProviders;
|
|
121
|
+
/**
|
|
122
|
+
* Parses a single AI provider element (e.g., <music-api-ai>)
|
|
123
|
+
*/
|
|
124
|
+
private parseAIProviderElement;
|
|
125
|
+
/**
|
|
126
|
+
* Finds all <ai> configuration elements in the HTML (excludes <ai> elements inside <asset>)
|
|
127
|
+
*/
|
|
128
|
+
private findAIElements;
|
|
129
|
+
/**
|
|
130
|
+
* Processes global tags from the top of the HTML file (before <project>)
|
|
131
|
+
*/
|
|
132
|
+
private processGlobalTags;
|
|
94
133
|
/**
|
|
95
134
|
* Processes the title from the parsed HTML
|
|
96
135
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html-project-parser.d.ts","sourceRoot":"","sources":["../src/html-project-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,
|
|
1
|
+
{"version":3,"file":"html-project-parser.d.ts","sourceRoot":"","sources":["../src/html-project-parser.ts"],"names":[],"mappings":"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"}
|