@julien-lin/universal-pwa-core 1.2.4 → 1.2.6

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/index.cjs CHANGED
@@ -604,12 +604,8 @@ function generateManifest(options) {
604
604
  if (options.orientation) {
605
605
  manifest.orientation = options.orientation;
606
606
  }
607
- if (options.themeColor) {
608
- manifest.theme_color = options.themeColor;
609
- }
610
- if (options.backgroundColor) {
611
- manifest.background_color = options.backgroundColor;
612
- }
607
+ manifest.theme_color = options.themeColor ?? "#ffffff";
608
+ manifest.background_color = options.backgroundColor ?? "#ffffff";
613
609
  if (options.splashScreens && options.splashScreens.length > 0) {
614
610
  manifest.splash_screens = options.splashScreens;
615
611
  }
@@ -632,8 +628,9 @@ function generateManifest(options) {
632
628
  }
633
629
  function writeManifest(manifest, outputDir) {
634
630
  const manifestPath = (0, import_path4.join)(outputDir, "manifest.json");
635
- const manifestJson = JSON.stringify(manifest, null, 2);
636
- (0, import_fs5.writeFileSync)(manifestPath, manifestJson, "utf-8");
631
+ const validatedManifest = ManifestSchema.parse(manifest);
632
+ const manifestJson = JSON.stringify(validatedManifest, null, 2);
633
+ (0, import_fs5.writeFileSync)(manifestPath, manifestJson, { encoding: "utf8" });
637
634
  return manifestPath;
638
635
  }
639
636
  function generateAndWriteManifest(options, outputDir) {
@@ -1113,7 +1110,7 @@ function findElement(parsed, tagName, attribute) {
1113
1110
  if (!attribute) {
1114
1111
  return element;
1115
1112
  }
1116
- const attrValue = element.attributes?.find((attr) => attr.name.toLowerCase() === attribute.name.toLowerCase())?.value;
1113
+ const attrValue = element.attribs?.[attribute.name.toLowerCase()];
1117
1114
  if (attrValue === attribute.value) {
1118
1115
  return element;
1119
1116
  }
@@ -1239,11 +1236,9 @@ function injectMetaTags(htmlContent, options = {}) {
1239
1236
  if (existingThemeColor) {
1240
1237
  updateMetaContent(existingThemeColor, options.themeColor);
1241
1238
  result.injected.push(`<meta name="theme-color" content="${options.themeColor}"> (updated)`);
1242
- } else if (!elementExists(parsed, "meta", { name: "theme-color", value: options.themeColor })) {
1239
+ } else {
1243
1240
  injectMetaTag(head, "theme-color", options.themeColor);
1244
1241
  result.injected.push(`<meta name="theme-color" content="${options.themeColor}">`);
1245
- } else {
1246
- result.skipped.push("theme-color (already exists)");
1247
1242
  }
1248
1243
  }
1249
1244
  if (options.appleTouchIcon) {
@@ -1257,11 +1252,19 @@ function injectMetaTags(htmlContent, options = {}) {
1257
1252
  }
1258
1253
  if (options.appleMobileWebAppCapable !== void 0) {
1259
1254
  const content = options.appleMobileWebAppCapable ? "yes" : "no";
1260
- if (!elementExists(parsed, "meta", { name: "apple-mobile-web-app-capable", value: content })) {
1261
- injectMetaTag(head, "apple-mobile-web-app-capable", content);
1262
- result.injected.push(`<meta name="apple-mobile-web-app-capable" content="${content}">`);
1255
+ const deprecatedMeta = findElement(parsed, "meta", { name: "name", value: "apple-mobile-web-app-capable" });
1256
+ if (deprecatedMeta && deprecatedMeta.parent) {
1257
+ const parent = deprecatedMeta.parent;
1258
+ if (parent.children) {
1259
+ parent.children = parent.children.filter((child) => child !== deprecatedMeta);
1260
+ result.warnings.push('Removed deprecated <meta name="apple-mobile-web-app-capable">');
1261
+ }
1262
+ }
1263
+ if (!elementExists(parsed, "meta", { name: "mobile-web-app-capable", value: content })) {
1264
+ injectMetaTag(head, "mobile-web-app-capable", content);
1265
+ result.injected.push(`<meta name="mobile-web-app-capable" content="${content}">`);
1263
1266
  } else {
1264
- result.skipped.push("apple-mobile-web-app-capable (already exists)");
1267
+ result.skipped.push("mobile-web-app-capable (already exists)");
1265
1268
  }
1266
1269
  }
1267
1270
  if (options.appleMobileWebAppStatusBarStyle) {
@@ -1280,7 +1283,7 @@ function injectMetaTags(htmlContent, options = {}) {
1280
1283
  result.skipped.push("apple-mobile-web-app-title (already exists)");
1281
1284
  }
1282
1285
  }
1283
- const modifiedHtml = (0, import_dom_serializer.render)(parsed.document, { decodeEntities: false });
1286
+ let modifiedHtml = (0, import_dom_serializer.render)(parsed.document, { decodeEntities: false });
1284
1287
  if (options.serviceWorkerPath) {
1285
1288
  const swPath = options.serviceWorkerPath.startsWith("/") ? options.serviceWorkerPath : `/${options.serviceWorkerPath}`;
1286
1289
  if (!htmlContent.includes("navigator.serviceWorker")) {
@@ -1295,10 +1298,13 @@ if ('serviceWorker' in navigator) {
1295
1298
  });
1296
1299
  }
1297
1300
  </script>`;
1298
- const finalHtml = modifiedHtml.replace("</body>", `${swScript}
1301
+ if (modifiedHtml.includes("</body>")) {
1302
+ modifiedHtml = modifiedHtml.replace("</body>", `${swScript}
1299
1303
  </body>`);
1304
+ } else {
1305
+ modifiedHtml = `${modifiedHtml}${swScript}`;
1306
+ }
1300
1307
  result.injected.push("Service Worker registration script");
1301
- return { html: finalHtml, result };
1302
1308
  } else {
1303
1309
  result.skipped.push("Service Worker registration (already exists)");
1304
1310
  }
package/dist/index.js CHANGED
@@ -538,12 +538,8 @@ function generateManifest(options) {
538
538
  if (options.orientation) {
539
539
  manifest.orientation = options.orientation;
540
540
  }
541
- if (options.themeColor) {
542
- manifest.theme_color = options.themeColor;
543
- }
544
- if (options.backgroundColor) {
545
- manifest.background_color = options.backgroundColor;
546
- }
541
+ manifest.theme_color = options.themeColor ?? "#ffffff";
542
+ manifest.background_color = options.backgroundColor ?? "#ffffff";
547
543
  if (options.splashScreens && options.splashScreens.length > 0) {
548
544
  manifest.splash_screens = options.splashScreens;
549
545
  }
@@ -566,8 +562,9 @@ function generateManifest(options) {
566
562
  }
567
563
  function writeManifest(manifest, outputDir) {
568
564
  const manifestPath = join4(outputDir, "manifest.json");
569
- const manifestJson = JSON.stringify(manifest, null, 2);
570
- writeFileSync(manifestPath, manifestJson, "utf-8");
565
+ const validatedManifest = ManifestSchema.parse(manifest);
566
+ const manifestJson = JSON.stringify(validatedManifest, null, 2);
567
+ writeFileSync(manifestPath, manifestJson, { encoding: "utf8" });
571
568
  return manifestPath;
572
569
  }
573
570
  function generateAndWriteManifest(options, outputDir) {
@@ -1047,7 +1044,7 @@ function findElement(parsed, tagName, attribute) {
1047
1044
  if (!attribute) {
1048
1045
  return element;
1049
1046
  }
1050
- const attrValue = element.attributes?.find((attr) => attr.name.toLowerCase() === attribute.name.toLowerCase())?.value;
1047
+ const attrValue = element.attribs?.[attribute.name.toLowerCase()];
1051
1048
  if (attrValue === attribute.value) {
1052
1049
  return element;
1053
1050
  }
@@ -1173,11 +1170,9 @@ function injectMetaTags(htmlContent, options = {}) {
1173
1170
  if (existingThemeColor) {
1174
1171
  updateMetaContent(existingThemeColor, options.themeColor);
1175
1172
  result.injected.push(`<meta name="theme-color" content="${options.themeColor}"> (updated)`);
1176
- } else if (!elementExists(parsed, "meta", { name: "theme-color", value: options.themeColor })) {
1173
+ } else {
1177
1174
  injectMetaTag(head, "theme-color", options.themeColor);
1178
1175
  result.injected.push(`<meta name="theme-color" content="${options.themeColor}">`);
1179
- } else {
1180
- result.skipped.push("theme-color (already exists)");
1181
1176
  }
1182
1177
  }
1183
1178
  if (options.appleTouchIcon) {
@@ -1191,11 +1186,19 @@ function injectMetaTags(htmlContent, options = {}) {
1191
1186
  }
1192
1187
  if (options.appleMobileWebAppCapable !== void 0) {
1193
1188
  const content = options.appleMobileWebAppCapable ? "yes" : "no";
1194
- if (!elementExists(parsed, "meta", { name: "apple-mobile-web-app-capable", value: content })) {
1195
- injectMetaTag(head, "apple-mobile-web-app-capable", content);
1196
- result.injected.push(`<meta name="apple-mobile-web-app-capable" content="${content}">`);
1189
+ const deprecatedMeta = findElement(parsed, "meta", { name: "name", value: "apple-mobile-web-app-capable" });
1190
+ if (deprecatedMeta && deprecatedMeta.parent) {
1191
+ const parent = deprecatedMeta.parent;
1192
+ if (parent.children) {
1193
+ parent.children = parent.children.filter((child) => child !== deprecatedMeta);
1194
+ result.warnings.push('Removed deprecated <meta name="apple-mobile-web-app-capable">');
1195
+ }
1196
+ }
1197
+ if (!elementExists(parsed, "meta", { name: "mobile-web-app-capable", value: content })) {
1198
+ injectMetaTag(head, "mobile-web-app-capable", content);
1199
+ result.injected.push(`<meta name="mobile-web-app-capable" content="${content}">`);
1197
1200
  } else {
1198
- result.skipped.push("apple-mobile-web-app-capable (already exists)");
1201
+ result.skipped.push("mobile-web-app-capable (already exists)");
1199
1202
  }
1200
1203
  }
1201
1204
  if (options.appleMobileWebAppStatusBarStyle) {
@@ -1214,7 +1217,7 @@ function injectMetaTags(htmlContent, options = {}) {
1214
1217
  result.skipped.push("apple-mobile-web-app-title (already exists)");
1215
1218
  }
1216
1219
  }
1217
- const modifiedHtml = render(parsed.document, { decodeEntities: false });
1220
+ let modifiedHtml = render(parsed.document, { decodeEntities: false });
1218
1221
  if (options.serviceWorkerPath) {
1219
1222
  const swPath = options.serviceWorkerPath.startsWith("/") ? options.serviceWorkerPath : `/${options.serviceWorkerPath}`;
1220
1223
  if (!htmlContent.includes("navigator.serviceWorker")) {
@@ -1229,10 +1232,13 @@ if ('serviceWorker' in navigator) {
1229
1232
  });
1230
1233
  }
1231
1234
  </script>`;
1232
- const finalHtml = modifiedHtml.replace("</body>", `${swScript}
1235
+ if (modifiedHtml.includes("</body>")) {
1236
+ modifiedHtml = modifiedHtml.replace("</body>", `${swScript}
1233
1237
  </body>`);
1238
+ } else {
1239
+ modifiedHtml = `${modifiedHtml}${swScript}`;
1240
+ }
1234
1241
  result.injected.push("Service Worker registration script");
1235
- return { html: finalHtml, result };
1236
1242
  } else {
1237
1243
  result.skipped.push("Service Worker registration (already exists)");
1238
1244
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@julien-lin/universal-pwa-core",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "Core engine for scanning, generation, and injection for UniversalPWA",
5
5
  "keywords": [
6
6
  "pwa",
@@ -61,7 +61,7 @@
61
61
  "workbox-routing": "^7.4.0",
62
62
  "workbox-strategies": "^7.4.0",
63
63
  "zod": "^4.2.1",
64
- "@julien-lin/universal-pwa-templates": "^1.2.4"
64
+ "@julien-lin/universal-pwa-templates": "^1.2.6"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@vitest/coverage-v8": "^2.1.4",