@julien-lin/universal-pwa-cli 1.1.0 → 1.1.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.
- package/dist/index.cjs +44 -9
- package/dist/index.js +44 -9
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -93,7 +93,7 @@ async function initCommand(options = {}) {
|
|
|
93
93
|
const finalOutputDir = outputDir ?? (result.framework === "WordPress" ? (0, import_path.join)(result.projectPath, "public") : (0, import_path.join)(result.projectPath, "public"));
|
|
94
94
|
console.log(import_chalk.default.blue("\u{1F4DD} Generating manifest.json..."));
|
|
95
95
|
const appName = name ?? (result.framework ? `${result.framework} App` : "My PWA");
|
|
96
|
-
const appShortName = shortName
|
|
96
|
+
const appShortName = shortName && shortName.length > 0 && shortName.length <= 12 ? shortName : appName.substring(0, 12);
|
|
97
97
|
let iconPaths = [];
|
|
98
98
|
if (!skipIcons && iconSource) {
|
|
99
99
|
const iconSourcePath = (0, import_fs.existsSync)(iconSource) ? iconSource : (0, import_path.join)(result.projectPath, iconSource);
|
|
@@ -106,7 +106,14 @@ async function initCommand(options = {}) {
|
|
|
106
106
|
});
|
|
107
107
|
iconPaths = iconResult.icons.map((icon) => icon.src);
|
|
108
108
|
result.iconsGenerated = iconResult.icons.length;
|
|
109
|
+
const appleTouchIconPath = (0, import_path.join)(finalOutputDir, "apple-touch-icon.png");
|
|
110
|
+
if ((0, import_fs.existsSync)(appleTouchIconPath)) {
|
|
111
|
+
iconPaths.push("/apple-touch-icon.png");
|
|
112
|
+
}
|
|
109
113
|
console.log(import_chalk.default.green(`\u2713 Generated ${result.iconsGenerated} icons`));
|
|
114
|
+
if ((0, import_fs.existsSync)(appleTouchIconPath)) {
|
|
115
|
+
console.log(import_chalk.default.green(`\u2713 Generated apple-touch-icon.png`));
|
|
116
|
+
}
|
|
110
117
|
} catch (error) {
|
|
111
118
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
112
119
|
result.errors.push(`Failed to generate icons: ${errorMessage}`);
|
|
@@ -116,6 +123,7 @@ async function initCommand(options = {}) {
|
|
|
116
123
|
result.warnings.push(`Icon source not found: ${iconSourcePath}`);
|
|
117
124
|
}
|
|
118
125
|
}
|
|
126
|
+
let manifestPath;
|
|
119
127
|
if (iconPaths.length > 0) {
|
|
120
128
|
const manifestWithIcons = (0, import_universal_pwa_core2.generateManifest)({
|
|
121
129
|
name: appName,
|
|
@@ -131,11 +139,30 @@ async function initCommand(options = {}) {
|
|
|
131
139
|
type: "image/png"
|
|
132
140
|
}))
|
|
133
141
|
});
|
|
134
|
-
|
|
142
|
+
manifestPath = (0, import_universal_pwa_core2.generateAndWriteManifest)(manifestWithIcons, finalOutputDir);
|
|
135
143
|
result.manifestPath = manifestPath;
|
|
144
|
+
console.log(import_chalk.default.green(`\u2713 Manifest generated: ${manifestPath}`));
|
|
136
145
|
} else {
|
|
137
|
-
result.warnings.push("No icons provided. Manifest
|
|
138
|
-
console.log(import_chalk.default.yellow("\u26A0
|
|
146
|
+
result.warnings.push("No icons provided. Manifest generated with placeholder icon. Please provide an icon source with --icon-source for production.");
|
|
147
|
+
console.log(import_chalk.default.yellow("\u26A0 Generating manifest with placeholder icon"));
|
|
148
|
+
const manifestMinimal = (0, import_universal_pwa_core2.generateManifest)({
|
|
149
|
+
name: appName,
|
|
150
|
+
shortName: appShortName,
|
|
151
|
+
startUrl: "/",
|
|
152
|
+
scope: "/",
|
|
153
|
+
display: "standalone",
|
|
154
|
+
themeColor: themeColor ?? "#ffffff",
|
|
155
|
+
backgroundColor: backgroundColor ?? "#000000",
|
|
156
|
+
icons: [{
|
|
157
|
+
src: "/icon-192x192.png",
|
|
158
|
+
// Placeholder - l'utilisateur devra ajouter une vraie icône
|
|
159
|
+
sizes: "192x192",
|
|
160
|
+
type: "image/png"
|
|
161
|
+
}]
|
|
162
|
+
});
|
|
163
|
+
manifestPath = (0, import_universal_pwa_core2.generateAndWriteManifest)(manifestMinimal, finalOutputDir);
|
|
164
|
+
result.manifestPath = manifestPath;
|
|
165
|
+
console.log(import_chalk.default.green(`\u2713 Manifest generated: ${manifestPath}`));
|
|
139
166
|
}
|
|
140
167
|
if (!skipServiceWorker) {
|
|
141
168
|
console.log(import_chalk.default.blue("\u2699\uFE0F Generating service worker..."));
|
|
@@ -168,22 +195,30 @@ async function initCommand(options = {}) {
|
|
|
168
195
|
let injectedCount = 0;
|
|
169
196
|
for (const htmlFile of htmlFiles.slice(0, 10)) {
|
|
170
197
|
try {
|
|
171
|
-
const normalizePathForInjection = (fullPath, basePath, fallback) => {
|
|
198
|
+
const normalizePathForInjection = (fullPath, basePath, outputDir2, fallback) => {
|
|
172
199
|
if (!fullPath) return fallback;
|
|
173
200
|
try {
|
|
174
201
|
const rel = relativePath(fullPath, basePath);
|
|
175
|
-
|
|
202
|
+
let normalized = rel.startsWith("/") ? rel : `/${rel}`;
|
|
203
|
+
const outputDirName = outputDir2.replace(basePath, "").replace(/^\/+|\/+$/g, "");
|
|
204
|
+
if (outputDirName && normalized.startsWith(`/${outputDirName}/`)) {
|
|
205
|
+
normalized = normalized.replace(`/${outputDirName}/`, "/");
|
|
206
|
+
}
|
|
207
|
+
return normalized;
|
|
176
208
|
} catch {
|
|
177
209
|
return fallback;
|
|
178
210
|
}
|
|
179
211
|
};
|
|
212
|
+
const appleTouchIconFullPath = (0, import_path.join)(finalOutputDir, "apple-touch-icon.png");
|
|
213
|
+
const appleTouchIconExists = (0, import_fs.existsSync)(appleTouchIconFullPath);
|
|
180
214
|
const injectionResult = (0, import_universal_pwa_core5.injectMetaTagsInFile)(htmlFile, {
|
|
181
|
-
manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, "/manifest.json"),
|
|
215
|
+
manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, finalOutputDir, "/manifest.json"),
|
|
182
216
|
themeColor: themeColor ?? "#ffffff",
|
|
183
217
|
backgroundColor: backgroundColor ?? "#000000",
|
|
184
|
-
appleTouchIcon:
|
|
218
|
+
appleTouchIcon: appleTouchIconExists ? normalizePathForInjection(appleTouchIconFullPath, result.projectPath, finalOutputDir, "/apple-touch-icon.png") : "/apple-touch-icon.png",
|
|
219
|
+
// Placeholder si non généré
|
|
185
220
|
appleMobileWebAppCapable: true,
|
|
186
|
-
serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, "/sw.js")
|
|
221
|
+
serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, finalOutputDir, "/sw.js")
|
|
187
222
|
});
|
|
188
223
|
if (injectionResult.injected.length > 0) {
|
|
189
224
|
injectedCount++;
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,7 @@ async function initCommand(options = {}) {
|
|
|
70
70
|
const finalOutputDir = outputDir ?? (result.framework === "WordPress" ? join(result.projectPath, "public") : join(result.projectPath, "public"));
|
|
71
71
|
console.log(chalk.blue("\u{1F4DD} Generating manifest.json..."));
|
|
72
72
|
const appName = name ?? (result.framework ? `${result.framework} App` : "My PWA");
|
|
73
|
-
const appShortName = shortName
|
|
73
|
+
const appShortName = shortName && shortName.length > 0 && shortName.length <= 12 ? shortName : appName.substring(0, 12);
|
|
74
74
|
let iconPaths = [];
|
|
75
75
|
if (!skipIcons && iconSource) {
|
|
76
76
|
const iconSourcePath = existsSync(iconSource) ? iconSource : join(result.projectPath, iconSource);
|
|
@@ -83,7 +83,14 @@ async function initCommand(options = {}) {
|
|
|
83
83
|
});
|
|
84
84
|
iconPaths = iconResult.icons.map((icon) => icon.src);
|
|
85
85
|
result.iconsGenerated = iconResult.icons.length;
|
|
86
|
+
const appleTouchIconPath = join(finalOutputDir, "apple-touch-icon.png");
|
|
87
|
+
if (existsSync(appleTouchIconPath)) {
|
|
88
|
+
iconPaths.push("/apple-touch-icon.png");
|
|
89
|
+
}
|
|
86
90
|
console.log(chalk.green(`\u2713 Generated ${result.iconsGenerated} icons`));
|
|
91
|
+
if (existsSync(appleTouchIconPath)) {
|
|
92
|
+
console.log(chalk.green(`\u2713 Generated apple-touch-icon.png`));
|
|
93
|
+
}
|
|
87
94
|
} catch (error) {
|
|
88
95
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
89
96
|
result.errors.push(`Failed to generate icons: ${errorMessage}`);
|
|
@@ -93,6 +100,7 @@ async function initCommand(options = {}) {
|
|
|
93
100
|
result.warnings.push(`Icon source not found: ${iconSourcePath}`);
|
|
94
101
|
}
|
|
95
102
|
}
|
|
103
|
+
let manifestPath;
|
|
96
104
|
if (iconPaths.length > 0) {
|
|
97
105
|
const manifestWithIcons = generateManifest({
|
|
98
106
|
name: appName,
|
|
@@ -108,11 +116,30 @@ async function initCommand(options = {}) {
|
|
|
108
116
|
type: "image/png"
|
|
109
117
|
}))
|
|
110
118
|
});
|
|
111
|
-
|
|
119
|
+
manifestPath = generateAndWriteManifest(manifestWithIcons, finalOutputDir);
|
|
112
120
|
result.manifestPath = manifestPath;
|
|
121
|
+
console.log(chalk.green(`\u2713 Manifest generated: ${manifestPath}`));
|
|
113
122
|
} else {
|
|
114
|
-
result.warnings.push("No icons provided. Manifest
|
|
115
|
-
console.log(chalk.yellow("\u26A0
|
|
123
|
+
result.warnings.push("No icons provided. Manifest generated with placeholder icon. Please provide an icon source with --icon-source for production.");
|
|
124
|
+
console.log(chalk.yellow("\u26A0 Generating manifest with placeholder icon"));
|
|
125
|
+
const manifestMinimal = generateManifest({
|
|
126
|
+
name: appName,
|
|
127
|
+
shortName: appShortName,
|
|
128
|
+
startUrl: "/",
|
|
129
|
+
scope: "/",
|
|
130
|
+
display: "standalone",
|
|
131
|
+
themeColor: themeColor ?? "#ffffff",
|
|
132
|
+
backgroundColor: backgroundColor ?? "#000000",
|
|
133
|
+
icons: [{
|
|
134
|
+
src: "/icon-192x192.png",
|
|
135
|
+
// Placeholder - l'utilisateur devra ajouter une vraie icône
|
|
136
|
+
sizes: "192x192",
|
|
137
|
+
type: "image/png"
|
|
138
|
+
}]
|
|
139
|
+
});
|
|
140
|
+
manifestPath = generateAndWriteManifest(manifestMinimal, finalOutputDir);
|
|
141
|
+
result.manifestPath = manifestPath;
|
|
142
|
+
console.log(chalk.green(`\u2713 Manifest generated: ${manifestPath}`));
|
|
116
143
|
}
|
|
117
144
|
if (!skipServiceWorker) {
|
|
118
145
|
console.log(chalk.blue("\u2699\uFE0F Generating service worker..."));
|
|
@@ -145,22 +172,30 @@ async function initCommand(options = {}) {
|
|
|
145
172
|
let injectedCount = 0;
|
|
146
173
|
for (const htmlFile of htmlFiles.slice(0, 10)) {
|
|
147
174
|
try {
|
|
148
|
-
const normalizePathForInjection = (fullPath, basePath, fallback) => {
|
|
175
|
+
const normalizePathForInjection = (fullPath, basePath, outputDir2, fallback) => {
|
|
149
176
|
if (!fullPath) return fallback;
|
|
150
177
|
try {
|
|
151
178
|
const rel = relativePath(fullPath, basePath);
|
|
152
|
-
|
|
179
|
+
let normalized = rel.startsWith("/") ? rel : `/${rel}`;
|
|
180
|
+
const outputDirName = outputDir2.replace(basePath, "").replace(/^\/+|\/+$/g, "");
|
|
181
|
+
if (outputDirName && normalized.startsWith(`/${outputDirName}/`)) {
|
|
182
|
+
normalized = normalized.replace(`/${outputDirName}/`, "/");
|
|
183
|
+
}
|
|
184
|
+
return normalized;
|
|
153
185
|
} catch {
|
|
154
186
|
return fallback;
|
|
155
187
|
}
|
|
156
188
|
};
|
|
189
|
+
const appleTouchIconFullPath = join(finalOutputDir, "apple-touch-icon.png");
|
|
190
|
+
const appleTouchIconExists = existsSync(appleTouchIconFullPath);
|
|
157
191
|
const injectionResult = injectMetaTagsInFile(htmlFile, {
|
|
158
|
-
manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, "/manifest.json"),
|
|
192
|
+
manifestPath: normalizePathForInjection(result.manifestPath, result.projectPath, finalOutputDir, "/manifest.json"),
|
|
159
193
|
themeColor: themeColor ?? "#ffffff",
|
|
160
194
|
backgroundColor: backgroundColor ?? "#000000",
|
|
161
|
-
appleTouchIcon:
|
|
195
|
+
appleTouchIcon: appleTouchIconExists ? normalizePathForInjection(appleTouchIconFullPath, result.projectPath, finalOutputDir, "/apple-touch-icon.png") : "/apple-touch-icon.png",
|
|
196
|
+
// Placeholder si non généré
|
|
162
197
|
appleMobileWebAppCapable: true,
|
|
163
|
-
serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, "/sw.js")
|
|
198
|
+
serviceWorkerPath: normalizePathForInjection(result.serviceWorkerPath, result.projectPath, finalOutputDir, "/sw.js")
|
|
164
199
|
});
|
|
165
200
|
if (injectionResult.injected.length > 0) {
|
|
166
201
|
injectedCount++;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@julien-lin/universal-pwa-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "CLI pour transformer n'importe quel projet web en PWA",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pwa",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"glob": "^13.0.0",
|
|
45
45
|
"pino": "^9.14.0",
|
|
46
46
|
"zod": "^4.2.1",
|
|
47
|
-
"@julien-lin/universal-pwa-core": "^1.1.
|
|
47
|
+
"@julien-lin/universal-pwa-core": "^1.1.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@vitest/coverage-v8": "^2.1.4",
|