framer-export 4.0.1 → 4.3.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/dist/cli/index.js +761 -431
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -9,6 +9,79 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// package.json
|
|
13
|
+
var package_default;
|
|
14
|
+
var init_package = __esm({
|
|
15
|
+
"package.json"() {
|
|
16
|
+
package_default = {
|
|
17
|
+
name: "framer-export",
|
|
18
|
+
version: "4.3.0",
|
|
19
|
+
description: "Export any Framer, Webflow, or Wix site into a fully working local mirror. Downloads all assets, strips badges, rewrites URLs, and pretty-prints JS.",
|
|
20
|
+
type: "module",
|
|
21
|
+
main: "dist/cli/index.js",
|
|
22
|
+
types: "dist/cli/index.d.ts",
|
|
23
|
+
bin: {
|
|
24
|
+
"framer-export": "./bin/framer-export.js",
|
|
25
|
+
fexport: "./bin/fexport.js",
|
|
26
|
+
framerexport: "./bin/framerexport.js"
|
|
27
|
+
},
|
|
28
|
+
files: [
|
|
29
|
+
"dist/",
|
|
30
|
+
"bin/",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
scripts: {
|
|
35
|
+
start: "tsx src/cli/index.ts",
|
|
36
|
+
dev: "tsx src/cli/index.ts",
|
|
37
|
+
build: "tsup",
|
|
38
|
+
typecheck: "tsc --noEmit",
|
|
39
|
+
format: 'prettier --write "src/**/*.ts"',
|
|
40
|
+
prepublishOnly: "npm run build",
|
|
41
|
+
prepack: "npm run build"
|
|
42
|
+
},
|
|
43
|
+
keywords: [
|
|
44
|
+
"framer",
|
|
45
|
+
"webflow",
|
|
46
|
+
"wix",
|
|
47
|
+
"exporter",
|
|
48
|
+
"export",
|
|
49
|
+
"scraper",
|
|
50
|
+
"mirror",
|
|
51
|
+
"site-downloader",
|
|
52
|
+
"site-export",
|
|
53
|
+
"cli"
|
|
54
|
+
],
|
|
55
|
+
repository: {
|
|
56
|
+
type: "git",
|
|
57
|
+
url: "git+https://github.com/danbenba/FramerExport.git"
|
|
58
|
+
},
|
|
59
|
+
homepage: "https://github.com/danbenba/FramerExport#readme",
|
|
60
|
+
bugs: {
|
|
61
|
+
url: "https://github.com/danbenba/FramerExport/issues"
|
|
62
|
+
},
|
|
63
|
+
license: "MIT",
|
|
64
|
+
author: "Dany (danbenba)",
|
|
65
|
+
engines: {
|
|
66
|
+
node: ">=18.0.0"
|
|
67
|
+
},
|
|
68
|
+
dependencies: {
|
|
69
|
+
chalk: "^5.3.0",
|
|
70
|
+
ora: "^8.0.0",
|
|
71
|
+
prettier: "^3.2.0",
|
|
72
|
+
puppeteer: "^22.0.0",
|
|
73
|
+
"readline-promise": "^1.0.5"
|
|
74
|
+
},
|
|
75
|
+
devDependencies: {
|
|
76
|
+
"@types/node": "^22.0.0",
|
|
77
|
+
tsup: "^8.5.1",
|
|
78
|
+
tsx: "^4.7.0",
|
|
79
|
+
typescript: "^5.4.0"
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
12
85
|
// src/cli/banner.ts
|
|
13
86
|
import chalk from "chalk";
|
|
14
87
|
function getWidth() {
|
|
@@ -19,26 +92,26 @@ function showBanner() {
|
|
|
19
92
|
const isSmall = width < 65;
|
|
20
93
|
if (isSmall) {
|
|
21
94
|
console.log(`
|
|
22
|
-
${chalk.
|
|
95
|
+
${chalk.hex("#D4A017").bold("F-EXPORT")} ${chalk.gray(`v${package_default.version}`)}`);
|
|
23
96
|
console.log(` ${chalk.white.bold("Framer \xB7 Webflow \xB7 Wix Exporter")}
|
|
24
97
|
`);
|
|
25
98
|
return;
|
|
26
99
|
}
|
|
27
|
-
const
|
|
28
|
-
const cyan = chalk.cyan.bold;
|
|
100
|
+
const gold = chalk.hex("#D4A017").bold;
|
|
29
101
|
const gray = chalk.gray;
|
|
30
102
|
console.log("");
|
|
31
103
|
ASCII_ART.forEach((line2) => {
|
|
32
|
-
console.log(" " +
|
|
104
|
+
console.log(" " + gold(line2));
|
|
33
105
|
});
|
|
34
106
|
console.log("");
|
|
35
|
-
console.log(` ${gray(
|
|
107
|
+
console.log(` ${gray(`v${package_default.version}`)} ${chalk.white.bold("Framer \xB7 Webflow \xB7 Wix Exporter")}
|
|
36
108
|
`);
|
|
37
109
|
}
|
|
38
110
|
var ASCII_ART;
|
|
39
111
|
var init_banner = __esm({
|
|
40
112
|
"src/cli/banner.ts"() {
|
|
41
113
|
"use strict";
|
|
114
|
+
init_package();
|
|
42
115
|
ASCII_ART = [
|
|
43
116
|
"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
|
|
44
117
|
"\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D",
|
|
@@ -190,6 +263,13 @@ import chalk3 from "chalk";
|
|
|
190
263
|
function setCooking(spinner) {
|
|
191
264
|
_cooking = spinner;
|
|
192
265
|
}
|
|
266
|
+
function nextMsgColor() {
|
|
267
|
+
return MSG_COLORS[_msgIdx++ % MSG_COLORS.length];
|
|
268
|
+
}
|
|
269
|
+
function trunc(text, max) {
|
|
270
|
+
if (text.length <= max) return text;
|
|
271
|
+
return text.slice(0, max - 2) + "\u2026";
|
|
272
|
+
}
|
|
193
273
|
function output(line2) {
|
|
194
274
|
if (_cooking) {
|
|
195
275
|
_cooking.log(line2);
|
|
@@ -197,20 +277,317 @@ function output(line2) {
|
|
|
197
277
|
console.log(line2);
|
|
198
278
|
}
|
|
199
279
|
}
|
|
200
|
-
var _cooking, T, log, info, warn, success;
|
|
280
|
+
var _cooking, T, TIME_COLORS, TAG_ROTATION, MSG_COLORS, _msgIdx, log, info, warn, success;
|
|
201
281
|
var init_logger = __esm({
|
|
202
282
|
"src/logger/index.ts"() {
|
|
203
283
|
"use strict";
|
|
204
284
|
_cooking = null;
|
|
205
285
|
T = () => (/* @__PURE__ */ new Date()).toISOString().slice(11, 19);
|
|
206
|
-
|
|
207
|
-
|
|
286
|
+
TIME_COLORS = [
|
|
287
|
+
chalk3.gray,
|
|
288
|
+
chalk3.hex("#9e9e9e"),
|
|
289
|
+
chalk3.hex("#757575"),
|
|
290
|
+
chalk3.hex("#6d6d6d")
|
|
291
|
+
];
|
|
292
|
+
TAG_ROTATION = [
|
|
293
|
+
(s) => chalk3.hex("#D4A017")(s),
|
|
294
|
+
(s) => chalk3.hex("#E0A030")(s),
|
|
295
|
+
(s) => chalk3.hex("#DAA520")(s),
|
|
296
|
+
(s) => chalk3.hex("#C4953A")(s),
|
|
297
|
+
(s) => chalk3.hex("#F0C040")(s)
|
|
298
|
+
];
|
|
299
|
+
MSG_COLORS = [
|
|
300
|
+
(s) => chalk3.hex("#D4A017")(s),
|
|
301
|
+
(s) => chalk3.hex("#C8A951")(s),
|
|
302
|
+
(s) => chalk3.hex("#B8960A")(s),
|
|
303
|
+
(s) => chalk3.hex("#d4a76a")(s),
|
|
304
|
+
(s) => chalk3.hex("#c0a060")(s),
|
|
305
|
+
(s) => chalk3.hex("#dab660")(s)
|
|
306
|
+
];
|
|
307
|
+
_msgIdx = 0;
|
|
308
|
+
log = (m) => {
|
|
309
|
+
const timeColor = TIME_COLORS[Math.floor(Math.random() * TIME_COLORS.length)];
|
|
310
|
+
const t = timeColor(`[${T()}]`);
|
|
311
|
+
const tag = TAG_ROTATION[0]("[LOG]");
|
|
312
|
+
const msg = nextMsgColor()(trunc(m, 120));
|
|
313
|
+
output(`${t} ${tag} ${msg}`);
|
|
314
|
+
};
|
|
315
|
+
info = (m) => {
|
|
316
|
+
const timeColor = chalk3.gray;
|
|
317
|
+
const t = timeColor(`[${T()}]`);
|
|
318
|
+
const tag = chalk3.hex("#E8A317")("[INFO]");
|
|
319
|
+
output(`${t} ${tag} ${chalk3.bold(trunc(m, 120))}`);
|
|
320
|
+
};
|
|
208
321
|
warn = (m) => {
|
|
209
|
-
const line2 = `${chalk3.gray(`[${T()}]`)} ${chalk3.
|
|
322
|
+
const line2 = `${chalk3.gray(`[${T()}]`)} ${chalk3.hex("#CC7722").bold("[WARN]")} ${chalk3.hex("#CC7722")(trunc(m, 120))}`;
|
|
210
323
|
if (_cooking) _cooking.log(line2);
|
|
211
324
|
else console.warn(line2);
|
|
212
325
|
};
|
|
213
|
-
success = (m) =>
|
|
326
|
+
success = (m) => {
|
|
327
|
+
const t = chalk3.hex("#8a8a8a")(`[${T()}]`);
|
|
328
|
+
const tag = chalk3.greenBright("[OK]");
|
|
329
|
+
const msg = chalk3.green(trunc(m, 120));
|
|
330
|
+
output(`${t} ${tag} ${msg}`);
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// src/platforms/framer.ts
|
|
336
|
+
var FONT_EXTS, framer;
|
|
337
|
+
var init_framer = __esm({
|
|
338
|
+
"src/platforms/framer.ts"() {
|
|
339
|
+
"use strict";
|
|
340
|
+
FONT_EXTS = [".woff2", ".woff", ".ttf", ".otf"];
|
|
341
|
+
framer = {
|
|
342
|
+
name: "framer",
|
|
343
|
+
displayName: "Framer",
|
|
344
|
+
detectByUrl(url) {
|
|
345
|
+
return /\.framer\.(app|website)|framercanvas\.com/.test(url);
|
|
346
|
+
},
|
|
347
|
+
detectByHtml(html) {
|
|
348
|
+
return html.includes('id="main"') && (html.includes("framerstatic.com") || html.includes("framerusercontent.com"));
|
|
349
|
+
},
|
|
350
|
+
stripDomains: ["events.framer.com", "api.framer.com", "collect.frameranalytics.com"],
|
|
351
|
+
stripSelectors: [
|
|
352
|
+
'script[src*="events.framer.com"]',
|
|
353
|
+
"#__framer-badge-container",
|
|
354
|
+
"#__framer-badge",
|
|
355
|
+
'link[href*="canvas-sandbox"]',
|
|
356
|
+
'script[src*="framer.com/bootstrap"]'
|
|
357
|
+
],
|
|
358
|
+
stripPatterns: [
|
|
359
|
+
/<div id="__framer-badge-container"[^>]*><\/div>/g,
|
|
360
|
+
/<script>try\{if\(localStorage\.get\("__framer_force_showing_editorbar_since"\)\)[^<]*<\/script>/g
|
|
361
|
+
],
|
|
362
|
+
hydrationTimeout: 1e4,
|
|
363
|
+
needsHydrationCheck: true,
|
|
364
|
+
mapAssetDir(host, pathname, ext) {
|
|
365
|
+
if (host.includes("framerusercontent.com")) {
|
|
366
|
+
if (pathname.startsWith("/images/")) return "assets/images";
|
|
367
|
+
if (pathname.startsWith("/assets/")) {
|
|
368
|
+
return FONT_EXTS.includes(ext) ? "assets/fonts" : "assets/misc";
|
|
369
|
+
}
|
|
370
|
+
if (pathname.startsWith("/sites/")) {
|
|
371
|
+
if (ext === ".mjs" || ext === ".js") return "scripts/vendor";
|
|
372
|
+
if (ext === ".json") return "data";
|
|
373
|
+
if (ext === ".css") return "styles";
|
|
374
|
+
if (ext === ".framercms") return "data";
|
|
375
|
+
return "assets/misc";
|
|
376
|
+
}
|
|
377
|
+
if (pathname.startsWith("/modules/")) {
|
|
378
|
+
return ext === ".framercms" ? "data" : "scripts/modules";
|
|
379
|
+
}
|
|
380
|
+
return "assets/misc";
|
|
381
|
+
}
|
|
382
|
+
if (host.includes("app.framerstatic.com")) {
|
|
383
|
+
if (ext === ".css") return "styles";
|
|
384
|
+
if (ext === ".mjs" || ext === ".js") return "scripts/vendor";
|
|
385
|
+
if (ext === ".woff2" || ext === ".woff") return "assets/fonts";
|
|
386
|
+
if (ext === ".png" || ext === ".svg") return "assets/images";
|
|
387
|
+
return "assets/misc";
|
|
388
|
+
}
|
|
389
|
+
if (host.includes("framercanvas.com") || host.includes("framer.com")) {
|
|
390
|
+
if (ext === ".mjs" || ext === ".js") return "scripts/vendor";
|
|
391
|
+
if (ext === ".css") return "styles";
|
|
392
|
+
return "assets/misc";
|
|
393
|
+
}
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
// src/platforms/webflow.ts
|
|
401
|
+
var IMG_EXTS, FONT_EXTS2, VIDEO_EXTS, webflow;
|
|
402
|
+
var init_webflow = __esm({
|
|
403
|
+
"src/platforms/webflow.ts"() {
|
|
404
|
+
"use strict";
|
|
405
|
+
IMG_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".svg", ".webp", ".avif"];
|
|
406
|
+
FONT_EXTS2 = [".woff2", ".woff", ".ttf", ".otf", ".eot"];
|
|
407
|
+
VIDEO_EXTS = [".mp4", ".webm", ".ogg"];
|
|
408
|
+
webflow = {
|
|
409
|
+
name: "webflow",
|
|
410
|
+
displayName: "Webflow",
|
|
411
|
+
detectByUrl(url) {
|
|
412
|
+
return /\.webflow\.(io|com)/.test(url);
|
|
413
|
+
},
|
|
414
|
+
detectByHtml(html) {
|
|
415
|
+
return html.includes("data-wf-site") || html.includes("w-webflow-badge") || html.includes("Webflow") || html.includes("webflow.js");
|
|
416
|
+
},
|
|
417
|
+
stripDomains: ["js-agent.newrelic.com", "cdn.heapanalytics.com", "tr.snapchat.com"],
|
|
418
|
+
stripSelectors: [".w-webflow-badge", 'link[href*="editorbar"]'],
|
|
419
|
+
stripPatterns: [
|
|
420
|
+
/<a[^>]*class="[^"]*w-webflow-badge[^"]*"[^>]*>[\s\S]*?<\/a>/g,
|
|
421
|
+
/<a[^>]*href="[^"]*webflow\.com\?utm_campaign=brandjs[^"]*"[^>]*>[\s\S]*?<\/a>/g,
|
|
422
|
+
/<style>[^<]*\.w-webflow-badge[^<]*<\/style>/g,
|
|
423
|
+
/Powered by <a[^>]*href="[^"]*webflow\.com"[^>]*>[^<]*<\/a>/g,
|
|
424
|
+
/<!-- This site was created in Webflow\.[^>]*-->/g,
|
|
425
|
+
/<html([^>]*) data-wf-domain="[^"]*"/g,
|
|
426
|
+
/<html([^>]*) data-wf-page="[^"]*"/g,
|
|
427
|
+
/<html([^>]*) data-wf-site="[^"]*"/g,
|
|
428
|
+
/<html([^>]*) data-wf-status="[^"]*"/g,
|
|
429
|
+
/<meta[^>]*content="Webflow"[^>]*>/g
|
|
430
|
+
],
|
|
431
|
+
hydrationTimeout: 2e3,
|
|
432
|
+
needsHydrationCheck: false,
|
|
433
|
+
mapAssetDir(host, pathname, ext) {
|
|
434
|
+
if (host.includes("website-files.com") || host.includes("webflow.com") || host.includes("uploads-ssl.webflow.com")) {
|
|
435
|
+
if (VIDEO_EXTS.includes(ext)) return "assets/videos";
|
|
436
|
+
if (pathname.includes("/images/") || IMG_EXTS.includes(ext)) return "assets/images";
|
|
437
|
+
if (pathname.includes("/css/") || ext === ".css") return "styles";
|
|
438
|
+
if (pathname.includes("/js/") || ext === ".js") return "scripts/vendor";
|
|
439
|
+
if (pathname.includes("/gsap/") || pathname.includes("/plugins/")) return "scripts/vendor";
|
|
440
|
+
if (FONT_EXTS2.includes(ext)) return "assets/fonts";
|
|
441
|
+
return "assets/misc";
|
|
442
|
+
}
|
|
443
|
+
if (host.includes("d3e54v103j8qbb.cloudfront.net")) {
|
|
444
|
+
if (ext === ".js") return "scripts/vendor";
|
|
445
|
+
if (ext === ".css") return "styles";
|
|
446
|
+
if (IMG_EXTS.includes(ext)) return "assets/images";
|
|
447
|
+
return "assets/misc";
|
|
448
|
+
}
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// src/platforms/wix.ts
|
|
456
|
+
var IMG_EXTS2, FONT_EXTS3, VIDEO_EXTS2, wix;
|
|
457
|
+
var init_wix = __esm({
|
|
458
|
+
"src/platforms/wix.ts"() {
|
|
459
|
+
"use strict";
|
|
460
|
+
IMG_EXTS2 = [".jpg", ".jpeg", ".png", ".gif", ".svg", ".webp", ".avif", ".ico"];
|
|
461
|
+
FONT_EXTS3 = [".woff2", ".woff", ".ttf", ".otf", ".eot"];
|
|
462
|
+
VIDEO_EXTS2 = [".mp4", ".webm", ".ogg"];
|
|
463
|
+
wix = {
|
|
464
|
+
name: "wix",
|
|
465
|
+
displayName: "Wix",
|
|
466
|
+
detectByUrl(url) {
|
|
467
|
+
return /\.wixsite\.com|\.wix\.com/.test(url);
|
|
468
|
+
},
|
|
469
|
+
detectByHtml(html) {
|
|
470
|
+
return html.includes("wix-viewer-model") || html.includes('id="WIX_ADS"') || html.includes("X-Wix-") || html.includes("Wix.com") || html.includes("wixcode-sdk") || html.includes("data-wix") || html.includes("wix-code") || html.includes("WixCode") || /\bwix\.com\b/.test(html) || /meta\s+name=["']generator["']\s+content=["'][^"']*Wix[^"']*["']/i.test(html) || /_wix_/i.test(html) || /wix-ecom/i.test(html);
|
|
471
|
+
},
|
|
472
|
+
stripDomains: [
|
|
473
|
+
"frog.wix.com",
|
|
474
|
+
"bi.wixapi.com",
|
|
475
|
+
"fed.wixcodescheduler.com",
|
|
476
|
+
"editor.wix.com",
|
|
477
|
+
"panorama.wixapps.net"
|
|
478
|
+
],
|
|
479
|
+
stripSelectors: ["#WIX_ADS", ".wix-ads", "#wix-badge", "#SCROLL_TO_TOP"],
|
|
480
|
+
stripPatterns: [
|
|
481
|
+
/<div[^>]*class="[^"]*wix-ads[^"]*"[^>]*>[\s\S]*?<\/div>/g
|
|
482
|
+
],
|
|
483
|
+
hydrationTimeout: 3e3,
|
|
484
|
+
needsHydrationCheck: false,
|
|
485
|
+
mapAssetDir(host, pathname, ext) {
|
|
486
|
+
if (host === "video.wixstatic.com") {
|
|
487
|
+
return "assets/videos";
|
|
488
|
+
}
|
|
489
|
+
if (host.includes("wixstatic.com")) {
|
|
490
|
+
if (VIDEO_EXTS2.includes(ext)) return "assets/videos";
|
|
491
|
+
if (pathname.includes("/images/") || IMG_EXTS2.includes(ext)) return "assets/images";
|
|
492
|
+
if (ext === ".css") return "styles";
|
|
493
|
+
if (ext === ".js") return "scripts/vendor";
|
|
494
|
+
if (FONT_EXTS3.includes(ext)) return "assets/fonts";
|
|
495
|
+
return "assets/misc";
|
|
496
|
+
}
|
|
497
|
+
if (host.includes("parastorage.com")) {
|
|
498
|
+
if (ext === ".js") return "scripts/vendor";
|
|
499
|
+
if (ext === ".css") return "styles";
|
|
500
|
+
if (FONT_EXTS3.includes(ext)) return "assets/fonts";
|
|
501
|
+
if (IMG_EXTS2.includes(ext)) return "assets/images";
|
|
502
|
+
return "assets/misc";
|
|
503
|
+
}
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
// src/platforms/detect.ts
|
|
511
|
+
function detectByUrl(url) {
|
|
512
|
+
for (const platform of ALL_PLATFORMS) {
|
|
513
|
+
if (platform.detectByUrl(url)) return platform;
|
|
514
|
+
}
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
function detectByHtml(html) {
|
|
518
|
+
for (const platform of ALL_PLATFORMS) {
|
|
519
|
+
if (platform.detectByHtml(html)) return platform;
|
|
520
|
+
}
|
|
521
|
+
return null;
|
|
522
|
+
}
|
|
523
|
+
function detectPlatform(url, html) {
|
|
524
|
+
const byUrl = detectByUrl(url);
|
|
525
|
+
if (byUrl) return byUrl;
|
|
526
|
+
if (html) {
|
|
527
|
+
const byHtml = detectByHtml(html);
|
|
528
|
+
if (byHtml) return byHtml;
|
|
529
|
+
}
|
|
530
|
+
return framer;
|
|
531
|
+
}
|
|
532
|
+
async function detectByDom(page) {
|
|
533
|
+
try {
|
|
534
|
+
const signal = await page.evaluate(() => {
|
|
535
|
+
const html = document.documentElement.outerHTML || "";
|
|
536
|
+
if (/wix-viewer-model|_wix_|wix-ecom/i.test(html)) return "wix";
|
|
537
|
+
if (/data-wf-|w-webflow-badge|webflow\.js/i.test(html)) return "webflow";
|
|
538
|
+
if (/framerusercontent|framercanvas|framerstatic/i.test(html)) return "framer";
|
|
539
|
+
const srcs = [];
|
|
540
|
+
const scripts = document.querySelectorAll("script[src]");
|
|
541
|
+
scripts.forEach((s) => {
|
|
542
|
+
if (s.src) srcs.push(s.src);
|
|
543
|
+
});
|
|
544
|
+
const allSrcs = srcs.join(" ");
|
|
545
|
+
if (/wixstatic\.com|parastorage\.com/.test(allSrcs)) return "wix";
|
|
546
|
+
if (/website-files\.com|webflow\.com/.test(allSrcs)) return "webflow";
|
|
547
|
+
if (/framerusercontent\.com|framerstatic\.com|framer\.app/.test(allSrcs)) return "framer";
|
|
548
|
+
return "";
|
|
549
|
+
});
|
|
550
|
+
if (signal === "wix") return wix;
|
|
551
|
+
if (signal === "webflow") return webflow;
|
|
552
|
+
if (signal === "framer") return framer;
|
|
553
|
+
} catch {
|
|
554
|
+
}
|
|
555
|
+
return null;
|
|
556
|
+
}
|
|
557
|
+
function getPlatformByName(name) {
|
|
558
|
+
const map = { framer, webflow, wix };
|
|
559
|
+
return map[name] || framer;
|
|
560
|
+
}
|
|
561
|
+
var ALL_PLATFORMS;
|
|
562
|
+
var init_detect = __esm({
|
|
563
|
+
"src/platforms/detect.ts"() {
|
|
564
|
+
"use strict";
|
|
565
|
+
init_framer();
|
|
566
|
+
init_webflow();
|
|
567
|
+
init_wix();
|
|
568
|
+
ALL_PLATFORMS = [framer, webflow, wix];
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// src/platforms/index.ts
|
|
573
|
+
var platforms_exports = {};
|
|
574
|
+
__export(platforms_exports, {
|
|
575
|
+
detectByDom: () => detectByDom,
|
|
576
|
+
detectByHtml: () => detectByHtml,
|
|
577
|
+
detectByUrl: () => detectByUrl,
|
|
578
|
+
detectPlatform: () => detectPlatform,
|
|
579
|
+
framer: () => framer,
|
|
580
|
+
getPlatformByName: () => getPlatformByName,
|
|
581
|
+
webflow: () => webflow,
|
|
582
|
+
wix: () => wix
|
|
583
|
+
});
|
|
584
|
+
var init_platforms = __esm({
|
|
585
|
+
"src/platforms/index.ts"() {
|
|
586
|
+
"use strict";
|
|
587
|
+
init_framer();
|
|
588
|
+
init_webflow();
|
|
589
|
+
init_wix();
|
|
590
|
+
init_detect();
|
|
214
591
|
}
|
|
215
592
|
});
|
|
216
593
|
|
|
@@ -269,6 +646,12 @@ async function launchAndCapture(exporter) {
|
|
|
269
646
|
});
|
|
270
647
|
success("Page loaded (networkidle2)");
|
|
271
648
|
log("Intercepted " + intercepted + " resources, blocked " + blocked + " tracking requests");
|
|
649
|
+
log("Checking DOM-based platform detection...");
|
|
650
|
+
const domDetected = await detectByDom(exporter.page);
|
|
651
|
+
if (domDetected && domDetected.name !== exporter.platform.name) {
|
|
652
|
+
log("Platform refined from DOM: " + domDetected.displayName + " (override: " + exporter.platform.name + ")");
|
|
653
|
+
exporter.platform = domDetected;
|
|
654
|
+
}
|
|
272
655
|
exporter.cooking?.update("Waiting for " + exporter.platform.displayName + " hydration...");
|
|
273
656
|
if (exporter.platform.needsHydrationCheck) {
|
|
274
657
|
log("Checking for #main element hydration...");
|
|
@@ -330,15 +713,42 @@ async function launchAndCapture(exporter) {
|
|
|
330
713
|
const imgCount = [...exporter.assets.entries.values()].filter((e) => e.localPath.startsWith("assets/images")).length;
|
|
331
714
|
const fontCount = [...exporter.assets.entries.values()].filter((e) => e.localPath.startsWith("assets/fonts")).length;
|
|
332
715
|
log(" CSS: " + cssCount + " | JS: " + jsCount + " | Images: " + imgCount + " | Fonts: " + fontCount);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
716
|
+
}
|
|
717
|
+
async function closeBrowser(exporter) {
|
|
718
|
+
if (exporter.browser) {
|
|
719
|
+
await exporter.browser.close();
|
|
720
|
+
exporter.browser = null;
|
|
721
|
+
log("Browser closed");
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
async function captureSubpage(page, url, platform) {
|
|
725
|
+
log(" Navigating to sub-page: " + url);
|
|
726
|
+
await page.goto(url, { waitUntil: "networkidle2", timeout: CFG.timeout });
|
|
727
|
+
if (platform.needsHydrationCheck) {
|
|
728
|
+
await page.evaluate(
|
|
729
|
+
`new Promise(function(r) {
|
|
730
|
+
var t = Date.now();
|
|
731
|
+
(function tick() {
|
|
732
|
+
var m = document.getElementById('main') || document.body;
|
|
733
|
+
if (m && m.children.length > 0) setTimeout(r, 500);
|
|
734
|
+
else if (Date.now() - t > ${platform.hydrationTimeout}) r();
|
|
735
|
+
else setTimeout(tick, 200);
|
|
736
|
+
})();
|
|
737
|
+
})`
|
|
738
|
+
);
|
|
739
|
+
} else {
|
|
740
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
741
|
+
}
|
|
742
|
+
const html = await page.evaluate(() => document.documentElement.outerHTML || document.body.innerHTML);
|
|
743
|
+
log(" Sub-page fetched: " + (html.length / 1024).toFixed(1) + " KB");
|
|
744
|
+
return html;
|
|
336
745
|
}
|
|
337
746
|
var init_capture = __esm({
|
|
338
747
|
"src/exporter/capture.ts"() {
|
|
339
748
|
"use strict";
|
|
340
749
|
init_config();
|
|
341
750
|
init_logger();
|
|
751
|
+
init_platforms();
|
|
342
752
|
}
|
|
343
753
|
});
|
|
344
754
|
|
|
@@ -694,417 +1104,207 @@ async function buildOutput(exporter) {
|
|
|
694
1104
|
}
|
|
695
1105
|
async function rewriteDownloadedFiles(exporter) {
|
|
696
1106
|
const dirs = ["scripts/vendor", "scripts/modules", "styles"];
|
|
697
|
-
let rewritten = 0;
|
|
698
|
-
for (const dir of dirs) {
|
|
699
|
-
const fullDir = path3.join(exporter.outDir, dir);
|
|
700
|
-
let files;
|
|
701
|
-
try {
|
|
702
|
-
files = await fs2.readdir(fullDir);
|
|
703
|
-
} catch {
|
|
704
|
-
continue;
|
|
705
|
-
}
|
|
706
|
-
for (const file of files) {
|
|
707
|
-
const ext = path3.extname(file).toLowerCase();
|
|
708
|
-
if (![".mjs", ".js", ".css"].includes(ext)) continue;
|
|
709
|
-
const filePath = path3.join(fullDir, file);
|
|
710
|
-
try {
|
|
711
|
-
let content = await fs2.readFile(filePath, "utf-8");
|
|
712
|
-
const before = content;
|
|
713
|
-
content = exporter.assets.rewrite(content, dir);
|
|
714
|
-
if (content !== before) {
|
|
715
|
-
await fs2.writeFile(filePath, content);
|
|
716
|
-
rewritten++;
|
|
717
|
-
}
|
|
718
|
-
} catch {
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
log("Rewrote URLs in " + rewritten + " JS/CSS files");
|
|
723
|
-
}
|
|
724
|
-
async function prettifyDownloadedJS(exporter) {
|
|
725
|
-
const dirs = ["scripts/vendor", "scripts/modules"];
|
|
726
|
-
let count = 0;
|
|
727
|
-
let total = 0;
|
|
728
|
-
for (const dir of dirs) {
|
|
729
|
-
const fullDir = path3.join(exporter.outDir, dir);
|
|
730
|
-
let files;
|
|
731
|
-
try {
|
|
732
|
-
files = await fs2.readdir(fullDir);
|
|
733
|
-
} catch {
|
|
734
|
-
continue;
|
|
735
|
-
}
|
|
736
|
-
const jsFiles = files.filter((f) => {
|
|
737
|
-
const ext = path3.extname(f).toLowerCase();
|
|
738
|
-
return ext === ".mjs" || ext === ".js";
|
|
739
|
-
});
|
|
740
|
-
total += jsFiles.length;
|
|
741
|
-
for (const file of jsFiles) {
|
|
742
|
-
const filePath = path3.join(fullDir, file);
|
|
743
|
-
try {
|
|
744
|
-
const raw = await fs2.readFile(filePath, "utf-8");
|
|
745
|
-
const nlRatio = (raw.match(/\n/g) || []).length / raw.length;
|
|
746
|
-
if (nlRatio > 0.05) {
|
|
747
|
-
count++;
|
|
748
|
-
continue;
|
|
749
|
-
}
|
|
750
|
-
const pretty = await prettifyJS(raw);
|
|
751
|
-
await fs2.writeFile(filePath, pretty, "utf-8");
|
|
752
|
-
count++;
|
|
753
|
-
if (count % 5 === 0) {
|
|
754
|
-
exporter.cooking?.update("Pretty-printing... (" + count + "/" + total + ")");
|
|
755
|
-
}
|
|
756
|
-
} catch (e) {
|
|
757
|
-
warn("Pretty-print skipped: " + file + " - " + e.message);
|
|
758
|
-
count++;
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
success("Formatted " + count + "/" + total + " JS/MJS files");
|
|
763
|
-
}
|
|
764
|
-
var init_output = __esm({
|
|
765
|
-
"src/exporter/output.ts"() {
|
|
766
|
-
"use strict";
|
|
767
|
-
init_logger();
|
|
768
|
-
init_prettify();
|
|
769
|
-
init_template();
|
|
770
|
-
}
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
// src/exporter/summary.ts
|
|
774
|
-
import fs3 from "fs/promises";
|
|
775
|
-
import path4 from "path";
|
|
776
|
-
import chalk4 from "chalk";
|
|
777
|
-
function getWidth2() {
|
|
778
|
-
return process.stdout.columns || 80;
|
|
779
|
-
}
|
|
780
|
-
async function printSummary(exporter) {
|
|
781
|
-
const width = getWidth2();
|
|
782
|
-
const isSmall = width < 50;
|
|
783
|
-
const count = async (d) => {
|
|
784
|
-
try {
|
|
785
|
-
return (await fs3.readdir(path4.join(exporter.outDir, d))).length;
|
|
786
|
-
} catch {
|
|
787
|
-
return 0;
|
|
788
|
-
}
|
|
789
|
-
};
|
|
790
|
-
const [imgs, fonts, videos, misc, scripts, vendor, styles, data] = await Promise.all([
|
|
791
|
-
count("assets/images"),
|
|
792
|
-
count("assets/fonts"),
|
|
793
|
-
count("assets/videos"),
|
|
794
|
-
count("assets/misc"),
|
|
795
|
-
count("scripts/modules"),
|
|
796
|
-
count("scripts/vendor"),
|
|
797
|
-
count("styles"),
|
|
798
|
-
count("data")
|
|
799
|
-
]);
|
|
800
|
-
console.log("");
|
|
801
|
-
if (!isSmall) {
|
|
802
|
-
console.log(chalk4.magenta(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
803
|
-
console.log(chalk4.magenta(" \u2502") + chalk4.bold.white(" Export Summary ") + chalk4.magenta("\u2502"));
|
|
804
|
-
console.log(chalk4.magenta(" \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
|
|
805
|
-
} else {
|
|
806
|
-
console.log(chalk4.bold.white(" Export Summary:"));
|
|
807
|
-
}
|
|
808
|
-
const row = (label, count2, type) => {
|
|
809
|
-
if (count2 === 0) return;
|
|
810
|
-
const l = label.padEnd(18);
|
|
811
|
-
const c = String(count2).padStart(3);
|
|
812
|
-
if (isSmall) {
|
|
813
|
-
console.log(` ${chalk4.yellow(label)} ${chalk4.white(String(count2))} ${chalk4.gray(type)}`);
|
|
814
|
-
} else {
|
|
815
|
-
console.log(` ${chalk4.magenta("\u2502")} ${chalk4.yellow(l)} ${chalk4.white(c)} ${chalk4.gray(type.padEnd(20))} ${chalk4.magenta("\u2502")}`);
|
|
816
|
-
}
|
|
817
|
-
};
|
|
818
|
-
row("styles/", styles, "CSS files");
|
|
819
|
-
row("scripts/vendor/", vendor, "JS modules");
|
|
820
|
-
row("scripts/modules/", scripts, "components");
|
|
821
|
-
row("assets/images/", imgs, "images");
|
|
822
|
-
row("assets/videos/", videos, "videos");
|
|
823
|
-
row("assets/fonts/", fonts, "fonts");
|
|
824
|
-
row("assets/misc/", misc, "misc files");
|
|
825
|
-
row("data/", data, "data files");
|
|
826
|
-
if (!isSmall) {
|
|
827
|
-
console.log(chalk4.magenta(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
828
|
-
}
|
|
829
|
-
console.log("");
|
|
830
|
-
const quotedDir = `"${exporter.outDir}"`;
|
|
831
|
-
if (!isSmall) {
|
|
832
|
-
console.log(chalk4.magenta(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
833
|
-
console.log(chalk4.magenta(" \u2502") + chalk4.bold.white(" To serve locally ") + chalk4.magenta("\u2502"));
|
|
834
|
-
console.log(chalk4.magenta(" \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
|
|
835
|
-
console.log(` ${chalk4.magenta("\u2502")} ${chalk4.cyan("cd " + path4.basename(exporter.outDir) + " && node serve.cjs").padEnd(44)} ${chalk4.magenta("\u2502")}`);
|
|
836
|
-
console.log(chalk4.magenta(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
837
|
-
} else {
|
|
838
|
-
console.log(chalk4.bold.white(" To serve locally:"));
|
|
839
|
-
console.log(` ${chalk4.cyan("cd " + path4.basename(exporter.outDir) + " && node serve.cjs")}`);
|
|
840
|
-
}
|
|
841
|
-
console.log("");
|
|
842
|
-
console.log(chalk4.gray(" NOTE: Must be served via HTTP for JS modules to work."));
|
|
843
|
-
console.log("");
|
|
844
|
-
}
|
|
845
|
-
var init_summary = __esm({
|
|
846
|
-
"src/exporter/summary.ts"() {
|
|
847
|
-
"use strict";
|
|
848
|
-
}
|
|
849
|
-
});
|
|
850
|
-
|
|
851
|
-
// src/platforms/framer.ts
|
|
852
|
-
var FONT_EXTS, framer;
|
|
853
|
-
var init_framer = __esm({
|
|
854
|
-
"src/platforms/framer.ts"() {
|
|
855
|
-
"use strict";
|
|
856
|
-
FONT_EXTS = [".woff2", ".woff", ".ttf", ".otf"];
|
|
857
|
-
framer = {
|
|
858
|
-
name: "framer",
|
|
859
|
-
displayName: "Framer",
|
|
860
|
-
detectByUrl(url) {
|
|
861
|
-
return /\.framer\.(app|website)|framercanvas\.com/.test(url);
|
|
862
|
-
},
|
|
863
|
-
detectByHtml(html) {
|
|
864
|
-
return html.includes('id="main"') && (html.includes("framerstatic.com") || html.includes("framerusercontent.com"));
|
|
865
|
-
},
|
|
866
|
-
stripDomains: ["events.framer.com", "api.framer.com", "collect.frameranalytics.com"],
|
|
867
|
-
stripSelectors: [
|
|
868
|
-
'script[src*="events.framer.com"]',
|
|
869
|
-
"#__framer-badge-container",
|
|
870
|
-
"#__framer-badge",
|
|
871
|
-
'link[href*="canvas-sandbox"]',
|
|
872
|
-
'script[src*="framer.com/bootstrap"]'
|
|
873
|
-
],
|
|
874
|
-
stripPatterns: [
|
|
875
|
-
/<div id="__framer-badge-container"[^>]*><\/div>/g,
|
|
876
|
-
/<script>try\{if\(localStorage\.get\("__framer_force_showing_editorbar_since"\)\)[^<]*<\/script>/g
|
|
877
|
-
],
|
|
878
|
-
hydrationTimeout: 1e4,
|
|
879
|
-
needsHydrationCheck: true,
|
|
880
|
-
mapAssetDir(host, pathname, ext) {
|
|
881
|
-
if (host.includes("framerusercontent.com")) {
|
|
882
|
-
if (pathname.startsWith("/images/")) return "assets/images";
|
|
883
|
-
if (pathname.startsWith("/assets/")) {
|
|
884
|
-
return FONT_EXTS.includes(ext) ? "assets/fonts" : "assets/misc";
|
|
885
|
-
}
|
|
886
|
-
if (pathname.startsWith("/sites/")) {
|
|
887
|
-
if (ext === ".mjs" || ext === ".js") return "scripts/vendor";
|
|
888
|
-
if (ext === ".json") return "data";
|
|
889
|
-
if (ext === ".css") return "styles";
|
|
890
|
-
if (ext === ".framercms") return "data";
|
|
891
|
-
return "assets/misc";
|
|
892
|
-
}
|
|
893
|
-
if (pathname.startsWith("/modules/")) {
|
|
894
|
-
return ext === ".framercms" ? "data" : "scripts/modules";
|
|
895
|
-
}
|
|
896
|
-
return "assets/misc";
|
|
897
|
-
}
|
|
898
|
-
if (host.includes("app.framerstatic.com")) {
|
|
899
|
-
if (ext === ".css") return "styles";
|
|
900
|
-
if (ext === ".mjs" || ext === ".js") return "scripts/vendor";
|
|
901
|
-
if (ext === ".woff2" || ext === ".woff") return "assets/fonts";
|
|
902
|
-
if (ext === ".png" || ext === ".svg") return "assets/images";
|
|
903
|
-
return "assets/misc";
|
|
904
|
-
}
|
|
905
|
-
if (host.includes("framercanvas.com") || host.includes("framer.com")) {
|
|
906
|
-
if (ext === ".mjs" || ext === ".js") return "scripts/vendor";
|
|
907
|
-
if (ext === ".css") return "styles";
|
|
908
|
-
return "assets/misc";
|
|
909
|
-
}
|
|
910
|
-
return null;
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
});
|
|
915
|
-
|
|
916
|
-
// src/platforms/webflow.ts
|
|
917
|
-
var IMG_EXTS, FONT_EXTS2, VIDEO_EXTS, webflow;
|
|
918
|
-
var init_webflow = __esm({
|
|
919
|
-
"src/platforms/webflow.ts"() {
|
|
920
|
-
"use strict";
|
|
921
|
-
IMG_EXTS = [".jpg", ".jpeg", ".png", ".gif", ".svg", ".webp", ".avif"];
|
|
922
|
-
FONT_EXTS2 = [".woff2", ".woff", ".ttf", ".otf", ".eot"];
|
|
923
|
-
VIDEO_EXTS = [".mp4", ".webm", ".ogg"];
|
|
924
|
-
webflow = {
|
|
925
|
-
name: "webflow",
|
|
926
|
-
displayName: "Webflow",
|
|
927
|
-
detectByUrl(url) {
|
|
928
|
-
return /\.webflow\.(io|com)/.test(url);
|
|
929
|
-
},
|
|
930
|
-
detectByHtml(html) {
|
|
931
|
-
return html.includes("data-wf-site") || html.includes("w-webflow-badge") || html.includes("Webflow") || html.includes("webflow.js");
|
|
932
|
-
},
|
|
933
|
-
stripDomains: ["js-agent.newrelic.com", "cdn.heapanalytics.com", "tr.snapchat.com"],
|
|
934
|
-
stripSelectors: [".w-webflow-badge", 'link[href*="editorbar"]'],
|
|
935
|
-
stripPatterns: [
|
|
936
|
-
/<a[^>]*class="[^"]*w-webflow-badge[^"]*"[^>]*>[\s\S]*?<\/a>/g,
|
|
937
|
-
/<a[^>]*href="[^"]*webflow\.com\?utm_campaign=brandjs[^"]*"[^>]*>[\s\S]*?<\/a>/g,
|
|
938
|
-
/<style>[^<]*\.w-webflow-badge[^<]*<\/style>/g,
|
|
939
|
-
/Powered by <a[^>]*href="[^"]*webflow\.com"[^>]*>[^<]*<\/a>/g,
|
|
940
|
-
/<!-- This site was created in Webflow\.[^>]*-->/g,
|
|
941
|
-
/<html([^>]*) data-wf-domain="[^"]*"/g,
|
|
942
|
-
/<html([^>]*) data-wf-page="[^"]*"/g,
|
|
943
|
-
/<html([^>]*) data-wf-site="[^"]*"/g,
|
|
944
|
-
/<html([^>]*) data-wf-status="[^"]*"/g,
|
|
945
|
-
/<meta[^>]*content="Webflow"[^>]*>/g
|
|
946
|
-
],
|
|
947
|
-
hydrationTimeout: 2e3,
|
|
948
|
-
needsHydrationCheck: false,
|
|
949
|
-
mapAssetDir(host, pathname, ext) {
|
|
950
|
-
if (host.includes("website-files.com") || host.includes("webflow.com") || host.includes("uploads-ssl.webflow.com")) {
|
|
951
|
-
if (VIDEO_EXTS.includes(ext)) return "assets/videos";
|
|
952
|
-
if (pathname.includes("/images/") || IMG_EXTS.includes(ext)) return "assets/images";
|
|
953
|
-
if (pathname.includes("/css/") || ext === ".css") return "styles";
|
|
954
|
-
if (pathname.includes("/js/") || ext === ".js") return "scripts/vendor";
|
|
955
|
-
if (pathname.includes("/gsap/") || pathname.includes("/plugins/")) return "scripts/vendor";
|
|
956
|
-
if (FONT_EXTS2.includes(ext)) return "assets/fonts";
|
|
957
|
-
return "assets/misc";
|
|
958
|
-
}
|
|
959
|
-
if (host.includes("d3e54v103j8qbb.cloudfront.net")) {
|
|
960
|
-
if (ext === ".js") return "scripts/vendor";
|
|
961
|
-
if (ext === ".css") return "styles";
|
|
962
|
-
if (IMG_EXTS.includes(ext)) return "assets/images";
|
|
963
|
-
return "assets/misc";
|
|
1107
|
+
let rewritten = 0;
|
|
1108
|
+
for (const dir of dirs) {
|
|
1109
|
+
const fullDir = path3.join(exporter.outDir, dir);
|
|
1110
|
+
let files;
|
|
1111
|
+
try {
|
|
1112
|
+
files = await fs2.readdir(fullDir);
|
|
1113
|
+
} catch {
|
|
1114
|
+
continue;
|
|
1115
|
+
}
|
|
1116
|
+
for (const file of files) {
|
|
1117
|
+
const ext = path3.extname(file).toLowerCase();
|
|
1118
|
+
if (![".mjs", ".js", ".css"].includes(ext)) continue;
|
|
1119
|
+
const filePath = path3.join(fullDir, file);
|
|
1120
|
+
try {
|
|
1121
|
+
let content = await fs2.readFile(filePath, "utf-8");
|
|
1122
|
+
const before = content;
|
|
1123
|
+
content = exporter.assets.rewrite(content, dir);
|
|
1124
|
+
if (content !== before) {
|
|
1125
|
+
await fs2.writeFile(filePath, content);
|
|
1126
|
+
rewritten++;
|
|
964
1127
|
}
|
|
965
|
-
|
|
1128
|
+
} catch {
|
|
966
1129
|
}
|
|
967
|
-
}
|
|
1130
|
+
}
|
|
968
1131
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
stripPatterns: [
|
|
997
|
-
/<div[^>]*class="[^"]*wix-ads[^"]*"[^>]*>[\s\S]*?<\/div>/g
|
|
998
|
-
],
|
|
999
|
-
hydrationTimeout: 3e3,
|
|
1000
|
-
needsHydrationCheck: false,
|
|
1001
|
-
mapAssetDir(host, pathname, ext) {
|
|
1002
|
-
if (host === "video.wixstatic.com") {
|
|
1003
|
-
return "assets/videos";
|
|
1004
|
-
}
|
|
1005
|
-
if (host.includes("wixstatic.com")) {
|
|
1006
|
-
if (VIDEO_EXTS2.includes(ext)) return "assets/videos";
|
|
1007
|
-
if (pathname.includes("/images/") || IMG_EXTS2.includes(ext)) return "assets/images";
|
|
1008
|
-
if (ext === ".css") return "styles";
|
|
1009
|
-
if (ext === ".js") return "scripts/vendor";
|
|
1010
|
-
if (FONT_EXTS3.includes(ext)) return "assets/fonts";
|
|
1011
|
-
return "assets/misc";
|
|
1132
|
+
log("Rewrote URLs in " + rewritten + " JS/CSS files");
|
|
1133
|
+
}
|
|
1134
|
+
async function prettifyDownloadedJS(exporter) {
|
|
1135
|
+
const dirs = ["scripts/vendor", "scripts/modules"];
|
|
1136
|
+
let count = 0;
|
|
1137
|
+
let total = 0;
|
|
1138
|
+
for (const dir of dirs) {
|
|
1139
|
+
const fullDir = path3.join(exporter.outDir, dir);
|
|
1140
|
+
let files;
|
|
1141
|
+
try {
|
|
1142
|
+
files = await fs2.readdir(fullDir);
|
|
1143
|
+
} catch {
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
const jsFiles = files.filter((f) => {
|
|
1147
|
+
const ext = path3.extname(f).toLowerCase();
|
|
1148
|
+
return ext === ".mjs" || ext === ".js";
|
|
1149
|
+
});
|
|
1150
|
+
total += jsFiles.length;
|
|
1151
|
+
for (const file of jsFiles) {
|
|
1152
|
+
const filePath = path3.join(fullDir, file);
|
|
1153
|
+
try {
|
|
1154
|
+
const raw = await fs2.readFile(filePath, "utf-8");
|
|
1155
|
+
const nlRatio = (raw.match(/\n/g) || []).length / raw.length;
|
|
1156
|
+
if (nlRatio > 0.05) {
|
|
1157
|
+
count++;
|
|
1158
|
+
continue;
|
|
1012
1159
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
return "assets/misc";
|
|
1160
|
+
const pretty = await prettifyJS(raw);
|
|
1161
|
+
await fs2.writeFile(filePath, pretty, "utf-8");
|
|
1162
|
+
count++;
|
|
1163
|
+
if (count % 5 === 0) {
|
|
1164
|
+
exporter.cooking?.update("Pretty-printing... (" + count + "/" + total + ")");
|
|
1019
1165
|
}
|
|
1020
|
-
|
|
1166
|
+
} catch (e) {
|
|
1167
|
+
warn("Pretty-print skipped: " + file + " - " + e.message);
|
|
1168
|
+
count++;
|
|
1021
1169
|
}
|
|
1022
|
-
}
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
success("Formatted " + count + "/" + total + " JS/MJS files");
|
|
1173
|
+
}
|
|
1174
|
+
var init_output = __esm({
|
|
1175
|
+
"src/exporter/output.ts"() {
|
|
1176
|
+
"use strict";
|
|
1177
|
+
init_logger();
|
|
1178
|
+
init_prettify();
|
|
1179
|
+
init_template();
|
|
1023
1180
|
}
|
|
1024
1181
|
});
|
|
1025
1182
|
|
|
1026
|
-
// src/
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
return
|
|
1183
|
+
// src/exporter/summary.ts
|
|
1184
|
+
import fs3 from "fs/promises";
|
|
1185
|
+
import path4 from "path";
|
|
1186
|
+
import chalk4 from "chalk";
|
|
1187
|
+
function getWidth2() {
|
|
1188
|
+
return process.stdout.columns || 80;
|
|
1032
1189
|
}
|
|
1033
|
-
function
|
|
1034
|
-
|
|
1035
|
-
|
|
1190
|
+
async function printSummary(exporter) {
|
|
1191
|
+
const width = getWidth2();
|
|
1192
|
+
const isSmall = width < 50;
|
|
1193
|
+
const count = async (d) => {
|
|
1194
|
+
try {
|
|
1195
|
+
return (await fs3.readdir(path4.join(exporter.outDir, d))).length;
|
|
1196
|
+
} catch {
|
|
1197
|
+
return 0;
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
const [imgs, fonts, videos, misc, scripts, vendor, styles, data] = await Promise.all([
|
|
1201
|
+
count("assets/images"),
|
|
1202
|
+
count("assets/fonts"),
|
|
1203
|
+
count("assets/videos"),
|
|
1204
|
+
count("assets/misc"),
|
|
1205
|
+
count("scripts/modules"),
|
|
1206
|
+
count("scripts/vendor"),
|
|
1207
|
+
count("styles"),
|
|
1208
|
+
count("data")
|
|
1209
|
+
]);
|
|
1210
|
+
const G = chalk4.hex("#D4A017");
|
|
1211
|
+
console.log("");
|
|
1212
|
+
if (!isSmall) {
|
|
1213
|
+
console.log(G(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
1214
|
+
console.log(G(" \u2502") + chalk4.bold.white(" Export Summary ") + G("\u2502"));
|
|
1215
|
+
console.log(G(" \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
|
|
1216
|
+
} else {
|
|
1217
|
+
console.log(chalk4.bold.white(" Export Summary:"));
|
|
1036
1218
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1219
|
+
const row = (label, count2, type) => {
|
|
1220
|
+
if (count2 === 0) return;
|
|
1221
|
+
const l = label.padEnd(18);
|
|
1222
|
+
const c = String(count2).padStart(3);
|
|
1223
|
+
if (isSmall) {
|
|
1224
|
+
console.log(` ${chalk4.yellow(label)} ${chalk4.white(String(count2))} ${chalk4.gray(type)}`);
|
|
1225
|
+
} else {
|
|
1226
|
+
console.log(` ${G("\u2502")} ${chalk4.yellow(l)} ${chalk4.white(c)} ${chalk4.gray(type.padEnd(20))} ${G("\u2502")}`);
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
row("styles/", styles, "CSS files");
|
|
1230
|
+
row("scripts/vendor/", vendor, "JS modules");
|
|
1231
|
+
row("scripts/modules/", scripts, "components");
|
|
1232
|
+
row("assets/images/", imgs, "images");
|
|
1233
|
+
row("assets/videos/", videos, "videos");
|
|
1234
|
+
row("assets/fonts/", fonts, "fonts");
|
|
1235
|
+
row("assets/misc/", misc, "misc files");
|
|
1236
|
+
row("data/", data, "data files");
|
|
1237
|
+
if (!isSmall) {
|
|
1238
|
+
console.log(G(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
1045
1239
|
}
|
|
1046
|
-
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
"
|
|
1056
|
-
|
|
1057
|
-
init_webflow();
|
|
1058
|
-
init_wix();
|
|
1059
|
-
ALL_PLATFORMS = [framer, webflow, wix];
|
|
1240
|
+
console.log("");
|
|
1241
|
+
const quotedDir = `"${exporter.outDir}"`;
|
|
1242
|
+
if (!isSmall) {
|
|
1243
|
+
console.log(G(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
1244
|
+
console.log(G(" \u2502") + chalk4.bold.white(" To serve locally ") + G("\u2502"));
|
|
1245
|
+
console.log(G(" \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
|
|
1246
|
+
console.log(` ${G("\u2502")} ${chalk4.hex("#D4A017")("cd " + path4.basename(exporter.outDir) + " && node serve.cjs").padEnd(44)} ${G("\u2502")}`);
|
|
1247
|
+
console.log(G(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
1248
|
+
} else {
|
|
1249
|
+
console.log(chalk4.bold.white(" To serve locally:"));
|
|
1250
|
+
console.log(` ${chalk4.hex("#D4A017")("cd " + path4.basename(exporter.outDir) + " && node serve.cjs")}`);
|
|
1060
1251
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
detectByUrl: () => detectByUrl,
|
|
1068
|
-
detectPlatform: () => detectPlatform,
|
|
1069
|
-
framer: () => framer,
|
|
1070
|
-
getPlatformByName: () => getPlatformByName,
|
|
1071
|
-
webflow: () => webflow,
|
|
1072
|
-
wix: () => wix
|
|
1073
|
-
});
|
|
1074
|
-
var init_platforms = __esm({
|
|
1075
|
-
"src/platforms/index.ts"() {
|
|
1252
|
+
console.log("");
|
|
1253
|
+
console.log(chalk4.gray(" NOTE: Must be served via HTTP for JS modules to work."));
|
|
1254
|
+
console.log("");
|
|
1255
|
+
}
|
|
1256
|
+
var init_summary = __esm({
|
|
1257
|
+
"src/exporter/summary.ts"() {
|
|
1076
1258
|
"use strict";
|
|
1077
|
-
init_framer();
|
|
1078
|
-
init_webflow();
|
|
1079
|
-
init_wix();
|
|
1080
|
-
init_detect();
|
|
1081
1259
|
}
|
|
1082
1260
|
});
|
|
1083
1261
|
|
|
1084
1262
|
// src/cli/cooking.ts
|
|
1085
1263
|
import chalk5 from "chalk";
|
|
1086
|
-
var SHINE_WIDTH, CookingSpinner;
|
|
1264
|
+
var SHINE_WIDTH, FRAME_INTERVAL, SPINNER_FRAMES, PALETTE, CookingSpinner;
|
|
1087
1265
|
var init_cooking = __esm({
|
|
1088
1266
|
"src/cli/cooking.ts"() {
|
|
1089
1267
|
"use strict";
|
|
1090
|
-
SHINE_WIDTH =
|
|
1268
|
+
SHINE_WIDTH = 10;
|
|
1269
|
+
FRAME_INTERVAL = 140;
|
|
1270
|
+
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1271
|
+
PALETTE = [
|
|
1272
|
+
(s) => chalk5.hex("#D4A017")(s),
|
|
1273
|
+
(s) => chalk5.hex("#E8A317")(s),
|
|
1274
|
+
(s) => chalk5.hex("#DAA520")(s),
|
|
1275
|
+
(s) => chalk5.hex("#F0C040")(s),
|
|
1276
|
+
(s) => chalk5.hex("#C4953A")(s),
|
|
1277
|
+
(s) => chalk5.hex("#E6B83C")(s),
|
|
1278
|
+
(s) => chalk5.hex("#C8A951")(s),
|
|
1279
|
+
(s) => chalk5.hex("#D9B44D")(s)
|
|
1280
|
+
];
|
|
1091
1281
|
CookingSpinner = class {
|
|
1092
1282
|
interval = null;
|
|
1283
|
+
bgInterval = null;
|
|
1093
1284
|
frame = 0;
|
|
1094
1285
|
phase = "";
|
|
1095
1286
|
active = false;
|
|
1287
|
+
bar = 0;
|
|
1288
|
+
barDir = 1;
|
|
1096
1289
|
start(phase = "") {
|
|
1097
1290
|
this.phase = phase;
|
|
1098
1291
|
this.frame = 0;
|
|
1292
|
+
this.bar = 0;
|
|
1293
|
+
this.barDir = 1;
|
|
1099
1294
|
this.active = true;
|
|
1100
1295
|
this.draw();
|
|
1101
1296
|
this.interval = setInterval(() => {
|
|
1102
1297
|
this.frame++;
|
|
1103
1298
|
this.draw();
|
|
1104
|
-
},
|
|
1299
|
+
}, FRAME_INTERVAL);
|
|
1300
|
+
this.bgInterval = setInterval(() => {
|
|
1301
|
+
this.bar++;
|
|
1302
|
+
this.draw();
|
|
1303
|
+
}, 800);
|
|
1105
1304
|
}
|
|
1106
1305
|
update(phase) {
|
|
1107
1306
|
this.phase = phase;
|
|
1307
|
+
if (!this.active) this.draw();
|
|
1108
1308
|
}
|
|
1109
1309
|
log(message) {
|
|
1110
1310
|
if (this.active) {
|
|
@@ -1121,18 +1321,27 @@ var init_cooking = __esm({
|
|
|
1121
1321
|
clearInterval(this.interval);
|
|
1122
1322
|
this.interval = null;
|
|
1123
1323
|
}
|
|
1324
|
+
if (this.bgInterval) {
|
|
1325
|
+
clearInterval(this.bgInterval);
|
|
1326
|
+
this.bgInterval = null;
|
|
1327
|
+
}
|
|
1124
1328
|
process.stdout.write("\r\x1B[2K");
|
|
1125
1329
|
}
|
|
1126
1330
|
draw() {
|
|
1127
1331
|
if (!this.active) return;
|
|
1128
|
-
const
|
|
1129
|
-
const
|
|
1130
|
-
const
|
|
1131
|
-
const
|
|
1132
|
-
const shimmer = this.renderShimmer(
|
|
1133
|
-
const
|
|
1134
|
-
const
|
|
1135
|
-
|
|
1332
|
+
const spinner = SPINNER_FRAMES[this.frame % SPINNER_FRAMES.length];
|
|
1333
|
+
const paletteFn = PALETTE[this.frame % PALETTE.length];
|
|
1334
|
+
const dotPhase = Math.floor(this.frame / 3) % 4;
|
|
1335
|
+
const dotStr = dotPhase === 0 ? " " : dotPhase === 1 ? ". " : dotPhase === 2 ? ".. " : "...";
|
|
1336
|
+
const shimmer = this.renderShimmer("Cooking");
|
|
1337
|
+
const spinnerChar = chalk5.hex("#F0C040")(spinner);
|
|
1338
|
+
const barLen = 12;
|
|
1339
|
+
const barPos = this.bar % (barLen * 2);
|
|
1340
|
+
const barStr = this.renderBar(barLen, barPos);
|
|
1341
|
+
const phaseStr = this.phase ? ` ${chalk5.gray(this.limitLen(this.phase, 38))}` : "";
|
|
1342
|
+
process.stdout.write(
|
|
1343
|
+
`\r\x1B[2K ${spinnerChar} ${shimmer} ${paletteFn(dotStr)} ${barStr}${phaseStr}`
|
|
1344
|
+
);
|
|
1136
1345
|
}
|
|
1137
1346
|
renderShimmer(text) {
|
|
1138
1347
|
let result = "";
|
|
@@ -1141,14 +1350,36 @@ var init_cooking = __esm({
|
|
|
1141
1350
|
const dist = Math.abs(i - pos);
|
|
1142
1351
|
if (dist < SHINE_WIDTH) {
|
|
1143
1352
|
const t = 1 - dist / SHINE_WIDTH;
|
|
1144
|
-
const
|
|
1145
|
-
result += chalk5.rgb(
|
|
1353
|
+
const g = Math.floor(160 + t * 95);
|
|
1354
|
+
result += chalk5.rgb(g, g, g)(text[i]);
|
|
1146
1355
|
} else {
|
|
1147
|
-
result += chalk5.rgb(
|
|
1356
|
+
result += chalk5.rgb(160, 160, 160)(text[i]);
|
|
1148
1357
|
}
|
|
1149
1358
|
}
|
|
1150
1359
|
return result;
|
|
1151
1360
|
}
|
|
1361
|
+
renderBar(len, pos) {
|
|
1362
|
+
let s = "";
|
|
1363
|
+
for (let i = 0; i < len; i++) {
|
|
1364
|
+
const dist = Math.abs(i - pos);
|
|
1365
|
+
if (dist < 3) {
|
|
1366
|
+
const t = 1 - dist / 3;
|
|
1367
|
+
const r = Math.floor(200 + t * 55);
|
|
1368
|
+
const g = Math.floor(160 + t * 50);
|
|
1369
|
+
const b = Math.floor(20 + t * 30);
|
|
1370
|
+
s += chalk5.rgb(r, g, b)("\u258C");
|
|
1371
|
+
} else if (dist < 6) {
|
|
1372
|
+
s += chalk5.rgb(140, 100, 20)("\u258C");
|
|
1373
|
+
} else {
|
|
1374
|
+
s += chalk5.rgb(50, 35, 10)(" ");
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
return `[${s}]`;
|
|
1378
|
+
}
|
|
1379
|
+
limitLen(s, max) {
|
|
1380
|
+
if (s.length <= max) return s;
|
|
1381
|
+
return s.slice(0, max - 3) + "\u2026";
|
|
1382
|
+
}
|
|
1152
1383
|
};
|
|
1153
1384
|
}
|
|
1154
1385
|
});
|
|
@@ -1219,11 +1450,14 @@ var init_exporter = __esm({
|
|
|
1219
1450
|
this.platform = detectPlatform(siteUrl);
|
|
1220
1451
|
}
|
|
1221
1452
|
}
|
|
1222
|
-
async run() {
|
|
1223
|
-
console.log(chalk6.bold.
|
|
1453
|
+
async run(includeSubpages = false) {
|
|
1454
|
+
console.log(chalk6.bold.hex("#D4A017")("\n Cooksite v4 - Full Mirror & Clean Export\n"));
|
|
1224
1455
|
info("Source : " + chalk6.underline(this.siteUrl));
|
|
1225
1456
|
info("Output : " + chalk6.yellow(this.outDir));
|
|
1226
|
-
info("Platform : " + chalk6.
|
|
1457
|
+
info("Platform : " + chalk6.hex("#D4A017")(this.platform.displayName));
|
|
1458
|
+
if (includeSubpages) {
|
|
1459
|
+
info("Subpages : " + chalk6.green("enabled"));
|
|
1460
|
+
}
|
|
1227
1461
|
console.log("");
|
|
1228
1462
|
this.cooking = new CookingSpinner();
|
|
1229
1463
|
setCooking(this.cooking);
|
|
@@ -1237,7 +1471,8 @@ var init_exporter = __esm({
|
|
|
1237
1471
|
"styles",
|
|
1238
1472
|
"scripts/vendor",
|
|
1239
1473
|
"scripts/modules",
|
|
1240
|
-
"data"
|
|
1474
|
+
"data",
|
|
1475
|
+
"subpages"
|
|
1241
1476
|
]) {
|
|
1242
1477
|
await fs4.mkdir(path5.join(this.outDir, d), { recursive: true });
|
|
1243
1478
|
}
|
|
@@ -1254,9 +1489,13 @@ var init_exporter = __esm({
|
|
|
1254
1489
|
const htmlDetected = detectPlatform(this.siteUrl, this.ssrHTML);
|
|
1255
1490
|
if (htmlDetected.name !== this.platform.name) {
|
|
1256
1491
|
this.platform = htmlDetected;
|
|
1257
|
-
log("Platform refined: " + chalk6.
|
|
1492
|
+
log("Platform refined: " + chalk6.hex("#D4A017")(this.platform.displayName) + " (from HTML analysis)");
|
|
1258
1493
|
}
|
|
1259
1494
|
await launchAndCapture(this);
|
|
1495
|
+
if (includeSubpages && this.page) {
|
|
1496
|
+
await this.crawlSubpages();
|
|
1497
|
+
}
|
|
1498
|
+
await closeBrowser(this);
|
|
1260
1499
|
this.cooking.update("Downloading assets...");
|
|
1261
1500
|
await downloadAll(this);
|
|
1262
1501
|
this.cooking.update("Building output...");
|
|
@@ -1267,6 +1506,64 @@ var init_exporter = __esm({
|
|
|
1267
1506
|
success("Export complete!");
|
|
1268
1507
|
await printSummary(this);
|
|
1269
1508
|
}
|
|
1509
|
+
async crawlSubpages() {
|
|
1510
|
+
this.cooking?.update("Discovering sub-pages...");
|
|
1511
|
+
log("Scanning page for internal links...");
|
|
1512
|
+
const page = this.page;
|
|
1513
|
+
const baseUrl = new URL(this.siteUrl);
|
|
1514
|
+
const baseHost = baseUrl.hostname.replace(/^www\./, "");
|
|
1515
|
+
const links = await page.evaluate((host) => {
|
|
1516
|
+
const anchors = Array.from(document.querySelectorAll("a[href]"));
|
|
1517
|
+
const hrefs = /* @__PURE__ */ new Set();
|
|
1518
|
+
for (const a of anchors) {
|
|
1519
|
+
const href = a.href;
|
|
1520
|
+
if (!href || href.startsWith("javascript:") || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("#")) continue;
|
|
1521
|
+
try {
|
|
1522
|
+
const u = new URL(href);
|
|
1523
|
+
const h = u.hostname.replace(/^www\./, "");
|
|
1524
|
+
if (h === host && u.pathname !== "/" && u.pathname !== "" && !u.pathname.startsWith("/#")) {
|
|
1525
|
+
hrefs.add(href.split("#")[0]);
|
|
1526
|
+
}
|
|
1527
|
+
} catch {
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
return Array.from(hrefs);
|
|
1531
|
+
}, baseHost);
|
|
1532
|
+
log("Found " + links.length + " sub-page links");
|
|
1533
|
+
const uniqueLinks = [...new Set(links)].slice(0, 50);
|
|
1534
|
+
if (uniqueLinks.length === 0) {
|
|
1535
|
+
log("No sub-pages to crawl");
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
for (let i = 0; i < uniqueLinks.length; i++) {
|
|
1539
|
+
const link = uniqueLinks[i];
|
|
1540
|
+
this.cooking?.update("Crawling sub-page " + (i + 1) + "/" + uniqueLinks.length);
|
|
1541
|
+
try {
|
|
1542
|
+
const html = await captureSubpage(page, link, {
|
|
1543
|
+
needsHydrationCheck: this.platform.needsHydrationCheck,
|
|
1544
|
+
hydrationTimeout: this.platform.hydrationTimeout
|
|
1545
|
+
});
|
|
1546
|
+
const slug = this.deriveSlug(link, baseUrl);
|
|
1547
|
+
const filename = slug + ".html";
|
|
1548
|
+
const filepath = path5.join(this.outDir, "subpages", filename);
|
|
1549
|
+
await fs4.writeFile(filepath, html, "utf-8");
|
|
1550
|
+
log(" Saved: subpages/" + filename);
|
|
1551
|
+
} catch (e) {
|
|
1552
|
+
log(" Skipped " + link + ": " + e.message);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
success("Sub-pages crawled: " + uniqueLinks.length);
|
|
1556
|
+
}
|
|
1557
|
+
deriveSlug(link, baseUrl) {
|
|
1558
|
+
try {
|
|
1559
|
+
const u = new URL(link);
|
|
1560
|
+
let pathname = u.pathname.replace(/\/+$/, "").replace(/^\//, "");
|
|
1561
|
+
if (!pathname) return "index";
|
|
1562
|
+
return pathname.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_") || "page";
|
|
1563
|
+
} catch {
|
|
1564
|
+
return "page";
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1270
1567
|
};
|
|
1271
1568
|
}
|
|
1272
1569
|
});
|
|
@@ -1283,10 +1580,10 @@ async function select(question, options, defaultIndex = 0) {
|
|
|
1283
1580
|
stdout.write(`\x1B[${options.length + 1}A`);
|
|
1284
1581
|
stdout.write("\x1B[J");
|
|
1285
1582
|
}
|
|
1286
|
-
console.log(` ${chalk7.
|
|
1583
|
+
console.log(` ${chalk7.hex("#D4A017")("?")} ${chalk7.white.bold(question)}`);
|
|
1287
1584
|
for (let i = 0; i < options.length; i++) {
|
|
1288
1585
|
if (i === selected) {
|
|
1289
|
-
console.log(` ${chalk7.
|
|
1586
|
+
console.log(` ${chalk7.hex("#D4A017")(">")} ${chalk7.white.bold(options[i].label)}`);
|
|
1290
1587
|
} else {
|
|
1291
1588
|
console.log(` ${chalk7.gray(options[i].label)}`);
|
|
1292
1589
|
}
|
|
@@ -1310,7 +1607,7 @@ async function select(question, options, defaultIndex = 0) {
|
|
|
1310
1607
|
stdin.pause();
|
|
1311
1608
|
stdout.write(`\x1B[${options.length + 1}A`);
|
|
1312
1609
|
stdout.write("\x1B[J");
|
|
1313
|
-
console.log(` ${chalk7.green("\u2713")} ${chalk7.white.bold(question)} ${chalk7.
|
|
1610
|
+
console.log(` ${chalk7.green("\u2713")} ${chalk7.white.bold(question)} ${chalk7.hex("#D4A017")(options[selected].label)}
|
|
1314
1611
|
`);
|
|
1315
1612
|
resolve(options[selected].value);
|
|
1316
1613
|
} else if (key.ctrl && key.name === "c" || key.name === "escape") {
|
|
@@ -1345,7 +1642,7 @@ function getWidth3() {
|
|
|
1345
1642
|
function drawHeader(title) {
|
|
1346
1643
|
const width = getWidth3();
|
|
1347
1644
|
const isSmall = width < 50;
|
|
1348
|
-
const magenta = chalk8.
|
|
1645
|
+
const magenta = chalk8.hex("#D4A017");
|
|
1349
1646
|
const boldWhite = chalk8.bold.white;
|
|
1350
1647
|
if (isSmall) {
|
|
1351
1648
|
console.log(`
|
|
@@ -1363,7 +1660,7 @@ ${magenta("\u25CF")} ${boldWhite(title)}`);
|
|
|
1363
1660
|
function line(label, value) {
|
|
1364
1661
|
const width = getWidth3();
|
|
1365
1662
|
const isSmall = width < 50;
|
|
1366
|
-
const magenta = chalk8.
|
|
1663
|
+
const magenta = chalk8.hex("#D4A017");
|
|
1367
1664
|
if (isSmall) {
|
|
1368
1665
|
console.log(` ${chalk8.bold(label)}: ${chalk8.yellow(value)}`);
|
|
1369
1666
|
return;
|
|
@@ -1377,7 +1674,7 @@ async function runSetup(legacyMode = false) {
|
|
|
1377
1674
|
const rl = readline2.createInterface({ input: stdin2, output: stdout2 });
|
|
1378
1675
|
const ask = async (question, defaultVal) => {
|
|
1379
1676
|
const suffix = defaultVal ? chalk8.gray(` (${defaultVal})`) : "";
|
|
1380
|
-
const prompt = ` ${chalk8.
|
|
1677
|
+
const prompt = ` ${chalk8.hex("#D4A017")("?")} ${chalk8.white.bold(question)}${suffix} ${chalk8.gray(">")} `;
|
|
1381
1678
|
const answer = await rl.question(prompt);
|
|
1382
1679
|
return answer.trim() || defaultVal || "";
|
|
1383
1680
|
};
|
|
@@ -1399,10 +1696,10 @@ async function runSetup(legacyMode = false) {
|
|
|
1399
1696
|
const detected = detectPlatform(siteUrl);
|
|
1400
1697
|
let platformName;
|
|
1401
1698
|
if (legacyMode) {
|
|
1402
|
-
console.log(` ${chalk8.blue("i")} Auto-detected: ${chalk8.
|
|
1699
|
+
console.log(` ${chalk8.blue("i")} Auto-detected: ${chalk8.hex("#D4A017")(detected.displayName)}`);
|
|
1403
1700
|
const platformInput = await ask("Platform (framer/webflow/wix)", detected.name);
|
|
1404
1701
|
platformName = ["framer", "webflow", "wix"].includes(platformInput) ? platformInput : detected.name;
|
|
1405
|
-
console.log(` ${chalk8.green("\u2713")} ${chalk8.green("Platform:")} ${chalk8.
|
|
1702
|
+
console.log(` ${chalk8.green("\u2713")} ${chalk8.green("Platform:")} ${chalk8.hex("#D4A017")(platformName)}
|
|
1406
1703
|
`);
|
|
1407
1704
|
} else {
|
|
1408
1705
|
rl.close();
|
|
@@ -1417,7 +1714,7 @@ async function runSetup(legacyMode = false) {
|
|
|
1417
1714
|
const rl2 = legacyMode ? rl : readline2.createInterface({ input: stdin2, output: stdout2 });
|
|
1418
1715
|
const ask2 = async (question, defaultVal) => {
|
|
1419
1716
|
const suffix = defaultVal ? chalk8.gray(` (${defaultVal})`) : "";
|
|
1420
|
-
const prompt = ` ${chalk8.
|
|
1717
|
+
const prompt = ` ${chalk8.hex("#D4A017")("?")} ${chalk8.white.bold(question)}${suffix} ${chalk8.gray(">")} `;
|
|
1421
1718
|
const answer = await rl2.question(prompt);
|
|
1422
1719
|
return answer.trim() || defaultVal || "";
|
|
1423
1720
|
};
|
|
@@ -1429,10 +1726,15 @@ async function runSetup(legacyMode = false) {
|
|
|
1429
1726
|
drawHeader("Step 4 : Options");
|
|
1430
1727
|
let prettyPrint;
|
|
1431
1728
|
let concurrency;
|
|
1729
|
+
let includeSubpages;
|
|
1432
1730
|
if (legacyMode) {
|
|
1433
1731
|
const prettyAnswer = await ask2("Pretty-print JS files? (y/n)", "y");
|
|
1434
1732
|
prettyPrint = prettyAnswer.toLowerCase().startsWith("y");
|
|
1435
1733
|
console.log(` ${chalk8.green("\u2713")} Pretty-print: ${prettyPrint ? chalk8.green("yes") : chalk8.red("no")}
|
|
1734
|
+
`);
|
|
1735
|
+
const subpagesAnswer = await ask2("Export sub-pages? (y/n)", "n");
|
|
1736
|
+
includeSubpages = subpagesAnswer.toLowerCase().startsWith("y");
|
|
1737
|
+
console.log(` ${chalk8.green("\u2713")} Sub-pages: ${includeSubpages ? chalk8.green("yes") : chalk8.red("no")}
|
|
1436
1738
|
`);
|
|
1437
1739
|
const concurrencyAnswer = await ask2("Download concurrency", "12");
|
|
1438
1740
|
concurrency = parseInt(concurrencyAnswer, 10) || 12;
|
|
@@ -1445,6 +1747,11 @@ async function runSetup(legacyMode = false) {
|
|
|
1445
1747
|
{ label: "No", value: "no" }
|
|
1446
1748
|
]);
|
|
1447
1749
|
prettyPrint = prettyVal === "yes";
|
|
1750
|
+
const subpagesVal = await select("Export sub-pages?", [
|
|
1751
|
+
{ label: "No", value: "no" },
|
|
1752
|
+
{ label: "Yes, crawl and export", value: "yes" }
|
|
1753
|
+
], 0);
|
|
1754
|
+
includeSubpages = subpagesVal === "yes";
|
|
1448
1755
|
const concurrencyVal = await select("Download concurrency", [
|
|
1449
1756
|
{ label: "6 (slow connection)", value: "6" },
|
|
1450
1757
|
{ label: "12 (default)", value: "12" },
|
|
@@ -1456,9 +1763,9 @@ async function runSetup(legacyMode = false) {
|
|
|
1456
1763
|
const width = getWidth3();
|
|
1457
1764
|
const isSmall = width < 50;
|
|
1458
1765
|
if (!isSmall) {
|
|
1459
|
-
console.log(chalk8.
|
|
1460
|
-
console.log(chalk8.
|
|
1461
|
-
console.log(chalk8.
|
|
1766
|
+
console.log(chalk8.hex("#D4A017")(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
1767
|
+
console.log(chalk8.hex("#D4A017")(" \u2502") + chalk8.bold.white(" Summary ") + chalk8.hex("#D4A017")("\u2502"));
|
|
1768
|
+
console.log(chalk8.hex("#D4A017")(" \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
|
|
1462
1769
|
} else {
|
|
1463
1770
|
console.log(chalk8.bold.white(" Summary:"));
|
|
1464
1771
|
}
|
|
@@ -1466,9 +1773,10 @@ async function runSetup(legacyMode = false) {
|
|
|
1466
1773
|
line("Platform", platformName);
|
|
1467
1774
|
line("Output", path6.resolve(outDir));
|
|
1468
1775
|
line("Pretty-print", prettyPrint ? "yes" : "no");
|
|
1776
|
+
line("Sub-pages", includeSubpages ? "yes" : "no");
|
|
1469
1777
|
line("Concurrency", String(concurrency));
|
|
1470
1778
|
if (!isSmall) {
|
|
1471
|
-
console.log(chalk8.
|
|
1779
|
+
console.log(chalk8.hex("#D4A017")(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
1472
1780
|
}
|
|
1473
1781
|
console.log("");
|
|
1474
1782
|
let startExport;
|
|
@@ -1494,7 +1802,7 @@ async function runSetup(legacyMode = false) {
|
|
|
1494
1802
|
CFG2.concurrency = concurrency;
|
|
1495
1803
|
const exporter = new FramerExporter(siteUrl, path6.resolve(outDir), platformName);
|
|
1496
1804
|
exporter.prettyPrint = prettyPrint;
|
|
1497
|
-
await exporter.run();
|
|
1805
|
+
await exporter.run(includeSubpages);
|
|
1498
1806
|
}
|
|
1499
1807
|
var init_setup = __esm({
|
|
1500
1808
|
"src/cli/setup.ts"() {
|
|
@@ -1507,6 +1815,7 @@ var init_setup = __esm({
|
|
|
1507
1815
|
});
|
|
1508
1816
|
|
|
1509
1817
|
// src/cli/index.ts
|
|
1818
|
+
init_package();
|
|
1510
1819
|
import path7 from "path";
|
|
1511
1820
|
import { URL as URL5 } from "url";
|
|
1512
1821
|
|
|
@@ -1516,14 +1825,14 @@ import chalk2 from "chalk";
|
|
|
1516
1825
|
function showHelp() {
|
|
1517
1826
|
showBanner();
|
|
1518
1827
|
console.log(chalk2.white.bold(" USAGE\n"));
|
|
1519
|
-
console.log(` ${chalk2.
|
|
1520
|
-
console.log(` ${chalk2.
|
|
1521
|
-
console.log(` ${chalk2.cyan("framer-export")} ${chalk2.yellow("<url>")} ${chalk2.gray("[output-dir]")}`);
|
|
1828
|
+
console.log(` ${chalk2.hex("#D4A017")("framer-export")} ${chalk2.yellow("<url>")} ${chalk2.gray("[output-dir]")}`);
|
|
1829
|
+
console.log(` ${chalk2.hex("#D4A017")("fexport")} ${chalk2.yellow("<url>")} ${chalk2.gray("[output-dir]")}`);
|
|
1522
1830
|
console.log("");
|
|
1523
1831
|
console.log(chalk2.white.bold(" OPTIONS\n"));
|
|
1524
1832
|
const opts = [
|
|
1525
1833
|
["--setup", "Launch the interactive setup assistant"],
|
|
1526
1834
|
["--platform <p>", "Force platform: framer, webflow, wix"],
|
|
1835
|
+
["--subpages", "Crawl and export sub-pages"],
|
|
1527
1836
|
["--legacy-mode", "Use text input instead of arrow selection"],
|
|
1528
1837
|
["--help, -h", "Show this help message"]
|
|
1529
1838
|
];
|
|
@@ -1533,21 +1842,22 @@ function showHelp() {
|
|
|
1533
1842
|
console.log("");
|
|
1534
1843
|
console.log(chalk2.white.bold(" SUPPORTED PLATFORMS\n"));
|
|
1535
1844
|
const platforms = [
|
|
1536
|
-
["Framer", "Auto-detected via .framer.app / .framer.
|
|
1845
|
+
["Framer", "Auto-detected via .framer.app / .framer.website URLs"],
|
|
1537
1846
|
["Webflow", "Auto-detected via .webflow.io URLs"],
|
|
1538
|
-
["Wix", "Auto-detected via .wixsite.com URLs"]
|
|
1847
|
+
["Wix", "Auto-detected via .wixsite.com URLs + HTML analysis"]
|
|
1539
1848
|
];
|
|
1540
1849
|
for (const [name, desc] of platforms) {
|
|
1541
|
-
console.log(` ${chalk2.
|
|
1850
|
+
console.log(` ${chalk2.hex("#D4A017")(name.padEnd(12))} ${chalk2.gray(desc)}`);
|
|
1542
1851
|
}
|
|
1543
1852
|
console.log("");
|
|
1544
1853
|
console.log(chalk2.white.bold(" EXAMPLES\n"));
|
|
1545
|
-
console.log(` ${chalk2.gray("$")} ${chalk2.
|
|
1546
|
-
console.log(` ${chalk2.gray("$")} ${chalk2.
|
|
1547
|
-
console.log(` ${chalk2.gray("$")} ${chalk2.
|
|
1548
|
-
console.log(` ${chalk2.gray("$")} ${chalk2.
|
|
1549
|
-
console.log(` ${chalk2.gray("$")} ${chalk2.
|
|
1550
|
-
console.log(` ${chalk2.gray("$")} ${chalk2.
|
|
1854
|
+
console.log(` ${chalk2.gray("$")} ${chalk2.hex("#D4A017")("framer-export")} ${chalk2.yellow("https://mysite.framer.app")}`);
|
|
1855
|
+
console.log(` ${chalk2.gray("$")} ${chalk2.hex("#D4A017")("framer-export")} ${chalk2.yellow("https://mysite.webflow.io")}`);
|
|
1856
|
+
console.log(` ${chalk2.gray("$")} ${chalk2.hex("#D4A017")("framer-export")} ${chalk2.yellow("https://user.wixsite.com/my-site")}`);
|
|
1857
|
+
console.log(` ${chalk2.gray("$")} ${chalk2.hex("#D4A017")("framer-export")} ${chalk2.green("--platform webflow")} ${chalk2.yellow("https://custom.com")}`);
|
|
1858
|
+
console.log(` ${chalk2.gray("$")} ${chalk2.hex("#D4A017")("framer-export")} ${chalk2.green("--subpages")} ${chalk2.yellow("https://mysite.com")}`);
|
|
1859
|
+
console.log(` ${chalk2.gray("$")} ${chalk2.hex("#D4A017")("framer-export")} ${chalk2.green("--setup")}`);
|
|
1860
|
+
console.log(` ${chalk2.gray("$")} ${chalk2.hex("#D4A017")("framer-export")} ${chalk2.green("--setup --legacy-mode")}`);
|
|
1551
1861
|
console.log("");
|
|
1552
1862
|
}
|
|
1553
1863
|
|
|
@@ -1586,7 +1896,7 @@ async function checkForUpdates(currentVersion) {
|
|
|
1586
1896
|
}
|
|
1587
1897
|
|
|
1588
1898
|
// src/cli/index.ts
|
|
1589
|
-
var VERSION =
|
|
1899
|
+
var VERSION = package_default.version;
|
|
1590
1900
|
function extractFlag(args, flag) {
|
|
1591
1901
|
const idx = args.indexOf(flag);
|
|
1592
1902
|
if (idx === -1 || idx + 1 >= args.length) return null;
|
|
@@ -1602,6 +1912,25 @@ function hasFlag(args, flag) {
|
|
|
1602
1912
|
}
|
|
1603
1913
|
async function main() {
|
|
1604
1914
|
const args = process.argv.slice(2);
|
|
1915
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
1916
|
+
console.log(VERSION);
|
|
1917
|
+
process.exit(0);
|
|
1918
|
+
}
|
|
1919
|
+
if (args.includes("--about")) {
|
|
1920
|
+
const chalk9 = (await import("chalk")).default;
|
|
1921
|
+
showBanner();
|
|
1922
|
+
console.log(` ${chalk9.white.bold("Framer Export")} ${chalk9.gray(`v${package_default.version}`)}`);
|
|
1923
|
+
console.log(` ${chalk9.white(package_default.description)}
|
|
1924
|
+
`);
|
|
1925
|
+
console.log(` ${chalk9.white.bold("Author")} ${chalk9.hex("#D4A017")("Dany (danbenba)")}`);
|
|
1926
|
+
console.log(` ${chalk9.white.bold("Portfolio")} ${chalk9.underline.hex("#D4A017")("https://github.com/danbenba")}`);
|
|
1927
|
+
console.log(` ${chalk9.white.bold("GitHub")} ${chalk9.underline.hex("#D4A017")(package_default.repository.url.replace("git+", "").replace(".git", ""))}`);
|
|
1928
|
+
console.log(` ${chalk9.white.bold("npm")} ${chalk9.underline.hex("#D4A017")(`https://www.npmjs.com/package/${package_default.name}`)}`);
|
|
1929
|
+
console.log(` ${chalk9.white.bold("License")} ${chalk9.green(package_default.license)}`);
|
|
1930
|
+
console.log(` ${chalk9.white.bold("Node")} ${chalk9.gray(`>=${package_default.engines.node}`)}`);
|
|
1931
|
+
console.log("");
|
|
1932
|
+
process.exit(0);
|
|
1933
|
+
}
|
|
1605
1934
|
checkForUpdates(VERSION).then((latest) => {
|
|
1606
1935
|
if (!latest) return;
|
|
1607
1936
|
import("chalk").then((chalk9) => {
|
|
@@ -1609,7 +1938,7 @@ async function main() {
|
|
|
1609
1938
|
console.log(
|
|
1610
1939
|
` ${chalk9.default.yellow("\u21B3")} Update available: ${chalk9.default.gray(VERSION)} \u2192 ${chalk9.default.green(latest)}`
|
|
1611
1940
|
);
|
|
1612
|
-
console.log(` ${chalk9.default.
|
|
1941
|
+
console.log(` ${chalk9.default.hex("#D4A017")(" Run:")} ${chalk9.default.hex("#B8860B")("npm i -g framer-export@latest")}`);
|
|
1613
1942
|
console.log("");
|
|
1614
1943
|
});
|
|
1615
1944
|
});
|
|
@@ -1630,6 +1959,7 @@ async function main() {
|
|
|
1630
1959
|
return;
|
|
1631
1960
|
}
|
|
1632
1961
|
const platformOverride = extractFlag(args, "--platform");
|
|
1962
|
+
const includeSubpages = hasFlag(args, "--subpages");
|
|
1633
1963
|
showBanner();
|
|
1634
1964
|
const url = args[0];
|
|
1635
1965
|
try {
|
|
@@ -1647,7 +1977,7 @@ async function main() {
|
|
|
1647
1977
|
const defaultDir = deriveOutputName2(url, detected);
|
|
1648
1978
|
const out = args[1] || `./${defaultDir}`;
|
|
1649
1979
|
try {
|
|
1650
|
-
await new FramerExporter2(url, path7.resolve(out), platformOverride || void 0).run();
|
|
1980
|
+
await new FramerExporter2(url, path7.resolve(out), platformOverride || void 0).run(includeSubpages);
|
|
1651
1981
|
} catch (e) {
|
|
1652
1982
|
const chalk9 = (await import("chalk")).default;
|
|
1653
1983
|
console.log(`
|