superprint 1.0.0
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/LICENSE +21 -0
- package/README.md +30 -0
- package/cli.mjs +226 -0
- package/package.json +45 -0
- package/scripts/postinstall.mjs +9 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SuperPrint
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# SuperPrint
|
|
2
|
+
|
|
3
|
+
Logiciel de **PAO (mise en page)** gratuit dans le navigateur + **studio SP213** de maquettes générées par IA.
|
|
4
|
+
|
|
5
|
+
100% **local** : les modèles IA sont téléchargés une seule fois puis exécutés sur votre machine via **WebGPU** (WebLLM). Aucune donnée ne quitte votre ordinateur.
|
|
6
|
+
|
|
7
|
+
## Installation — une seule commande
|
|
8
|
+
|
|
9
|
+
Prérequis : [Node.js 18+](https://nodejs.org) (npm inclus).
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx superprint
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Au premier lancement, SuperPrint télécharge l'application (≈50 Mo, une seule fois), installe les dépendances puis ouvre votre navigateur sur **http://localhost:5173**.
|
|
16
|
+
|
|
17
|
+
Identique sur **Windows, macOS et Linux**.
|
|
18
|
+
|
|
19
|
+
## Utilisation
|
|
20
|
+
|
|
21
|
+
- **Studio SP213** : créez vos maquettes par conversation avec l'IA.
|
|
22
|
+
- **SuperPrint Editor** : affinez vos maquettes dans le canevas PAO complet (mm, fond perdu, zones de sécurité…).
|
|
23
|
+
|
|
24
|
+
## En ligne
|
|
25
|
+
|
|
26
|
+
Pas besoin d'installation : [superprint.cc](https://superprint.cc) (version web, aussi disponible sur mobile).
|
|
27
|
+
|
|
28
|
+
## Licence
|
|
29
|
+
|
|
30
|
+
MIT — © SuperPrint
|
package/cli.mjs
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ═══════════════════════════════════════════════════════════════
|
|
3
|
+
// SuperPrint — launcher npm
|
|
4
|
+
// Une seule commande : npx superprint
|
|
5
|
+
// Télécharge l'app (1 seule fois), installe les deps, lance Vite.
|
|
6
|
+
// Marche identiquement sur Windows, macOS et Linux.
|
|
7
|
+
// ═══════════════════════════════════════════════════════════════
|
|
8
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
9
|
+
import { createWriteStream, existsSync, mkdirSync, readFileSync, statSync, writeFileSync, unlinkSync } from 'node:fs';
|
|
10
|
+
import { get as httpsGet } from 'node:https';
|
|
11
|
+
import { pipeline } from 'node:stream/promises';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import os from 'node:os';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
|
|
16
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const isWin = process.platform === 'win32';
|
|
18
|
+
|
|
19
|
+
// ── URLs & chemins ────────────────────────────────────────────
|
|
20
|
+
const APP_VERSION_URL = 'https://superprint.cc/version.txt';
|
|
21
|
+
const APP_ZIP_URL = 'https://superprint.cc/sp213-local.zip';
|
|
22
|
+
const APP_DIR = path.join(os.homedir(), '.superprint', 'app');
|
|
23
|
+
const ZIP_PATH = path.join(os.homedir(), '.superprint', 'sp213-local.zip');
|
|
24
|
+
const VERSION_FILE = path.join(APP_DIR, 'version.txt');
|
|
25
|
+
|
|
26
|
+
// ── Couleurs ANSI ─────────────────────────────────────────────
|
|
27
|
+
const C = {
|
|
28
|
+
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
29
|
+
red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m',
|
|
30
|
+
blue: '\x1b[34m', cyan: '\x1b[36m', white: '\x1b[37m',
|
|
31
|
+
bgDark: '\x1b[40m', bgGreen: '\x1b[42m', bgRed: '\x1b[41m'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const BANNER = String.raw`
|
|
35
|
+
███████╗██╗ ██╗██████╗ ███████╗██████╗ ██████╗ ██████╗ ██╗███╗ ██╗████████╗
|
|
36
|
+
██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝
|
|
37
|
+
███████╗██║ ██║██████╔╝█████╗ ██████╔╝██████╔╝██████╔╝██║██╔██╗ ██║ ██║
|
|
38
|
+
╚════██║██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗██╔═══╝ ██╔══██╗██║██║╚██╗██║ ██║
|
|
39
|
+
███████║╚██████╔╝██║ ███████╗██║ ██║██║ ██║ ██║██║██║ ╚████║ ██║
|
|
40
|
+
╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═══╝
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
const SEP = '\n' + C.dim + '─'.repeat(60) + C.reset + '\n';
|
|
44
|
+
|
|
45
|
+
function title(text) {
|
|
46
|
+
console.log(C.green + ' ' + '='.repeat(56) + C.reset);
|
|
47
|
+
console.log(C.green + C.bold + ' ' + text + C.reset);
|
|
48
|
+
console.log(C.green + ' ' + '='.repeat(56) + C.reset);
|
|
49
|
+
}
|
|
50
|
+
function step(n, label) {
|
|
51
|
+
console.log('');
|
|
52
|
+
console.log(C.bold + C.blue + ' [' + n + '/4] ' + label + C.reset);
|
|
53
|
+
console.log(C.dim + ' ' + '─'.repeat(50) + C.reset);
|
|
54
|
+
}
|
|
55
|
+
function ok(m) { console.log(C.green + ' ✔ ' + m + C.reset); }
|
|
56
|
+
function info(m) { console.log(C.dim + ' · ' + m + C.reset); }
|
|
57
|
+
function warn(m) { console.log(C.yellow + ' ⚠ ' + m + C.reset); }
|
|
58
|
+
function fail(m) {
|
|
59
|
+
console.log('');
|
|
60
|
+
console.log(C.bgRed + C.white + ' ERREUR ' + C.reset);
|
|
61
|
+
console.log(C.red + ' ' + m + C.reset);
|
|
62
|
+
console.log(C.dim + ' Téléchargez manuellement : https://superprint.cc/sp213-local.zip' + C.reset);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ── Helpers réseau ────────────────────────────────────────────
|
|
66
|
+
function httpsGetText(url, timeout = 20000) {
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
const req = httpsGet(url, (res) => {
|
|
69
|
+
if (res.statusCode !== 200) { reject(new Error('HTTP ' + res.statusCode)); res.resume(); return; }
|
|
70
|
+
let data = '';
|
|
71
|
+
res.setEncoding('utf8');
|
|
72
|
+
res.on('data', (c) => { data += c; });
|
|
73
|
+
res.on('end', () => resolve(data.trim()));
|
|
74
|
+
});
|
|
75
|
+
req.on('error', reject);
|
|
76
|
+
req.setTimeout(timeout, () => { req.destroy(new Error('Timeout')); });
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function downloadFile(url, dest) {
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
mkdirSync(path.dirname(dest), { recursive: true });
|
|
83
|
+
const req = httpsGet(url, (res) => {
|
|
84
|
+
if (res.statusCode !== 200) { reject(new Error('HTTP ' + res.statusCode)); res.resume(); return; }
|
|
85
|
+
const total = parseInt(res.headers['content-length'] || '0', 10);
|
|
86
|
+
let received = 0, lastPct = -1;
|
|
87
|
+
res.on('data', (chunk) => {
|
|
88
|
+
received += chunk.length;
|
|
89
|
+
if (total) {
|
|
90
|
+
const pct = Math.floor((received / total) * 100);
|
|
91
|
+
if (pct !== lastPct) { lastPct = pct; process.stdout.write('\r ⬇ Téléchargement… ' + pct + '% '); }
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const out = createWriteStream(dest);
|
|
95
|
+
pipeline(res, out).then(() => {
|
|
96
|
+
process.stdout.write('\r' + ' '.repeat(50) + '\r');
|
|
97
|
+
resolve();
|
|
98
|
+
}).catch(reject);
|
|
99
|
+
});
|
|
100
|
+
req.on('error', reject);
|
|
101
|
+
req.setTimeout(0); // pas de timeout sur un gros fichier
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ── Décompression ─────────────────────────────────────────────
|
|
106
|
+
function unzip(zipPath, destDir) {
|
|
107
|
+
if (isWin) {
|
|
108
|
+
const r = spawnSync('powershell', ['-NoProfile', '-Command',
|
|
109
|
+
'Expand-Archive -Path "' + zipPath + '" -DestinationPath "' + destDir + '" -Force'],
|
|
110
|
+
{ stdio: 'inherit' });
|
|
111
|
+
return r.status === 0;
|
|
112
|
+
}
|
|
113
|
+
// macOS / Linux : unzip, sinon tar, sinon python3
|
|
114
|
+
const attempts = [
|
|
115
|
+
['unzip', ['-oq', zipPath, '-d', destDir]],
|
|
116
|
+
['tar', ['-xf', zipPath, '-C', destDir]],
|
|
117
|
+
['python3', ['-c', 'import zipfile,sys;zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])', zipPath, destDir]]
|
|
118
|
+
];
|
|
119
|
+
for (const [cmd, args] of attempts) {
|
|
120
|
+
const r = spawnSync(cmd, args, { stdio: 'inherit' });
|
|
121
|
+
if (r.status === 0) return true;
|
|
122
|
+
}
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ── Vérification d'une install existante ─────────────────────
|
|
127
|
+
function isInstalled() {
|
|
128
|
+
return existsSync(path.join(APP_DIR, 'package.json'));
|
|
129
|
+
}
|
|
130
|
+
function installedVersion() {
|
|
131
|
+
try { return readFileSync(VERSION_FILE, 'utf8').trim(); } catch { return null; }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ── Main ──────────────────────────────────────────────────────
|
|
135
|
+
async function main() {
|
|
136
|
+
console.log('');
|
|
137
|
+
console.log(C.cyan + C.bold + BANNER + C.reset);
|
|
138
|
+
console.log(C.bgDark + C.white + ' SUPERPRINT · PAO + Studio SP213 · 100% local' + C.reset);
|
|
139
|
+
console.log(C.dim + ' Aucune donnée ne quitte votre machine.' + C.reset);
|
|
140
|
+
|
|
141
|
+
// ---- Étape 1/4 : vérification de la version en ligne ----
|
|
142
|
+
step(1, 'Vérification de la version en ligne');
|
|
143
|
+
let onlineVersion = null;
|
|
144
|
+
try { onlineVersion = await httpsGetText(APP_VERSION_URL); } catch (e) {}
|
|
145
|
+
const localVer = installedVersion();
|
|
146
|
+
|
|
147
|
+
if (isInstalled()) {
|
|
148
|
+
if (onlineVersion && localVer && onlineVersion !== localVer) {
|
|
149
|
+
info('Version en ligne (' + onlineVersion + ') ≠ locale (' + localVer + ') — mise à jour.');
|
|
150
|
+
// On supprime l'ancienne app pour re-télécharger la nouvelle
|
|
151
|
+
const { rmSync } = await import('node:fs');
|
|
152
|
+
rmSync(APP_DIR, { recursive: true, force: true });
|
|
153
|
+
} else {
|
|
154
|
+
info('Déjà installé (v' + (localVer || '?') + ') — téléchargement ignoré.');
|
|
155
|
+
}
|
|
156
|
+
ok('SuperPrint est prêt.');
|
|
157
|
+
} else {
|
|
158
|
+
info('Première installation — téléchargement de l’application.');
|
|
159
|
+
ok(onlineVersion ? 'Dernière version en ligne : v' + onlineVersion : 'Version en ligne : superprint.cc');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ---- Étape 2/4 : téléchargement + décompression ----
|
|
163
|
+
if (!isInstalled()) {
|
|
164
|
+
step(2, 'Téléchargement de l’application');
|
|
165
|
+
info('Source : ' + APP_ZIP_URL);
|
|
166
|
+
try {
|
|
167
|
+
await downloadFile(APP_ZIP_URL, ZIP_PATH);
|
|
168
|
+
ok('Téléchargé (' + Math.round(statSync(ZIP_PATH).size / 1048576) + ' Mo).');
|
|
169
|
+
} catch (e) {
|
|
170
|
+
fail('Échec du téléchargement : ' + e.message);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
step(3, 'Décompression');
|
|
175
|
+
info('Dans : ' + APP_DIR);
|
|
176
|
+
mkdirSync(APP_DIR, { recursive: true });
|
|
177
|
+
if (!unzip(ZIP_PATH, APP_DIR)) {
|
|
178
|
+
fail('Échec de la décompression du zip.');
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
ok('Application décompressée.');
|
|
182
|
+
if (onlineVersion) {
|
|
183
|
+
try { mkdirSync(APP_DIR, { recursive: true }); } catch {}
|
|
184
|
+
try { writeFileSync(VERSION_FILE, onlineVersion); } catch {}
|
|
185
|
+
}
|
|
186
|
+
// Nettoie le zip (économie de place)
|
|
187
|
+
try { unlinkSync(ZIP_PATH); } catch {}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ---- Étape 4/4 : npm install si nécessaire ----
|
|
191
|
+
if (!existsSync(path.join(APP_DIR, 'node_modules'))) {
|
|
192
|
+
step(4, 'Installation des dépendances (npm install)');
|
|
193
|
+
info('Première installation : quelques minutes. Les suivantes seront instantanées.');
|
|
194
|
+
const npmCmd = isWin ? 'npm.cmd' : 'npm';
|
|
195
|
+
const r = spawnSync(npmCmd, ['install', '--no-audit', '--no-fund'], {
|
|
196
|
+
stdio: 'inherit', cwd: APP_DIR
|
|
197
|
+
});
|
|
198
|
+
if (r.status !== 0) { fail('Échec de npm install.'); process.exit(1); }
|
|
199
|
+
ok('Dépendances installées.');
|
|
200
|
+
} else {
|
|
201
|
+
info('Dépendances déjà installées.');
|
|
202
|
+
ok('Tout est prêt.');
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ---- Lancer Vite ----
|
|
206
|
+
console.log(SEP);
|
|
207
|
+
console.log(C.green + C.bold + ' Démarrage de SuperPrint…' + C.reset);
|
|
208
|
+
console.log(C.dim + ' Ouvrez votre navigateur sur : http://localhost:5173' + C.reset);
|
|
209
|
+
console.log(SEP);
|
|
210
|
+
|
|
211
|
+
const viteBin = path.join(APP_DIR, 'node_modules', 'vite', 'bin', 'vite.js');
|
|
212
|
+
const args = process.argv.slice(2);
|
|
213
|
+
const child = spawn(process.execPath, [viteBin, ...args], {
|
|
214
|
+
stdio: 'inherit', cwd: APP_DIR
|
|
215
|
+
});
|
|
216
|
+
child.on('close', (code) => {
|
|
217
|
+
if (code !== 0 && code !== null) {
|
|
218
|
+
console.log(C.yellow + '\n Le serveur s\'est arrêté (code ' + code + ').' + C.reset);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
main().catch((e) => {
|
|
224
|
+
console.error(C.red + ' Erreur : ' + (e && e.message ? e.message : e) + C.reset);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "superprint",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "SuperPrint — logiciel de PAO (mise en page) gratuit + studio SP213 de maquettes par IA. 100% local, aucun CDN, aucune donnée ne quitte votre machine.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"superprint",
|
|
7
|
+
"sp213",
|
|
8
|
+
"pao",
|
|
9
|
+
"dtp",
|
|
10
|
+
"layout",
|
|
11
|
+
"design",
|
|
12
|
+
"print",
|
|
13
|
+
"affiche",
|
|
14
|
+
"catalogue",
|
|
15
|
+
"webllm",
|
|
16
|
+
"llm",
|
|
17
|
+
"local",
|
|
18
|
+
"webgpu"
|
|
19
|
+
],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"type": "module",
|
|
22
|
+
"bin": {
|
|
23
|
+
"superprint": "cli.mjs"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"postinstall": "node scripts/postinstall.mjs"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"cli.mjs",
|
|
33
|
+
"scripts/",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/superprint/superprint.git"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://superprint.cc",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/superprint/superprint/issues"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// S'affiche après `npm install -g superprint` ou `npx superprint`
|
|
3
|
+
console.log('');
|
|
4
|
+
console.log('\x1b[36m ═══════════════════════════════════════════════════════\x1b[0m');
|
|
5
|
+
console.log('\x1b[36m ║ SUPERPRINT — installé. Lancez avec : npx superprint \x1b[0m');
|
|
6
|
+
console.log('\x1b[36m ═══════════════════════════════════════════════════════\x1b[0m');
|
|
7
|
+
console.log('\x1b[2m · PAO + studio SP213 par IA · 100% local\x1b[0m');
|
|
8
|
+
console.log('\x1b[2m · Aucune donnée ne quitte votre machine.\x1b[0m');
|
|
9
|
+
console.log('');
|