superprint 1.0.100 → 1.0.102

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.
Files changed (2) hide show
  1. package/cli.mjs +81 -7
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -25,8 +25,10 @@ const APP_ZIP_URL = 'https://app.zigmoon.com/sp213-local.zip';
25
25
  // le zip ET le site, sinon `npx superprint` s'arrête sur « downloaded
26
26
  // version is invalid or older than the online version ».
27
27
  // La version du paquet npm, elle, vit dans package.json.
28
- // 📌 Dernier plancher avancé : 1.7.457 (zip et site 1.7.457 en ligne depuis le 17/09/2026).
29
- const MIN_APP_VERSION = '1.7.457';
28
+ // 📌 Dernier plancher avancé : 1.7.483 (zip et version.txt en ligne, téléchargement
29
+ // vérifié octet à octet le 19/09/2026). 1.7.484 est prêt, mais son plancher
30
+ // n'avancera qu'APRÈS son téléversement sur app.zigmoon.com.
31
+ const MIN_APP_VERSION = '1.7.483';
30
32
  const APP_DIR = path.join(os.homedir(), '.superprint', 'app');
31
33
  const ZIP_PATH = path.join(os.homedir(), '.superprint', 'sp213-local.zip');
32
34
  const VERSION_FILE = path.join(APP_DIR, 'version.txt');
@@ -178,6 +180,23 @@ function dependenciesReady() {
178
180
  path.join(APP_DIR, 'node_modules', '@e965', 'xlsx', 'package.json')
179
181
  ].every(existsSync);
180
182
  }
183
+ // 🛡️ v1.0.102 : une installation ABÎMÉE (dossier vidé, extraction interrompue,
184
+ // vieux paquet sans le studio local) ne doit jamais être considérée comme bonne :
185
+ // sinon `npx superprint` sert un lanceur auquel il manque des pages — c'est le
186
+ // symptôme « je ne peux pas ouvrir le Studio IA en local ».
187
+ // ⚠️ Les 7 pages du lanceur : s'il en manque UNE, on retélécharge tout.
188
+ function installationComplete() {
189
+ return [
190
+ path.join(APP_DIR, 'index.html'),
191
+ path.join(APP_DIR, 'vite.config.js'),
192
+ path.join(APP_DIR, 'public', 'superprint', 'version.txt'),
193
+ path.join(APP_DIR, 'public', 'superprint', 'app', 'index.html'),
194
+ path.join(APP_DIR, 'public', 'superprint', 'sp213-studio.html'),
195
+ path.join(APP_DIR, 'public', 'superprint', 'supertypo', 'index.html'),
196
+ path.join(APP_DIR, 'public', 'superprint', 'documentation.html'),
197
+ path.join(APP_DIR, 'public', 'superprint', 'api.html')
198
+ ].every(existsSync);
199
+ }
181
200
  function runNpmInstall() {
182
201
  return spawnSync(isWin ? 'npm.cmd' : 'npm', ['install', '--no-audit', '--no-fund'], {
183
202
  stdio: 'inherit', cwd: APP_DIR, shell: isWin
@@ -198,7 +217,10 @@ async function main() {
198
217
  const localVer = installedVersion();
199
218
 
200
219
  if (isInstalled()) {
201
- if (!localVer || compareVersions(localVer, onlineVersion) < 0) {
220
+ if (!installationComplete()) {
221
+ warn('The local installation is incomplete (pages missing) — reinstalling.');
222
+ }
223
+ if (!localVer || compareVersions(localVer, onlineVersion) < 0 || !installationComplete()) {
202
224
  info('Online version (' + onlineVersion + ') is newer than local (' + (localVer || '?') + ') — updating.');
203
225
  // Remove the old app to re-download the new one
204
226
  const { rmSync } = await import('node:fs');
@@ -274,20 +296,72 @@ async function main() {
274
296
 
275
297
  // ---- Launch Vite ----
276
298
  const viteBin = path.join(APP_DIR, 'node_modules', 'vite', 'bin', 'vite.js');
299
+ // v1.0.102 : plus de port calculé ici — c'est Vite qui décide (il bascule de port
300
+ // si 5173 est occupé) et on relaie SON adresse (voir plus bas).
277
301
  const userArgs = process.argv.slice(2);
278
302
  const hasExplicitHost = userArgs.some(arg => arg === '--host' || arg.startsWith('--host='));
279
- const portArgIndex = userArgs.findIndex(arg => arg === '--port');
280
- const inlinePort = userArgs.find(arg => arg.startsWith('--port='));
281
- const displayPort = inlinePort ? inlinePort.slice('--port='.length) : (portArgIndex >= 0 ? userArgs[portArgIndex + 1] : '5173');
282
303
  const args = hasExplicitHost ? userArgs : ['--host', '127.0.0.1', ...userArgs];
283
304
 
284
305
  console.log(SEP);
285
306
  console.log(C.green + C.bold + ' Starting SuperPrint…' + C.reset);
286
- console.log(C.dim + ' Open your browser at: http://127.0.0.1:' + displayPort + C.reset);
307
+ console.log(C.dim + ' The address is displayed below as soon as the server is ready.' + C.reset);
308
+ console.log(C.dim + ' (the port changes automatically if 5173 is already taken)' + C.reset);
287
309
  console.log(SEP);
310
+
311
+ // 🛡️ v1.0.102 : on ne DEVINE plus l'adresse. Avant, le message annonçait 5173 en dur
312
+ // (la valeur par défaut) alors que Vite bascule sur 5174/5175 si 5173 est occupé :
313
+ // l'utilisateur atterrissait sur une AUTRE application et croyait que SuperPrint
314
+ // ne s'ouvrait pas (« je ne peux pas ouvrir le studio en local »).
315
+ // Ici on SONDE les ports, en écartant d'abord ceux qui répondent DÉJÀ (un autre
316
+ // outil, un ancien serveur, une autre copie de SuperPrint) : seuls les ports
317
+ // ouverts APRÈS notre démarrage sont candidats.
318
+ const portDemande = (() => {
319
+ const enLigne = userArgs.find((arg) => arg.startsWith('--port='));
320
+ if (enLigne) return enLigne.slice('--port='.length);
321
+ const index = userArgs.indexOf('--port');
322
+ return index >= 0 ? userArgs[index + 1] : null;
323
+ })();
324
+ const ports = [];
325
+ if (portDemande) ports.push(String(portDemande));
326
+ for (let p = 5173; p <= 5185; p++) if (!ports.includes(String(p))) ports.push(String(p));
327
+
328
+ const dejaOuverts = new Set();
329
+ for (const port of ports) {
330
+ try {
331
+ const reponse = await fetch('http://127.0.0.1:' + port + '/', { redirect: 'manual', signal: AbortSignal.timeout(800) });
332
+ await reponse.text();
333
+ dejaOuverts.add(port);
334
+ } catch (_) { /* personne sur ce port : c'est un candidat */ }
335
+ }
336
+ if (dejaOuverts.size) {
337
+ info('Port(s) already busy (ignored): ' + [...dejaOuverts].join(', '));
338
+ }
339
+
288
340
  const child = spawn(process.execPath, [viteBin, ...args], {
289
341
  stdio: 'inherit', cwd: APP_DIR
290
342
  });
343
+
344
+ (async () => {
345
+ for (let essai = 0; essai < 80; essai++) {
346
+ for (const port of ports) {
347
+ if (dejaOuverts.has(port)) continue;
348
+ let texte = '';
349
+ try {
350
+ const reponse = await fetch('http://127.0.0.1:' + port + '/', { redirect: 'manual', signal: AbortSignal.timeout(1500) });
351
+ if (!reponse.ok) continue;
352
+ texte = await reponse.text();
353
+ } catch (_) { continue; }
354
+ if (texte.indexOf('SuperPrint') < 0) continue; // un autre outil a pris ce port
355
+ console.log('');
356
+ console.log(C.green + C.bold + ' ✔ SuperPrint runs at: http://127.0.0.1:' + port + '/' + C.reset);
357
+ console.log(C.dim + ' Open that exact address, then pick Editor, Studio IA, SuperTyPo,' + C.reset);
358
+ console.log(C.dim + ' Documentation or API on the page.' + C.reset);
359
+ return;
360
+ }
361
+ await new Promise((suite) => setTimeout(suite, 250));
362
+ }
363
+ })();
364
+
291
365
  child.on('close', (code) => {
292
366
  if (code !== 0 && code !== null) {
293
367
  console.log(C.yellow + '\n The server stopped (code ' + code + ').' + C.reset);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superprint",
3
- "version": "1.0.100",
3
+ "version": "1.0.102",
4
4
  "description": "SuperPrint by 2.13 — professional desktop publishing (DTP) and prepress, in your browser. Free, no subscription, no account. CMYK/PDF up to 600 DPI with bleed & imposition, advanced typography, vector text export, offline PWA, the SP213 AI layout studio (local WebLLM or cloud) and the SuperTyPo font editor (decompose & reshape any typeface). Use online at https://superprint.cc or run locally with npx.",
5
5
  "keywords": [
6
6
  "superprint",