browser-extension-manager 1.3.12 → 1.3.14
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/CLAUDE.md +26 -1
- package/dist/gulp/tasks/html.js +9 -0
- package/dist/gulp/tasks/publish.js +70 -16
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -209,8 +209,33 @@ When adding a new component type to the framework:
|
|
|
209
209
|
- **distribute** ([gulp/tasks/distribute.js](src/gulp/tasks/distribute.js)) - Copies project files to `dist/`
|
|
210
210
|
- **sass** ([gulp/tasks/sass.js](src/gulp/tasks/sass.js)) - Compiles SCSS with sophisticated load path system
|
|
211
211
|
- **webpack** ([gulp/tasks/webpack.js](src/gulp/tasks/webpack.js)) - Bundles JavaScript with Babel
|
|
212
|
-
- **html** ([gulp/tasks/html.js](src/gulp/tasks/html.js)) - Processes HTML views into templates
|
|
212
|
+
- **html** ([gulp/tasks/html.js](src/gulp/tasks/html.js)) - Processes HTML views into templates (see HTML Templating below)
|
|
213
213
|
- **package** ([gulp/tasks/package.js](src/gulp/tasks/package.js)) - Creates packaged extension
|
|
214
|
+
|
|
215
|
+
### HTML Templating
|
|
216
|
+
|
|
217
|
+
HTML views in `src/views/` are processed through a two-step templating system using `{{ }}` brackets.
|
|
218
|
+
|
|
219
|
+
**Available variables:**
|
|
220
|
+
- `{{ brand.name }}` - Brand name from config
|
|
221
|
+
- `{{ brand.url }}` - Brand URL from config
|
|
222
|
+
- `{{ page.name }}` - Component name (e.g., `popup`, `pages/index`)
|
|
223
|
+
- `{{ page.path }}` - Full view path
|
|
224
|
+
- `{{ page.title }}` - Page title (defaults to brand name)
|
|
225
|
+
- `{{ theme.appearance }}` - Theme appearance (`dark` or `light`)
|
|
226
|
+
- `{{ cacheBust }}` - Cache-busting timestamp
|
|
227
|
+
|
|
228
|
+
**Example usage in views:**
|
|
229
|
+
```html
|
|
230
|
+
<a href="{{ brand.url }}/pricing">Upgrade to Premium</a>
|
|
231
|
+
<p>Welcome to {{ brand.name }}</p>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
**How it works:**
|
|
235
|
+
1. Your view file (`src/views/[component]/index.html`) is templated first
|
|
236
|
+
2. The result is injected into [page-template.html](src/config/page-template.html)
|
|
237
|
+
3. The outer template is processed with the same variables
|
|
238
|
+
|
|
214
239
|
- **serve** ([gulp/tasks/serve.js](src/gulp/tasks/serve.js)) - WebSocket server for live reload
|
|
215
240
|
|
|
216
241
|
### Modifying Themes
|
package/dist/gulp/tasks/html.js
CHANGED
|
@@ -105,6 +105,15 @@ function processHtml(templateContent) {
|
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
// Apply template with custom brackets
|
|
108
|
+
// First, template the body content to replace any {{ }} placeholders in the view
|
|
109
|
+
const templatedBody = template(bodyContent, data, {
|
|
110
|
+
brackets: ['{{', '}}'],
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Update data with templated body
|
|
114
|
+
data.content = templatedBody;
|
|
115
|
+
|
|
116
|
+
// Then template the outer page template
|
|
108
117
|
const rendered = template(templateContent, data, {
|
|
109
118
|
brackets: ['{{', '}}'],
|
|
110
119
|
});
|
|
@@ -314,39 +314,77 @@ async function publishToEdge() {
|
|
|
314
314
|
throw new Error('Missing Edge credentials. Set EDGE_PRODUCT_ID, EDGE_CLIENT_ID, EDGE_API_KEY in .env');
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
+
// Helper for Edge API requests
|
|
318
|
+
const edgeHeaders = {
|
|
319
|
+
'Authorization': `ApiKey ${apiKey}`,
|
|
320
|
+
'X-ClientID': clientId,
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// Step 1: Try to submit first to check if there's a pending submission
|
|
324
|
+
// This is faster than uploading first, since upload always succeeds
|
|
325
|
+
logger.log('[edge] Checking for pending submissions...');
|
|
326
|
+
|
|
327
|
+
const publishUrl = `https://api.addons.microsoftedge.microsoft.com/v1/products/${productId}/submissions`;
|
|
328
|
+
const checkResponse = await fetch(publishUrl, {
|
|
329
|
+
method: 'POST',
|
|
330
|
+
headers: {
|
|
331
|
+
...edgeHeaders,
|
|
332
|
+
'Content-Type': 'application/json',
|
|
333
|
+
},
|
|
334
|
+
body: JSON.stringify({
|
|
335
|
+
notes: `Check for pending submission`,
|
|
336
|
+
}),
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
const checkData = await checkResponse.json().catch(() => null);
|
|
340
|
+
|
|
341
|
+
// Log the response for debugging
|
|
342
|
+
logger.log(`[edge] Submission check response: ${JSON.stringify(checkData)}`);
|
|
343
|
+
|
|
344
|
+
// Check if there's a pending submission blocking us
|
|
345
|
+
if (checkData && checkData.status === 'Failed') {
|
|
346
|
+
if (checkData.errorCode === 'InProgressSubmission') {
|
|
347
|
+
throw new Error('Extension already has a pending submission in review. Wait for it to complete before publishing again.');
|
|
348
|
+
}
|
|
349
|
+
if (checkData.errorCode === 'UnpublishInProgress') {
|
|
350
|
+
throw new Error('Extension is being unpublished. Wait for unpublish to complete before publishing.');
|
|
351
|
+
}
|
|
352
|
+
// If it failed for another reason (like no draft package), that's expected - continue to upload
|
|
353
|
+
if (checkData.errorCode !== 'NoDraftPackage' && checkData.errorCode !== 'NoPackageToPublish') {
|
|
354
|
+
logger.log(`[edge] Check failed with: ${checkData.errorCode} - ${checkData.message}`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Step 2: Upload the package
|
|
317
359
|
logger.log('[edge] Uploading to Microsoft Edge Add-ons...');
|
|
318
360
|
|
|
319
|
-
// Read chromium zip file (Edge uses same build as Chrome)
|
|
320
361
|
const zipBuffer = jetpack.read(PATHS.chromium.zip, 'buffer');
|
|
321
|
-
|
|
322
|
-
// Edge API v1.1 endpoint
|
|
323
362
|
const uploadUrl = `https://api.addons.microsoftedge.microsoft.com/v1/products/${productId}/submissions/draft/package`;
|
|
324
363
|
|
|
325
|
-
|
|
326
|
-
const response = await fetch(uploadUrl, {
|
|
364
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
327
365
|
method: 'POST',
|
|
328
366
|
headers: {
|
|
329
|
-
|
|
330
|
-
'X-ClientID': clientId,
|
|
367
|
+
...edgeHeaders,
|
|
331
368
|
'Content-Type': 'application/zip',
|
|
332
369
|
},
|
|
333
370
|
body: zipBuffer,
|
|
334
371
|
});
|
|
335
372
|
|
|
336
|
-
if (!
|
|
337
|
-
const errorText = await
|
|
338
|
-
throw new Error(`Edge
|
|
373
|
+
if (!uploadResponse.ok) {
|
|
374
|
+
const errorText = await uploadResponse.text();
|
|
375
|
+
throw new Error(`Edge upload error: ${uploadResponse.status} - ${errorText}`);
|
|
339
376
|
}
|
|
340
377
|
|
|
378
|
+
const uploadData = await uploadResponse.json().catch(() => null);
|
|
379
|
+
logger.log(`[edge] Upload response: ${JSON.stringify(uploadData)}`);
|
|
380
|
+
|
|
341
381
|
logger.log('[edge] Package uploaded, submitting for review...');
|
|
342
382
|
|
|
343
|
-
// Submit for review
|
|
344
|
-
const publishUrl = `https://api.addons.microsoftedge.microsoft.com/v1/products/${productId}/submissions`;
|
|
383
|
+
// Step 3: Submit for review
|
|
345
384
|
const publishResponse = await fetch(publishUrl, {
|
|
346
385
|
method: 'POST',
|
|
347
386
|
headers: {
|
|
348
|
-
|
|
349
|
-
'X-ClientID': clientId,
|
|
387
|
+
...edgeHeaders,
|
|
350
388
|
'Content-Type': 'application/json',
|
|
351
389
|
},
|
|
352
390
|
body: JSON.stringify({
|
|
@@ -354,9 +392,25 @@ async function publishToEdge() {
|
|
|
354
392
|
}),
|
|
355
393
|
});
|
|
356
394
|
|
|
395
|
+
const publishData = await publishResponse.json().catch(() => null);
|
|
396
|
+
|
|
397
|
+
// Log the full response
|
|
398
|
+
logger.log(`[edge] Publish response: ${JSON.stringify(publishData)}`);
|
|
399
|
+
|
|
400
|
+
// Check for HTTP errors
|
|
357
401
|
if (!publishResponse.ok) {
|
|
358
|
-
|
|
359
|
-
|
|
402
|
+
throw new Error(`Edge publish error: ${publishResponse.status} - ${JSON.stringify(publishData)}`);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Check for API-level failures (HTTP 200 but status: "Failed")
|
|
406
|
+
if (publishData && publishData.status === 'Failed') {
|
|
407
|
+
if (publishData.errorCode === 'InProgressSubmission') {
|
|
408
|
+
throw new Error('Extension already has a pending submission in review. Wait for it to complete before publishing again.');
|
|
409
|
+
}
|
|
410
|
+
if (publishData.errorCode === 'UnpublishInProgress') {
|
|
411
|
+
throw new Error('Extension is being unpublished. Wait for unpublish to complete before publishing.');
|
|
412
|
+
}
|
|
413
|
+
throw new Error(`Edge publish failed: ${publishData.message || publishData.errorCode || 'Unknown error'}`);
|
|
360
414
|
}
|
|
361
415
|
|
|
362
416
|
logger.log('[edge] Upload complete');
|