@julien-lin/universal-pwa-core 1.2.5 → 1.2.7

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
@@ -628,8 +628,9 @@ function generateManifest(options) {
628
628
  }
629
629
  function writeManifest(manifest, outputDir) {
630
630
  const manifestPath = (0, import_path4.join)(outputDir, "manifest.json");
631
- const manifestJson = JSON.stringify(manifest, null, 2);
632
- (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" });
633
634
  return manifestPath;
634
635
  }
635
636
  function generateAndWriteManifest(options, outputDir) {
@@ -1109,7 +1110,7 @@ function findElement(parsed, tagName, attribute) {
1109
1110
  if (!attribute) {
1110
1111
  return element;
1111
1112
  }
1112
- const attrValue = element.attributes?.find((attr) => attr.name.toLowerCase() === attribute.name.toLowerCase())?.value;
1113
+ const attrValue = element.attribs?.[attribute.name.toLowerCase()];
1113
1114
  if (attrValue === attribute.value) {
1114
1115
  return element;
1115
1116
  }
@@ -1235,11 +1236,9 @@ function injectMetaTags(htmlContent, options = {}) {
1235
1236
  if (existingThemeColor) {
1236
1237
  updateMetaContent(existingThemeColor, options.themeColor);
1237
1238
  result.injected.push(`<meta name="theme-color" content="${options.themeColor}"> (updated)`);
1238
- } else if (!elementExists(parsed, "meta", { name: "theme-color", value: options.themeColor })) {
1239
+ } else {
1239
1240
  injectMetaTag(head, "theme-color", options.themeColor);
1240
1241
  result.injected.push(`<meta name="theme-color" content="${options.themeColor}">`);
1241
- } else {
1242
- result.skipped.push("theme-color (already exists)");
1243
1242
  }
1244
1243
  }
1245
1244
  if (options.appleTouchIcon) {
@@ -1253,11 +1252,19 @@ function injectMetaTags(htmlContent, options = {}) {
1253
1252
  }
1254
1253
  if (options.appleMobileWebAppCapable !== void 0) {
1255
1254
  const content = options.appleMobileWebAppCapable ? "yes" : "no";
1256
- if (!elementExists(parsed, "meta", { name: "apple-mobile-web-app-capable", value: content })) {
1257
- injectMetaTag(head, "apple-mobile-web-app-capable", content);
1258
- 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}">`);
1259
1266
  } else {
1260
- result.skipped.push("apple-mobile-web-app-capable (already exists)");
1267
+ result.skipped.push("mobile-web-app-capable (already exists)");
1261
1268
  }
1262
1269
  }
1263
1270
  if (options.appleMobileWebAppStatusBarStyle) {
@@ -1276,7 +1283,7 @@ function injectMetaTags(htmlContent, options = {}) {
1276
1283
  result.skipped.push("apple-mobile-web-app-title (already exists)");
1277
1284
  }
1278
1285
  }
1279
- const modifiedHtml = (0, import_dom_serializer.render)(parsed.document, { decodeEntities: false });
1286
+ let modifiedHtml = (0, import_dom_serializer.render)(parsed.document, { decodeEntities: false });
1280
1287
  if (options.serviceWorkerPath) {
1281
1288
  const swPath = options.serviceWorkerPath.startsWith("/") ? options.serviceWorkerPath : `/${options.serviceWorkerPath}`;
1282
1289
  if (!htmlContent.includes("navigator.serviceWorker")) {
@@ -1291,10 +1298,13 @@ if ('serviceWorker' in navigator) {
1291
1298
  });
1292
1299
  }
1293
1300
  </script>`;
1294
- const finalHtml = modifiedHtml.replace("</body>", `${swScript}
1301
+ if (modifiedHtml.includes("</body>")) {
1302
+ modifiedHtml = modifiedHtml.replace("</body>", `${swScript}
1295
1303
  </body>`);
1304
+ } else {
1305
+ modifiedHtml = `${modifiedHtml}${swScript}`;
1306
+ }
1296
1307
  result.injected.push("Service Worker registration script");
1297
- return { html: finalHtml, result };
1298
1308
  } else {
1299
1309
  result.skipped.push("Service Worker registration (already exists)");
1300
1310
  }
package/dist/index.js CHANGED
@@ -562,8 +562,9 @@ function generateManifest(options) {
562
562
  }
563
563
  function writeManifest(manifest, outputDir) {
564
564
  const manifestPath = join4(outputDir, "manifest.json");
565
- const manifestJson = JSON.stringify(manifest, null, 2);
566
- 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" });
567
568
  return manifestPath;
568
569
  }
569
570
  function generateAndWriteManifest(options, outputDir) {
@@ -1043,7 +1044,7 @@ function findElement(parsed, tagName, attribute) {
1043
1044
  if (!attribute) {
1044
1045
  return element;
1045
1046
  }
1046
- const attrValue = element.attributes?.find((attr) => attr.name.toLowerCase() === attribute.name.toLowerCase())?.value;
1047
+ const attrValue = element.attribs?.[attribute.name.toLowerCase()];
1047
1048
  if (attrValue === attribute.value) {
1048
1049
  return element;
1049
1050
  }
@@ -1169,11 +1170,9 @@ function injectMetaTags(htmlContent, options = {}) {
1169
1170
  if (existingThemeColor) {
1170
1171
  updateMetaContent(existingThemeColor, options.themeColor);
1171
1172
  result.injected.push(`<meta name="theme-color" content="${options.themeColor}"> (updated)`);
1172
- } else if (!elementExists(parsed, "meta", { name: "theme-color", value: options.themeColor })) {
1173
+ } else {
1173
1174
  injectMetaTag(head, "theme-color", options.themeColor);
1174
1175
  result.injected.push(`<meta name="theme-color" content="${options.themeColor}">`);
1175
- } else {
1176
- result.skipped.push("theme-color (already exists)");
1177
1176
  }
1178
1177
  }
1179
1178
  if (options.appleTouchIcon) {
@@ -1187,11 +1186,19 @@ function injectMetaTags(htmlContent, options = {}) {
1187
1186
  }
1188
1187
  if (options.appleMobileWebAppCapable !== void 0) {
1189
1188
  const content = options.appleMobileWebAppCapable ? "yes" : "no";
1190
- if (!elementExists(parsed, "meta", { name: "apple-mobile-web-app-capable", value: content })) {
1191
- injectMetaTag(head, "apple-mobile-web-app-capable", content);
1192
- 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}">`);
1193
1200
  } else {
1194
- result.skipped.push("apple-mobile-web-app-capable (already exists)");
1201
+ result.skipped.push("mobile-web-app-capable (already exists)");
1195
1202
  }
1196
1203
  }
1197
1204
  if (options.appleMobileWebAppStatusBarStyle) {
@@ -1210,7 +1217,7 @@ function injectMetaTags(htmlContent, options = {}) {
1210
1217
  result.skipped.push("apple-mobile-web-app-title (already exists)");
1211
1218
  }
1212
1219
  }
1213
- const modifiedHtml = render(parsed.document, { decodeEntities: false });
1220
+ let modifiedHtml = render(parsed.document, { decodeEntities: false });
1214
1221
  if (options.serviceWorkerPath) {
1215
1222
  const swPath = options.serviceWorkerPath.startsWith("/") ? options.serviceWorkerPath : `/${options.serviceWorkerPath}`;
1216
1223
  if (!htmlContent.includes("navigator.serviceWorker")) {
@@ -1225,10 +1232,13 @@ if ('serviceWorker' in navigator) {
1225
1232
  });
1226
1233
  }
1227
1234
  </script>`;
1228
- const finalHtml = modifiedHtml.replace("</body>", `${swScript}
1235
+ if (modifiedHtml.includes("</body>")) {
1236
+ modifiedHtml = modifiedHtml.replace("</body>", `${swScript}
1229
1237
  </body>`);
1238
+ } else {
1239
+ modifiedHtml = `${modifiedHtml}${swScript}`;
1240
+ }
1230
1241
  result.injected.push("Service Worker registration script");
1231
- return { html: finalHtml, result };
1232
1242
  } else {
1233
1243
  result.skipped.push("Service Worker registration (already exists)");
1234
1244
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@julien-lin/universal-pwa-core",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
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.5"
64
+ "@julien-lin/universal-pwa-templates": "^1.2.7"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@vitest/coverage-v8": "^2.1.4",