framer-export 4.3.8 → 4.3.10
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 +421 -120
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "framer-export",
|
|
18
|
-
version: "4.3.
|
|
18
|
+
version: "4.3.10",
|
|
19
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
20
|
type: "module",
|
|
21
21
|
main: "dist/cli/index.js",
|
|
@@ -103,6 +103,16 @@ function chip(label) {
|
|
|
103
103
|
function bullet(label = "\u2022") {
|
|
104
104
|
return ui.primary(label);
|
|
105
105
|
}
|
|
106
|
+
function centerText(text, width) {
|
|
107
|
+
const visible = stripAnsi(text).length;
|
|
108
|
+
if (visible >= width) return text;
|
|
109
|
+
const left = Math.floor((width - visible) / 2);
|
|
110
|
+
return " ".repeat(left) + text + " ".repeat(width - visible - left);
|
|
111
|
+
}
|
|
112
|
+
function truncatePlain(text, max) {
|
|
113
|
+
if (text.length <= max) return text;
|
|
114
|
+
return text.slice(0, Math.max(0, max - 2)) + "..";
|
|
115
|
+
}
|
|
106
116
|
var THEME, ui;
|
|
107
117
|
var init_theme = __esm({
|
|
108
118
|
"src/cli/theme.ts"() {
|
|
@@ -150,8 +160,10 @@ function showBanner() {
|
|
|
150
160
|
const width = getWidth();
|
|
151
161
|
const isSmall = width < 65;
|
|
152
162
|
if (isSmall) {
|
|
153
|
-
console.log(
|
|
154
|
-
|
|
163
|
+
console.log(
|
|
164
|
+
`
|
|
165
|
+
${ui.primary.bold("f-export")} ${ui.muted(`v${package_default.version}`)} ${chip("beta ui")}`
|
|
166
|
+
);
|
|
155
167
|
console.log(` ${ui.text.bold("Framer Export")} ${ui.muted("for Framer, Webflow, and Wix")}
|
|
156
168
|
`);
|
|
157
169
|
return;
|
|
@@ -176,10 +188,18 @@ var init_banner = __esm({
|
|
|
176
188
|
init_package();
|
|
177
189
|
init_theme();
|
|
178
190
|
ASCII_ART = [
|
|
179
|
-
"
|
|
180
|
-
"\u2588\
|
|
181
|
-
"\u2588\
|
|
182
|
-
"\
|
|
191
|
+
"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
192
|
+
"\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557",
|
|
193
|
+
"\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
|
|
194
|
+
"\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557",
|
|
195
|
+
"\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
196
|
+
"\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D",
|
|
197
|
+
"\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",
|
|
198
|
+
"\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",
|
|
199
|
+
"\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 ",
|
|
200
|
+
"\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 ",
|
|
201
|
+
"\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 ",
|
|
202
|
+
"\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D "
|
|
183
203
|
];
|
|
184
204
|
}
|
|
185
205
|
});
|
|
@@ -351,7 +371,9 @@ var init_logger = __esm({
|
|
|
351
371
|
log = (m) => {
|
|
352
372
|
_li++;
|
|
353
373
|
const c = LOG_PALETTE[_li % LOG_PALETTE.length];
|
|
354
|
-
output(
|
|
374
|
+
output(
|
|
375
|
+
`${chalk2.hex(THEME.muted)(`[${T()}]`)} ${chalk2.hex(THEME.primary)("[log]")} ${c(trunc(m, 120))}`
|
|
376
|
+
);
|
|
355
377
|
};
|
|
356
378
|
INFO_PALETTE = [
|
|
357
379
|
(s) => chalk2.hex(THEME.info)(s),
|
|
@@ -362,7 +384,9 @@ var init_logger = __esm({
|
|
|
362
384
|
info = (m) => {
|
|
363
385
|
_ii++;
|
|
364
386
|
const c = INFO_PALETTE[_ii % INFO_PALETTE.length];
|
|
365
|
-
output(
|
|
387
|
+
output(
|
|
388
|
+
`${chalk2.hex(THEME.muted)(`[${T()}]`)} ${chalk2.hex(THEME.info).bold("[info]")} ${c(trunc(m, 120))}`
|
|
389
|
+
);
|
|
366
390
|
};
|
|
367
391
|
warn = (m) => {
|
|
368
392
|
const colors = [
|
|
@@ -380,7 +404,9 @@ var init_logger = __esm({
|
|
|
380
404
|
(s) => chalk2.hex(THEME.info)(s)
|
|
381
405
|
];
|
|
382
406
|
const c = colors[Math.floor(Math.random() * colors.length)];
|
|
383
|
-
output(
|
|
407
|
+
output(
|
|
408
|
+
`${chalk2.hex(THEME.muted)(`[${T()}]`)} ${chalk2.hex(THEME.success)("[ok]")} ${c(trunc(m, 120))}`
|
|
409
|
+
);
|
|
384
410
|
};
|
|
385
411
|
}
|
|
386
412
|
});
|
|
@@ -987,11 +1013,64 @@ const server = http.createServer((req, res) => {
|
|
|
987
1013
|
serveFile(filePath);
|
|
988
1014
|
});
|
|
989
1015
|
|
|
1016
|
+
const ANSI = {
|
|
1017
|
+
reset: '\\x1b[0m',
|
|
1018
|
+
primary: '\\x1b[38;2;250;178;131m',
|
|
1019
|
+
soft: '\\x1b[38;2;255;192;159m',
|
|
1020
|
+
text: '\\x1b[38;2;238;238;238m',
|
|
1021
|
+
muted: '\\x1b[38;2;128;128;128m',
|
|
1022
|
+
border: '\\x1b[38;2;72;72;72m',
|
|
1023
|
+
success: '\\x1b[38;2;127;216;143m',
|
|
1024
|
+
info: '\\x1b[38;2;86;182;194m',
|
|
1025
|
+
};
|
|
1026
|
+
|
|
1027
|
+
function color(name, value) {
|
|
1028
|
+
return ANSI[name] + value + ANSI.reset;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
function frameLine(label, value) {
|
|
1032
|
+
const text = ' ' + label.padEnd(10) + value;
|
|
1033
|
+
const pad = Math.max(0, 56 - text.length);
|
|
1034
|
+
console.log(' ' + color('border', '\u2502 ') + color('muted', label.padEnd(10)) + color('text', value) + ' '.repeat(pad) + color('border', ' \u2502'));
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
function drawServerUi() {
|
|
1038
|
+
const logo = [
|
|
1039
|
+
'\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ',
|
|
1040
|
+
'\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557',
|
|
1041
|
+
'\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D',
|
|
1042
|
+
'\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',
|
|
1043
|
+
'\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',
|
|
1044
|
+
'\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 ',
|
|
1045
|
+
];
|
|
1046
|
+
|
|
1047
|
+
console.log('');
|
|
1048
|
+
for (const line of logo) console.log(' ' + color('primary', line));
|
|
1049
|
+
console.log('');
|
|
1050
|
+
console.log(' ' + color('border', '\u256D\u2500' + '\u2500'.repeat(56) + '\u2500\u256E'));
|
|
1051
|
+
console.log(' ' + color('border', '\u2502 ') + color('text', ' Framer Export local server') + ' '.repeat(28) + color('border', ' \u2502'));
|
|
1052
|
+
console.log(' ' + color('border', '\u251C\u2500' + '\u2500'.repeat(56) + '\u2500\u2524'));
|
|
1053
|
+
frameLine('URL', 'http://localhost:' + PORT);
|
|
1054
|
+
frameLine('Root', ROOT);
|
|
1055
|
+
frameLine('Mode', 'static mirror + SPA fallback');
|
|
1056
|
+
console.log(' ' + color('border', '\u2570\u2500' + '\u2500'.repeat(56) + '\u2500\u256F'));
|
|
1057
|
+
console.log('');
|
|
1058
|
+
console.log(' ' + color('success', 'ready') + color('muted', ' press Ctrl+C to stop') + '\\n');
|
|
1059
|
+
}
|
|
1060
|
+
|
|
990
1061
|
server.listen(PORT, () => {
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1062
|
+
const frames = ['\u280B', '\u2819', '\u2839', '\u2838', '\u283C', '\u2834', '\u2826', '\u2827', '\u2807', '\u280F'];
|
|
1063
|
+
let i = 0;
|
|
1064
|
+
const timer = setInterval(() => {
|
|
1065
|
+
process.stdout.write('\\r\\x1B[2K ' + color('primary', frames[i % frames.length]) + ' ' + color('muted', 'starting Framer Export server'));
|
|
1066
|
+
i++;
|
|
1067
|
+
}, 80);
|
|
1068
|
+
|
|
1069
|
+
setTimeout(() => {
|
|
1070
|
+
clearInterval(timer);
|
|
1071
|
+
process.stdout.write('\\r\\x1B[2K');
|
|
1072
|
+
drawServerUi();
|
|
1073
|
+
}, 720);
|
|
995
1074
|
});
|
|
996
1075
|
`;
|
|
997
1076
|
}
|
|
@@ -1065,15 +1144,21 @@ function processSEO(html, url) {
|
|
|
1065
1144
|
</head>`);
|
|
1066
1145
|
}
|
|
1067
1146
|
if (!html.includes('name="description"')) {
|
|
1068
|
-
html = html.replace(
|
|
1069
|
-
|
|
1147
|
+
html = html.replace(
|
|
1148
|
+
"</head>",
|
|
1149
|
+
` <meta name="description" content="Exported with Framer Export - Fast, SEO-optimized, and clean.">
|
|
1150
|
+
</head>`
|
|
1151
|
+
);
|
|
1070
1152
|
}
|
|
1071
1153
|
if (!html.includes('property="og:')) {
|
|
1072
|
-
html = html.replace(
|
|
1154
|
+
html = html.replace(
|
|
1155
|
+
"</head>",
|
|
1156
|
+
` <meta property="og:type" content="website">
|
|
1073
1157
|
<meta property="og:url" content="${canonical}">
|
|
1074
1158
|
<meta property="og:title" content="Exported Site">
|
|
1075
1159
|
<meta property="og:description" content="A fast, clean version of this site, exported for performance.">
|
|
1076
|
-
</head>`
|
|
1160
|
+
</head>`
|
|
1161
|
+
);
|
|
1077
1162
|
}
|
|
1078
1163
|
if (!html.includes('name="robots"')) {
|
|
1079
1164
|
html = html.replace("</head>", ` <meta name="robots" content="index, follow">
|
|
@@ -1236,7 +1321,7 @@ var init_output = __esm({
|
|
|
1236
1321
|
// src/cli/box.ts
|
|
1237
1322
|
import chalk3 from "chalk";
|
|
1238
1323
|
function maxWidth() {
|
|
1239
|
-
return Math.min(process.stdout.columns || 80,
|
|
1324
|
+
return Math.min(process.stdout.columns || 80, 76);
|
|
1240
1325
|
}
|
|
1241
1326
|
function padRight(text, w) {
|
|
1242
1327
|
const visible = stripAnsi(text).length;
|
|
@@ -1356,7 +1441,9 @@ async function printSummary(exporter) {
|
|
|
1356
1441
|
const inner = w - 6;
|
|
1357
1442
|
const cmdLen = cdCmd.length;
|
|
1358
1443
|
const pad = Math.max(0, inner - cmdLen);
|
|
1359
|
-
console.log(
|
|
1444
|
+
console.log(
|
|
1445
|
+
" " + ui.border("\u2502 ") + G(cdCmd) + " ".repeat(pad) + ui.muted(" copy") + ui.border(" \u2502")
|
|
1446
|
+
);
|
|
1360
1447
|
console.log(boxBot(w));
|
|
1361
1448
|
} else {
|
|
1362
1449
|
console.log(ui.text.bold(" To serve locally:"));
|
|
@@ -1385,6 +1472,11 @@ async function select(question, options, defaultIndex = 0) {
|
|
|
1385
1472
|
return arrowSelect(question, options, defaultIndex);
|
|
1386
1473
|
}
|
|
1387
1474
|
async function arrowSelect(question, options, defaultIndex) {
|
|
1475
|
+
const panelTopRow = await queryCursorRow();
|
|
1476
|
+
const width = Math.min(maxWidth(), 72);
|
|
1477
|
+
const inner = width - 4;
|
|
1478
|
+
const optionStartOffset = 3;
|
|
1479
|
+
const lineCount = options.length + 4;
|
|
1388
1480
|
return new Promise((resolve) => {
|
|
1389
1481
|
const firstEnabled = options.findIndex((option) => !option.disabled);
|
|
1390
1482
|
let selected = options[defaultIndex]?.disabled ? firstEnabled : defaultIndex;
|
|
@@ -1401,23 +1493,66 @@ async function arrowSelect(question, options, defaultIndex) {
|
|
|
1401
1493
|
};
|
|
1402
1494
|
const render = (initial = false) => {
|
|
1403
1495
|
if (!initial) {
|
|
1404
|
-
stdout.write(`\x1B[${
|
|
1496
|
+
stdout.write(`\x1B[${lineCount}A`);
|
|
1405
1497
|
stdout.write("\x1B[J");
|
|
1406
1498
|
}
|
|
1407
|
-
console.log(
|
|
1499
|
+
console.log(boxTop(width));
|
|
1500
|
+
console.log(
|
|
1501
|
+
boxLine(width, centerText(`${ui.primary("\u25CF")} ${ui.text.bold(question)}`, inner))
|
|
1502
|
+
);
|
|
1503
|
+
console.log(boxSep(width));
|
|
1408
1504
|
for (let i = 0; i < options.length; i++) {
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
console.log(` ${ui.primary(">")} ${ui.text.bold(options[i].label)}`);
|
|
1413
|
-
} else {
|
|
1414
|
-
console.log(` ${ui.muted(options[i].label)}`);
|
|
1415
|
-
}
|
|
1505
|
+
console.log(
|
|
1506
|
+
boxLine(width, centerText(renderOption(options[i], i === selected, inner), inner))
|
|
1507
|
+
);
|
|
1416
1508
|
}
|
|
1509
|
+
console.log(boxBot(width));
|
|
1510
|
+
};
|
|
1511
|
+
const choose = () => {
|
|
1512
|
+
cleanup();
|
|
1513
|
+
stdout.write(`\x1B[${lineCount}A`);
|
|
1514
|
+
stdout.write("\x1B[J");
|
|
1515
|
+
console.log(
|
|
1516
|
+
` ${ui.success("\u2713")} ${ui.text.bold(question)} ${ui.primary(stripAnsi(options[selected].label))}
|
|
1517
|
+
`
|
|
1518
|
+
);
|
|
1519
|
+
resolve(options[selected].value);
|
|
1520
|
+
};
|
|
1521
|
+
const onMouseData = (chunk) => {
|
|
1522
|
+
const mouse = parseMouseEvent(chunk);
|
|
1523
|
+
if (!mouse) return;
|
|
1524
|
+
if (mouse.kind === "wheel-up") {
|
|
1525
|
+
move(-1);
|
|
1526
|
+
render();
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
if (mouse.kind === "wheel-down") {
|
|
1530
|
+
move(1);
|
|
1531
|
+
render();
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
if (panelTopRow === null) return;
|
|
1535
|
+
const idx = mouse.y - panelTopRow - optionStartOffset;
|
|
1536
|
+
if (idx < 0 || idx >= options.length || options[idx].disabled) return;
|
|
1537
|
+
if (selected !== idx) {
|
|
1538
|
+
selected = idx;
|
|
1539
|
+
render();
|
|
1540
|
+
}
|
|
1541
|
+
if (mouse.kind === "click") {
|
|
1542
|
+
choose();
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
const cleanup = () => {
|
|
1546
|
+
disableMouse();
|
|
1547
|
+
stdin.setRawMode(false);
|
|
1548
|
+
stdin.removeListener("keypress", onKeypress);
|
|
1549
|
+
stdin.removeListener("data", onMouseData);
|
|
1550
|
+
stdin.pause();
|
|
1417
1551
|
};
|
|
1418
1552
|
render(true);
|
|
1419
1553
|
readline.emitKeypressEvents(stdin);
|
|
1420
1554
|
stdin.setRawMode(true);
|
|
1555
|
+
enableInteractiveInput();
|
|
1421
1556
|
const onKeypress = (_str, key) => {
|
|
1422
1557
|
if (!key) return;
|
|
1423
1558
|
if (key.name === "up" && selected > 0) {
|
|
@@ -1427,23 +1562,14 @@ async function arrowSelect(question, options, defaultIndex) {
|
|
|
1427
1562
|
move(1);
|
|
1428
1563
|
render();
|
|
1429
1564
|
} else if (key.name === "return") {
|
|
1430
|
-
|
|
1431
|
-
stdin.removeListener("keypress", onKeypress);
|
|
1432
|
-
stdin.pause();
|
|
1433
|
-
stdout.write(`\x1B[${options.length + 1}A`);
|
|
1434
|
-
stdout.write("\x1B[J");
|
|
1435
|
-
console.log(
|
|
1436
|
-
` ${ui.success("\u2713")} ${ui.text.bold(question)} ${ui.primary(stripAnsi(options[selected].label))}
|
|
1437
|
-
`
|
|
1438
|
-
);
|
|
1439
|
-
resolve(options[selected].value);
|
|
1565
|
+
choose();
|
|
1440
1566
|
} else if (key.ctrl && key.name === "c" || key.name === "escape") {
|
|
1441
|
-
|
|
1442
|
-
stdin.removeListener("keypress", onKeypress);
|
|
1567
|
+
cleanup();
|
|
1443
1568
|
process.exit(0);
|
|
1444
1569
|
}
|
|
1445
1570
|
};
|
|
1446
1571
|
stdin.resume();
|
|
1572
|
+
stdin.on("data", onMouseData);
|
|
1447
1573
|
stdin.on("keypress", onKeypress);
|
|
1448
1574
|
});
|
|
1449
1575
|
}
|
|
@@ -1496,9 +1622,66 @@ async function fallbackPrompt(question, options, defaultIndex) {
|
|
|
1496
1622
|
ask();
|
|
1497
1623
|
});
|
|
1498
1624
|
}
|
|
1625
|
+
function renderOption(option, selected, width) {
|
|
1626
|
+
const plain = truncatePlain(stripAnsi(option.label), Math.max(10, width - 12));
|
|
1627
|
+
if (option.disabled) {
|
|
1628
|
+
return `${ui.border("[")} ${ui.muted(plain)} ${ui.border("]")}`;
|
|
1629
|
+
}
|
|
1630
|
+
if (selected) {
|
|
1631
|
+
return `${ui.primary("\u203A")} ${ui.primary("[")} ${ui.text.bold(plain)} ${ui.primary("]")} ${ui.primary("\u2039")}`;
|
|
1632
|
+
}
|
|
1633
|
+
return `${ui.muted(" ")} ${ui.border("[")} ${ui.muted(plain)} ${ui.border("]")} ${ui.muted(" ")}`;
|
|
1634
|
+
}
|
|
1635
|
+
function enableInteractiveInput() {
|
|
1636
|
+
stdout.write("\x1B[?25l\x1B[?1000h\x1B[?1002h\x1B[?1003h\x1B[?1006h");
|
|
1637
|
+
}
|
|
1638
|
+
function disableMouse() {
|
|
1639
|
+
stdout.write("\x1B[?1003l\x1B[?1002l\x1B[?1000l\x1B[?1006l\x1B[?25h");
|
|
1640
|
+
}
|
|
1641
|
+
function parseMouseEvent(chunk) {
|
|
1642
|
+
const text = chunk.toString("utf-8");
|
|
1643
|
+
const match = text.match(/\x1B\[<(\d+);(\d+);(\d+)([mM])/);
|
|
1644
|
+
if (!match) return null;
|
|
1645
|
+
const code = Number(match[1]);
|
|
1646
|
+
const x = Number(match[2]);
|
|
1647
|
+
const y = Number(match[3]);
|
|
1648
|
+
const state = match[4];
|
|
1649
|
+
if (code === 64) return { kind: "wheel-up", x, y };
|
|
1650
|
+
if (code === 65) return { kind: "wheel-down", x, y };
|
|
1651
|
+
if (state === "m") return { kind: "click", x, y };
|
|
1652
|
+
if ((code & 32) === 32 || code === 35) return { kind: "hover", x, y };
|
|
1653
|
+
if ((code & 3) === 0) return { kind: "hover", x, y };
|
|
1654
|
+
return null;
|
|
1655
|
+
}
|
|
1656
|
+
function queryCursorRow() {
|
|
1657
|
+
if (!stdin.isTTY || !stdout.isTTY) return Promise.resolve(null);
|
|
1658
|
+
return new Promise((resolve) => {
|
|
1659
|
+
const wasRaw = stdin.isRaw;
|
|
1660
|
+
let done = false;
|
|
1661
|
+
const finish = (row) => {
|
|
1662
|
+
if (done) return;
|
|
1663
|
+
done = true;
|
|
1664
|
+
clearTimeout(timer);
|
|
1665
|
+
stdin.removeListener("data", onData);
|
|
1666
|
+
if (!wasRaw) stdin.setRawMode(false);
|
|
1667
|
+
resolve(row);
|
|
1668
|
+
};
|
|
1669
|
+
const onData = (chunk) => {
|
|
1670
|
+
const match = chunk.toString("utf-8").match(/\x1B\[(\d+);\d+R/);
|
|
1671
|
+
if (!match) return;
|
|
1672
|
+
finish(Number(match[1]));
|
|
1673
|
+
};
|
|
1674
|
+
const timer = setTimeout(() => finish(null), 80);
|
|
1675
|
+
stdin.setRawMode(true);
|
|
1676
|
+
stdin.resume();
|
|
1677
|
+
stdin.on("data", onData);
|
|
1678
|
+
stdout.write("\x1B[6n");
|
|
1679
|
+
});
|
|
1680
|
+
}
|
|
1499
1681
|
var init_select = __esm({
|
|
1500
1682
|
"src/cli/select.ts"() {
|
|
1501
1683
|
"use strict";
|
|
1684
|
+
init_box();
|
|
1502
1685
|
init_theme();
|
|
1503
1686
|
}
|
|
1504
1687
|
});
|
|
@@ -1508,17 +1691,28 @@ import fs4 from "fs/promises";
|
|
|
1508
1691
|
import path5 from "path";
|
|
1509
1692
|
import { stdin as stdin2, stdout as stdout2 } from "process";
|
|
1510
1693
|
import { spawn } from "child_process";
|
|
1511
|
-
import chalk4 from "chalk";
|
|
1512
1694
|
async function runAiPromptAssistant(exporter) {
|
|
1513
1695
|
if (!stdin2.isTTY || !stdout2.isTTY) return;
|
|
1696
|
+
printConvertPanel(exporter);
|
|
1697
|
+
const action = await select(
|
|
1698
|
+
"Framer Export AI Convert",
|
|
1699
|
+
[
|
|
1700
|
+
{ label: `${buttonLabel("Convert")} open AI prompt modal`, value: "convert" },
|
|
1701
|
+
{ label: `${buttonLabel("Skip")} finish export`, value: "skip" }
|
|
1702
|
+
],
|
|
1703
|
+
0
|
|
1704
|
+
);
|
|
1705
|
+
if (action === "skip") return;
|
|
1706
|
+
printAssistantModal("AI conversion prompt", [
|
|
1707
|
+
"Choose a target stack, AI tool, and conversion situation.",
|
|
1708
|
+
"Mouse clicks are supported in the terminal when available.",
|
|
1709
|
+
"A detailed prompt file will be generated inside the export folder."
|
|
1710
|
+
]);
|
|
1514
1711
|
const targetOptions = [
|
|
1515
1712
|
...TARGETS.map((target2) => ({ label: target2.label, value: target2.id })),
|
|
1516
|
-
{ label: "Customize with AI - BETA in development", value: "custom-ai", disabled: true }
|
|
1517
|
-
{ label: "Skip AI prompt", value: "skip" }
|
|
1713
|
+
{ label: "Customize with AI - BETA in development", value: "custom-ai", disabled: true }
|
|
1518
1714
|
];
|
|
1519
|
-
|
|
1520
|
-
const targetId = await select("AI Prompt Assistant BETA: choose target stack", targetOptions, 0);
|
|
1521
|
-
if (targetId === "skip") return;
|
|
1715
|
+
const targetId = await select("Choose target stack", targetOptions, 0);
|
|
1522
1716
|
const aiToolId = await select(
|
|
1523
1717
|
"Choose the AI coding tool",
|
|
1524
1718
|
AI_TOOLS.map((tool) => ({ label: tool.label, value: tool.id })),
|
|
@@ -1539,22 +1733,22 @@ async function runAiPromptAssistant(exporter) {
|
|
|
1539
1733
|
await fs4.mkdir(aiDir, { recursive: true });
|
|
1540
1734
|
await fs4.writeFile(promptPath, prompt, "utf-8");
|
|
1541
1735
|
printPromptResult(promptPath, target, aiTool, goal);
|
|
1542
|
-
const
|
|
1543
|
-
"
|
|
1736
|
+
const promptAction = await select(
|
|
1737
|
+
"Prompt actions",
|
|
1544
1738
|
[
|
|
1545
|
-
{ label: "Copy prompt"
|
|
1546
|
-
{ label: "
|
|
1739
|
+
{ label: `${buttonLabel("Copy prompt")} clipboard`, value: "copy" },
|
|
1740
|
+
{ label: `${buttonLabel("Done")} keep file only`, value: "done" }
|
|
1547
1741
|
],
|
|
1548
1742
|
0
|
|
1549
1743
|
);
|
|
1550
|
-
if (
|
|
1744
|
+
if (promptAction === "copy") {
|
|
1551
1745
|
try {
|
|
1552
1746
|
await copyToClipboard(prompt);
|
|
1553
|
-
console.log(` ${
|
|
1747
|
+
console.log(` ${ui.success("\u2713")} ${ui.text.bold("Prompt copied to clipboard")}
|
|
1554
1748
|
`);
|
|
1555
1749
|
} catch (error) {
|
|
1556
1750
|
console.log(
|
|
1557
|
-
` ${
|
|
1751
|
+
` ${ui.warning("!")} ${ui.warning("Clipboard copy unavailable:")} ${ui.muted(error.message)}
|
|
1558
1752
|
`
|
|
1559
1753
|
);
|
|
1560
1754
|
}
|
|
@@ -1596,6 +1790,43 @@ async function countEntries(dir) {
|
|
|
1596
1790
|
return 0;
|
|
1597
1791
|
}
|
|
1598
1792
|
}
|
|
1793
|
+
function buttonLabel(label) {
|
|
1794
|
+
return `${ui.border("[")} ${ui.text.bold(label)} ${ui.border("]")}`;
|
|
1795
|
+
}
|
|
1796
|
+
function centerText2(text, width) {
|
|
1797
|
+
const visible = stripAnsi(text).length;
|
|
1798
|
+
if (visible >= width) return text;
|
|
1799
|
+
const left = Math.floor((width - visible) / 2);
|
|
1800
|
+
return " ".repeat(left) + text + " ".repeat(width - visible - left);
|
|
1801
|
+
}
|
|
1802
|
+
function printConvertPanel(exporter) {
|
|
1803
|
+
const w = maxWidth();
|
|
1804
|
+
const inner = w - 4;
|
|
1805
|
+
const rows = [
|
|
1806
|
+
centerText2(`${ui.text.bold("AI Convert")} ${ui.muted("BETA")}`, inner),
|
|
1807
|
+
centerText2(ui.muted("Generate a conversion prompt after the export."), inner),
|
|
1808
|
+
centerText2(`${buttonLabel("Convert")} ${ui.muted("or")} ${buttonLabel("Skip")}`, inner),
|
|
1809
|
+
centerText2(ui.muted(path5.basename(exporter.outDir)), inner)
|
|
1810
|
+
];
|
|
1811
|
+
console.log("");
|
|
1812
|
+
console.log(boxTop(w));
|
|
1813
|
+
for (const row of rows) console.log(boxLine(w, row));
|
|
1814
|
+
console.log(boxBot(w));
|
|
1815
|
+
console.log("");
|
|
1816
|
+
}
|
|
1817
|
+
function printAssistantModal(title, lines) {
|
|
1818
|
+
const w = maxWidth();
|
|
1819
|
+
const inner = w - 4;
|
|
1820
|
+
console.log("");
|
|
1821
|
+
console.log(boxTop(w));
|
|
1822
|
+
console.log(boxLine(w, centerText2(`${ui.primary("\u25C6")} ${ui.text.bold(title)}`, inner)));
|
|
1823
|
+
console.log(boxSep(w));
|
|
1824
|
+
for (const line of lines) {
|
|
1825
|
+
console.log(boxLine(w, centerText2(ui.muted(line), inner)));
|
|
1826
|
+
}
|
|
1827
|
+
console.log(boxBot(w));
|
|
1828
|
+
console.log("");
|
|
1829
|
+
}
|
|
1599
1830
|
function buildConversionPrompt(target, aiTool, goal, facts) {
|
|
1600
1831
|
const rootEntries = facts.rootEntries.length ? facts.rootEntries.join(", ") : "No root entries detected";
|
|
1601
1832
|
const exportDir = quoteForPrompt(facts.outputDir);
|
|
@@ -1615,8 +1846,8 @@ function buildConversionPrompt(target, aiTool, goal, facts) {
|
|
|
1615
1846
|
(dir) => `Inspect ${dir}: ${facts.counts[dir]} item(s) detected in the export.`
|
|
1616
1847
|
);
|
|
1617
1848
|
const promptLines = [
|
|
1618
|
-
`You are ${aiTool.agentName} working inside a local export created by
|
|
1619
|
-
"This brief was generated by the
|
|
1849
|
+
`You are ${aiTool.agentName} working inside a local export created by Framer Export.`,
|
|
1850
|
+
"This brief was generated by the Framer Export AI Prompt Assistant BETA.",
|
|
1620
1851
|
"Treat this beta prompt as a strict conversion checklist, not as permission to skip inspection.",
|
|
1621
1852
|
"Your mission is to convert this exported static mirror into a clean production project.",
|
|
1622
1853
|
`Target stack: ${target.stack}.`,
|
|
@@ -1774,23 +2005,38 @@ function pipeToCommand(command, args, input) {
|
|
|
1774
2005
|
function printPromptResult(promptPath, target, aiTool, goal) {
|
|
1775
2006
|
const w = maxWidth();
|
|
1776
2007
|
const isSmall = w < 50;
|
|
2008
|
+
const inner = w - 4;
|
|
1777
2009
|
const relPath = path5.relative(process.cwd(), promptPath) || promptPath;
|
|
1778
2010
|
console.log("");
|
|
1779
2011
|
if (!isSmall) {
|
|
1780
2012
|
console.log(boxTop(w));
|
|
1781
|
-
console.log(
|
|
2013
|
+
console.log(
|
|
2014
|
+
boxLine(
|
|
2015
|
+
w,
|
|
2016
|
+
centerText2(
|
|
2017
|
+
`${ui.success("\u2713")} ${ui.text.bold("AI Prompt Ready")} ${ui.muted("BETA")}`,
|
|
2018
|
+
inner
|
|
2019
|
+
)
|
|
2020
|
+
)
|
|
2021
|
+
);
|
|
1782
2022
|
console.log(boxSep(w));
|
|
1783
|
-
console.log(
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
console.log(boxLine(w,
|
|
2023
|
+
console.log(
|
|
2024
|
+
boxLine(w, centerText2(`${ui.muted("Tool")} ${ui.primary(aiTool.displayName)}`, inner))
|
|
2025
|
+
);
|
|
2026
|
+
console.log(boxLine(w, centerText2(`${ui.muted("Stack")} ${ui.primary(target.label)}`, inner)));
|
|
2027
|
+
console.log(boxLine(w, centerText2(`${ui.muted("Mode")} ${ui.primary(goal.label)}`, inner)));
|
|
2028
|
+
console.log(boxLine(w, centerText2(`${ui.muted("File")} ${ui.primary(relPath)}`, inner)));
|
|
2029
|
+
console.log(boxSep(w));
|
|
2030
|
+
console.log(
|
|
2031
|
+
boxLine(w, centerText2(`${buttonLabel("Copy prompt")} ${buttonLabel("Done")}`, inner))
|
|
2032
|
+
);
|
|
1787
2033
|
console.log(boxBot(w));
|
|
1788
2034
|
} else {
|
|
1789
|
-
console.log(
|
|
1790
|
-
console.log(` Tool: ${
|
|
1791
|
-
console.log(` Stack: ${
|
|
1792
|
-
console.log(` Situation: ${
|
|
1793
|
-
console.log(` File: ${
|
|
2035
|
+
console.log(ui.text.bold(" AI Prompt Ready - BETA"));
|
|
2036
|
+
console.log(` Tool: ${ui.primary(aiTool.displayName)}`);
|
|
2037
|
+
console.log(` Stack: ${ui.primary(target.label)}`);
|
|
2038
|
+
console.log(` Situation: ${ui.primary(goal.label)}`);
|
|
2039
|
+
console.log(` File: ${ui.primary(relPath)}`);
|
|
1794
2040
|
}
|
|
1795
2041
|
console.log("");
|
|
1796
2042
|
}
|
|
@@ -1800,6 +2046,7 @@ var init_prompt_assistant = __esm({
|
|
|
1800
2046
|
"use strict";
|
|
1801
2047
|
init_select();
|
|
1802
2048
|
init_box();
|
|
2049
|
+
init_theme();
|
|
1803
2050
|
IMPORTANT_DIRS = [
|
|
1804
2051
|
"index.html",
|
|
1805
2052
|
"styles",
|
|
@@ -1920,7 +2167,7 @@ var init_prompt_assistant = __esm({
|
|
|
1920
2167
|
});
|
|
1921
2168
|
|
|
1922
2169
|
// src/cli/cooking.ts
|
|
1923
|
-
import
|
|
2170
|
+
import chalk4 from "chalk";
|
|
1924
2171
|
var SHINE_WIDTH, FRAME_INTERVAL, SPINNER_FRAMES, CookingSpinner;
|
|
1925
2172
|
var init_cooking = __esm({
|
|
1926
2173
|
"src/cli/cooking.ts"() {
|
|
@@ -1967,7 +2214,7 @@ var init_cooking = __esm({
|
|
|
1967
2214
|
draw() {
|
|
1968
2215
|
if (!this.active) return;
|
|
1969
2216
|
const spinner = SPINNER_FRAMES[this.frame % SPINNER_FRAMES.length];
|
|
1970
|
-
const shimmer = this.renderShimmer("
|
|
2217
|
+
const shimmer = this.renderShimmer("Exporting");
|
|
1971
2218
|
const frameStr = ui.primary(spinner);
|
|
1972
2219
|
const phaseStr = this.phase ? ` ${ui.muted(this.limitLen(this.phase, 52))}` : "";
|
|
1973
2220
|
process.stdout.write(`\r\x1B[2K ${frameStr} ${shimmer}${phaseStr}`);
|
|
@@ -1980,7 +2227,7 @@ var init_cooking = __esm({
|
|
|
1980
2227
|
if (dist < SHINE_WIDTH) {
|
|
1981
2228
|
const t = 1 - dist / SHINE_WIDTH;
|
|
1982
2229
|
const g = Math.floor(160 + t * 95);
|
|
1983
|
-
result +=
|
|
2230
|
+
result += chalk4.rgb(250, Math.min(255, g), Math.min(255, Math.floor(g * 0.75)))(text[i]);
|
|
1984
2231
|
} else {
|
|
1985
2232
|
result += ui.muted(text[i]);
|
|
1986
2233
|
}
|
|
@@ -2003,7 +2250,7 @@ __export(exporter_exports, {
|
|
|
2003
2250
|
});
|
|
2004
2251
|
import fs5 from "fs/promises";
|
|
2005
2252
|
import path6 from "path";
|
|
2006
|
-
import
|
|
2253
|
+
import chalk5 from "chalk";
|
|
2007
2254
|
function deriveOutputName(url, platformName) {
|
|
2008
2255
|
try {
|
|
2009
2256
|
const parsed = new URL(url);
|
|
@@ -2064,10 +2311,12 @@ var init_exporter = __esm({
|
|
|
2064
2311
|
}
|
|
2065
2312
|
}
|
|
2066
2313
|
async run(includeSubpages = false) {
|
|
2067
|
-
console.log(
|
|
2314
|
+
console.log(
|
|
2315
|
+
`
|
|
2068
2316
|
${ui.text.bold("Framer Export")} ${chip("mirror")} ${ui.muted("v4 pipeline")}
|
|
2069
|
-
`
|
|
2070
|
-
|
|
2317
|
+
`
|
|
2318
|
+
);
|
|
2319
|
+
info("Source : " + chalk5.underline(this.siteUrl));
|
|
2071
2320
|
info("Output : " + ui.primary(this.outDir));
|
|
2072
2321
|
info("Platform : " + ui.primary(this.platform.displayName));
|
|
2073
2322
|
if (includeSubpages) {
|
|
@@ -2099,14 +2348,12 @@ var init_exporter = __esm({
|
|
|
2099
2348
|
this.ssrHTML = buf.toString("utf-8");
|
|
2100
2349
|
success("SSR HTML fetched (" + (this.ssrHTML.length / 1024).toFixed(1) + " KB)");
|
|
2101
2350
|
} catch (e) {
|
|
2102
|
-
log(
|
|
2351
|
+
log(chalk5.red("Could not fetch SSR HTML: " + e.message));
|
|
2103
2352
|
}
|
|
2104
2353
|
const htmlDetected = detectPlatform(this.siteUrl, this.ssrHTML);
|
|
2105
2354
|
if (htmlDetected.name !== this.platform.name) {
|
|
2106
2355
|
this.platform = htmlDetected;
|
|
2107
|
-
log(
|
|
2108
|
-
"Platform refined: " + ui.primary(this.platform.displayName) + " (from HTML analysis)"
|
|
2109
|
-
);
|
|
2356
|
+
log("Platform refined: " + ui.primary(this.platform.displayName) + " (from HTML analysis)");
|
|
2110
2357
|
}
|
|
2111
2358
|
await launchAndCapture(this);
|
|
2112
2359
|
if (includeSubpages && this.page) {
|
|
@@ -2196,7 +2443,7 @@ import readline2 from "readline/promises";
|
|
|
2196
2443
|
import { stdin as stdin3, stdout as stdout3 } from "process";
|
|
2197
2444
|
import path7 from "path";
|
|
2198
2445
|
import { URL as URL4 } from "url";
|
|
2199
|
-
import
|
|
2446
|
+
import chalk6 from "chalk";
|
|
2200
2447
|
function drawHeader(title) {
|
|
2201
2448
|
const w = maxWidth();
|
|
2202
2449
|
if (w < 50) {
|
|
@@ -2212,11 +2459,13 @@ function drawHeader(title) {
|
|
|
2212
2459
|
async function runSetup(legacyMode = false) {
|
|
2213
2460
|
showBanner();
|
|
2214
2461
|
console.log(` ${ui.text.bold("Framer Export setup")} ${chip("interactive")}`);
|
|
2215
|
-
console.log(
|
|
2216
|
-
`)
|
|
2462
|
+
console.log(
|
|
2463
|
+
` ${ui.muted("Export Framer, Webflow, and Wix sites into a clean local mirror.")}
|
|
2464
|
+
`
|
|
2465
|
+
);
|
|
2217
2466
|
const rl = readline2.createInterface({ input: stdin3, output: stdout3 });
|
|
2218
2467
|
const ask = async (question, defaultVal) => {
|
|
2219
|
-
const suffix = defaultVal ?
|
|
2468
|
+
const suffix = defaultVal ? chalk6.gray(` (${defaultVal})`) : "";
|
|
2220
2469
|
const prompt = ` ${ui.primary("\u25CF")} ${ui.text.bold(question)}${suffix} ${ui.muted(">")} `;
|
|
2221
2470
|
const answer = await rl.question(prompt);
|
|
2222
2471
|
return answer.trim() || defaultVal || "";
|
|
@@ -2229,11 +2478,13 @@ async function runSetup(legacyMode = false) {
|
|
|
2229
2478
|
new URL4(input);
|
|
2230
2479
|
siteUrl = input;
|
|
2231
2480
|
} catch {
|
|
2232
|
-
console.log(
|
|
2233
|
-
`)
|
|
2481
|
+
console.log(
|
|
2482
|
+
` ${ui.error("\u2717")} ${ui.error("Invalid URL. Enter a valid URL (https://...)")}
|
|
2483
|
+
`
|
|
2484
|
+
);
|
|
2234
2485
|
}
|
|
2235
2486
|
}
|
|
2236
|
-
console.log(` ${ui.success("\u2713")} ${ui.success("URL:")} ${
|
|
2487
|
+
console.log(` ${ui.success("\u2713")} ${ui.success("URL:")} ${chalk6.underline(siteUrl)}
|
|
2237
2488
|
`);
|
|
2238
2489
|
drawHeader("Step 2 : Platform");
|
|
2239
2490
|
const detected = detectPlatform(siteUrl);
|
|
@@ -2247,16 +2498,26 @@ async function runSetup(legacyMode = false) {
|
|
|
2247
2498
|
} else {
|
|
2248
2499
|
rl.close();
|
|
2249
2500
|
const platforms = [
|
|
2250
|
-
{
|
|
2251
|
-
|
|
2252
|
-
|
|
2501
|
+
{
|
|
2502
|
+
label: `Framer${detected.name === "framer" ? chalk6.gray(" (detected)") : ""}`,
|
|
2503
|
+
value: "framer"
|
|
2504
|
+
},
|
|
2505
|
+
{
|
|
2506
|
+
label: `Webflow${detected.name === "webflow" ? chalk6.gray(" (detected)") : ""}`,
|
|
2507
|
+
value: "webflow"
|
|
2508
|
+
},
|
|
2509
|
+
{ label: `Wix${detected.name === "wix" ? chalk6.gray(" (detected)") : ""}`, value: "wix" }
|
|
2253
2510
|
];
|
|
2254
2511
|
const defaultIdx = ["framer", "webflow", "wix"].indexOf(detected.name);
|
|
2255
|
-
platformName = await select(
|
|
2512
|
+
platformName = await select(
|
|
2513
|
+
"Select platform",
|
|
2514
|
+
platforms,
|
|
2515
|
+
Math.max(0, defaultIdx)
|
|
2516
|
+
);
|
|
2256
2517
|
}
|
|
2257
2518
|
const rl2 = legacyMode ? rl : readline2.createInterface({ input: stdin3, output: stdout3 });
|
|
2258
2519
|
const ask2 = async (question, defaultVal) => {
|
|
2259
|
-
const suffix = defaultVal ?
|
|
2520
|
+
const suffix = defaultVal ? chalk6.gray(` (${defaultVal})`) : "";
|
|
2260
2521
|
const prompt = ` ${ui.primary("\u25CF")} ${ui.text.bold(question)}${suffix} ${ui.muted(">")} `;
|
|
2261
2522
|
const answer = await rl2.question(prompt);
|
|
2262
2523
|
return answer.trim() || defaultVal || "";
|
|
@@ -2273,12 +2534,16 @@ async function runSetup(legacyMode = false) {
|
|
|
2273
2534
|
if (legacyMode) {
|
|
2274
2535
|
const prettyAnswer = await ask2("Pretty-print JS files? (y/n)", "y");
|
|
2275
2536
|
prettyPrint = prettyAnswer.toLowerCase().startsWith("y");
|
|
2276
|
-
console.log(
|
|
2277
|
-
`)
|
|
2537
|
+
console.log(
|
|
2538
|
+
` ${ui.success("\u2713")} Pretty-print: ${prettyPrint ? ui.success("yes") : ui.error("no")}
|
|
2539
|
+
`
|
|
2540
|
+
);
|
|
2278
2541
|
const subpagesAnswer = await ask2("Export sub-pages? (y/n)", "n");
|
|
2279
2542
|
includeSubpages = subpagesAnswer.toLowerCase().startsWith("y");
|
|
2280
|
-
console.log(
|
|
2281
|
-
`)
|
|
2543
|
+
console.log(
|
|
2544
|
+
` ${ui.success("\u2713")} Sub-pages: ${includeSubpages ? ui.success("yes") : ui.error("no")}
|
|
2545
|
+
`
|
|
2546
|
+
);
|
|
2282
2547
|
const concurrencyAnswer = await ask2("Download concurrency", "12");
|
|
2283
2548
|
concurrency = parseInt(concurrencyAnswer, 10) || 12;
|
|
2284
2549
|
console.log(` ${ui.success("\u2713")} Concurrency: ${ui.primary(String(concurrency))}
|
|
@@ -2290,16 +2555,24 @@ async function runSetup(legacyMode = false) {
|
|
|
2290
2555
|
{ label: "No", value: "no" }
|
|
2291
2556
|
]);
|
|
2292
2557
|
prettyPrint = prettyVal === "yes";
|
|
2293
|
-
const subpagesVal = await select(
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2558
|
+
const subpagesVal = await select(
|
|
2559
|
+
"Export sub-pages?",
|
|
2560
|
+
[
|
|
2561
|
+
{ label: "No", value: "no" },
|
|
2562
|
+
{ label: "Yes, crawl and export", value: "yes" }
|
|
2563
|
+
],
|
|
2564
|
+
0
|
|
2565
|
+
);
|
|
2297
2566
|
includeSubpages = subpagesVal === "yes";
|
|
2298
|
-
const concurrencyVal = await select(
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2567
|
+
const concurrencyVal = await select(
|
|
2568
|
+
"Download concurrency",
|
|
2569
|
+
[
|
|
2570
|
+
{ label: "6 (slow connection)", value: "6" },
|
|
2571
|
+
{ label: "12 (default)", value: "12" },
|
|
2572
|
+
{ label: "20 (fast connection)", value: "20" }
|
|
2573
|
+
],
|
|
2574
|
+
1
|
|
2575
|
+
);
|
|
2303
2576
|
concurrency = parseInt(concurrencyVal, 10);
|
|
2304
2577
|
}
|
|
2305
2578
|
const w = maxWidth();
|
|
@@ -2375,8 +2648,12 @@ function showHelp() {
|
|
|
2375
2648
|
showBanner();
|
|
2376
2649
|
console.log(`${ui.text.bold(" USAGE")} ${chip("cli")}
|
|
2377
2650
|
`);
|
|
2378
|
-
console.log(
|
|
2379
|
-
|
|
2651
|
+
console.log(
|
|
2652
|
+
` ${ui.primary("framer-export")} ${ui.warning("<url>")} ${ui.muted("[output-dir]")}`
|
|
2653
|
+
);
|
|
2654
|
+
console.log(
|
|
2655
|
+
` ${ui.primary("fexport")} ${ui.warning("<url>")} ${ui.muted("[output-dir]")}`
|
|
2656
|
+
);
|
|
2380
2657
|
console.log("");
|
|
2381
2658
|
console.log(ui.text.bold(" OPTIONS\n"));
|
|
2382
2659
|
const opts = [
|
|
@@ -2401,13 +2678,25 @@ function showHelp() {
|
|
|
2401
2678
|
}
|
|
2402
2679
|
console.log("");
|
|
2403
2680
|
console.log(ui.text.bold(" EXAMPLES\n"));
|
|
2404
|
-
console.log(
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
console.log(
|
|
2408
|
-
|
|
2681
|
+
console.log(
|
|
2682
|
+
` ${ui.muted("$")} ${ui.primary("framer-export")} ${ui.warning("https://mysite.framer.app")}`
|
|
2683
|
+
);
|
|
2684
|
+
console.log(
|
|
2685
|
+
` ${ui.muted("$")} ${ui.primary("framer-export")} ${ui.warning("https://mysite.webflow.io")}`
|
|
2686
|
+
);
|
|
2687
|
+
console.log(
|
|
2688
|
+
` ${ui.muted("$")} ${ui.primary("framer-export")} ${ui.warning("https://user.wixsite.com/my-site")}`
|
|
2689
|
+
);
|
|
2690
|
+
console.log(
|
|
2691
|
+
` ${ui.muted("$")} ${ui.primary("framer-export")} ${ui.success("--platform webflow")} ${ui.warning("https://custom.com")}`
|
|
2692
|
+
);
|
|
2693
|
+
console.log(
|
|
2694
|
+
` ${ui.muted("$")} ${ui.primary("framer-export")} ${ui.success("--subpages")} ${ui.warning("https://mysite.com")}`
|
|
2695
|
+
);
|
|
2409
2696
|
console.log(` ${ui.muted("$")} ${ui.primary("framer-export")} ${ui.success("--setup")}`);
|
|
2410
|
-
console.log(
|
|
2697
|
+
console.log(
|
|
2698
|
+
` ${ui.muted("$")} ${ui.primary("framer-export")} ${ui.success("--setup --legacy-mode")}`
|
|
2699
|
+
);
|
|
2411
2700
|
console.log("");
|
|
2412
2701
|
}
|
|
2413
2702
|
|
|
@@ -2468,15 +2757,21 @@ async function main() {
|
|
|
2468
2757
|
process.exit(0);
|
|
2469
2758
|
}
|
|
2470
2759
|
if (args.includes("--about")) {
|
|
2471
|
-
const
|
|
2760
|
+
const chalk7 = (await import("chalk")).default;
|
|
2472
2761
|
showBanner();
|
|
2473
2762
|
console.log(` ${ui.text.bold("Framer Export")} ${ui.muted(`v${package_default.version}`)}`);
|
|
2474
2763
|
console.log(` ${ui.text(package_default.description)}
|
|
2475
2764
|
`);
|
|
2476
2765
|
console.log(` ${ui.text.bold("Author")} ${ui.primary("Dany (danbenba)")}`);
|
|
2477
|
-
console.log(
|
|
2478
|
-
|
|
2479
|
-
|
|
2766
|
+
console.log(
|
|
2767
|
+
` ${ui.text.bold("Portfolio")} ${chalk7.underline.hex("#FAB283")("https://github.com/danbenba")}`
|
|
2768
|
+
);
|
|
2769
|
+
console.log(
|
|
2770
|
+
` ${ui.text.bold("GitHub")} ${chalk7.underline.hex("#FAB283")(package_default.repository.url.replace("git+", "").replace(".git", ""))}`
|
|
2771
|
+
);
|
|
2772
|
+
console.log(
|
|
2773
|
+
` ${ui.text.bold("npm")} ${chalk7.underline.hex("#FAB283")(`https://www.npmjs.com/package/${package_default.name}`)}`
|
|
2774
|
+
);
|
|
2480
2775
|
console.log(` ${ui.text.bold("License")} ${ui.success(package_default.license)}`);
|
|
2481
2776
|
console.log(` ${ui.text.bold("Node")} ${ui.muted(`>=${package_default.engines.node}`)}`);
|
|
2482
2777
|
console.log("");
|
|
@@ -2485,7 +2780,9 @@ async function main() {
|
|
|
2485
2780
|
checkForUpdates(VERSION).then((latest) => {
|
|
2486
2781
|
if (!latest) return;
|
|
2487
2782
|
console.log("");
|
|
2488
|
-
console.log(
|
|
2783
|
+
console.log(
|
|
2784
|
+
` ${ui.warning("\u21B3")} Update available: ${ui.muted(VERSION)} -> ${ui.success(latest)}`
|
|
2785
|
+
);
|
|
2489
2786
|
console.log(` ${ui.primary(" Run:")} ${ui.primarySoft("npm i -g framer-export@latest")}`);
|
|
2490
2787
|
console.log("");
|
|
2491
2788
|
});
|
|
@@ -2523,12 +2820,16 @@ async function main() {
|
|
|
2523
2820
|
const defaultDir = deriveOutputName2(url, detected);
|
|
2524
2821
|
const out = args[1] || `./${defaultDir}`;
|
|
2525
2822
|
try {
|
|
2526
|
-
await new FramerExporter2(url, path8.resolve(out), platformOverride || void 0).run(
|
|
2823
|
+
await new FramerExporter2(url, path8.resolve(out), platformOverride || void 0).run(
|
|
2824
|
+
includeSubpages
|
|
2825
|
+
);
|
|
2527
2826
|
} catch (e) {
|
|
2528
|
-
const
|
|
2529
|
-
console.log(
|
|
2530
|
-
|
|
2531
|
-
|
|
2827
|
+
const chalk7 = (await import("chalk")).default;
|
|
2828
|
+
console.log(
|
|
2829
|
+
`
|
|
2830
|
+
${ui.error("\u2717")} ${ui.error.bold("FAILED:")} ${ui.text(e.message)}`
|
|
2831
|
+
);
|
|
2832
|
+
console.log(chalk7.gray(e.stack || ""));
|
|
2532
2833
|
process.exit(1);
|
|
2533
2834
|
}
|
|
2534
2835
|
}
|