framer-export 5.0.0-beta.2 → 5.0.0-beta.3
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/README.md +1 -1
- package/dist/cli/index.js +595 -233
- 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: "5.0.0-beta.
|
|
18
|
+
version: "5.0.0-beta.3",
|
|
19
19
|
description: "Export 25+ website platforms (Framer, Webflow, Wix, Shopify, Notion, WordPress, Squarespace, Ghost, and more) 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",
|
|
@@ -1881,6 +1881,171 @@ var init_cooking = __esm({
|
|
|
1881
1881
|
}
|
|
1882
1882
|
});
|
|
1883
1883
|
|
|
1884
|
+
// src/cli/input.ts
|
|
1885
|
+
import { stdin } from "process";
|
|
1886
|
+
function parseInput(buffer) {
|
|
1887
|
+
const events = [];
|
|
1888
|
+
let i = 0;
|
|
1889
|
+
while (i < buffer.length) {
|
|
1890
|
+
const ch = buffer[i];
|
|
1891
|
+
if (ch === "") {
|
|
1892
|
+
events.push({ type: "key", name: "ctrl-c" });
|
|
1893
|
+
i++;
|
|
1894
|
+
continue;
|
|
1895
|
+
}
|
|
1896
|
+
if (ch === "\r" || ch === "\n") {
|
|
1897
|
+
events.push({ type: "key", name: "return" });
|
|
1898
|
+
i++;
|
|
1899
|
+
continue;
|
|
1900
|
+
}
|
|
1901
|
+
if (ch === " ") {
|
|
1902
|
+
events.push({ type: "key", name: "tab" });
|
|
1903
|
+
i++;
|
|
1904
|
+
continue;
|
|
1905
|
+
}
|
|
1906
|
+
if (ch === "\x7F" || ch === "\b") {
|
|
1907
|
+
events.push({ type: "key", name: "backspace" });
|
|
1908
|
+
i++;
|
|
1909
|
+
continue;
|
|
1910
|
+
}
|
|
1911
|
+
if (ch === ESC) {
|
|
1912
|
+
const rest = buffer.slice(i);
|
|
1913
|
+
if (rest.length === 1) {
|
|
1914
|
+
return { events, rest };
|
|
1915
|
+
}
|
|
1916
|
+
const next = rest[1];
|
|
1917
|
+
if (next === "[" || next === "O") {
|
|
1918
|
+
const sgr = rest.match(/^\x1B\[<(\d+);(\d+);(\d+)([mM])/);
|
|
1919
|
+
if (sgr) {
|
|
1920
|
+
const code = Number(sgr[1]);
|
|
1921
|
+
const x = Number(sgr[2]);
|
|
1922
|
+
const y = Number(sgr[3]);
|
|
1923
|
+
const release = sgr[4] === "m";
|
|
1924
|
+
if (code === 64) events.push({ type: "mouse", kind: "wheel-up", x, y });
|
|
1925
|
+
else if (code === 65) events.push({ type: "mouse", kind: "wheel-down", x, y });
|
|
1926
|
+
else if ((code & 32) === 32) events.push({ type: "mouse", kind: "move", x, y });
|
|
1927
|
+
else if (release) events.push({ type: "mouse", kind: "click", x, y });
|
|
1928
|
+
else events.push({ type: "mouse", kind: "press", x, y });
|
|
1929
|
+
i += sgr[0].length;
|
|
1930
|
+
continue;
|
|
1931
|
+
}
|
|
1932
|
+
if (/^\x1B\[<[\d;]*$/.test(rest)) {
|
|
1933
|
+
return { events, rest };
|
|
1934
|
+
}
|
|
1935
|
+
const legacy = rest.match(/^\x1B\[M([\s\S])([\s\S])([\s\S])/);
|
|
1936
|
+
if (legacy) {
|
|
1937
|
+
const code = legacy[1].charCodeAt(0) - 32;
|
|
1938
|
+
const x = legacy[2].charCodeAt(0) - 32;
|
|
1939
|
+
const y = legacy[3].charCodeAt(0) - 32;
|
|
1940
|
+
if (code === 64) events.push({ type: "mouse", kind: "wheel-up", x, y });
|
|
1941
|
+
else if (code === 65) events.push({ type: "mouse", kind: "wheel-down", x, y });
|
|
1942
|
+
else if ((code & 32) === 32) events.push({ type: "mouse", kind: "move", x, y });
|
|
1943
|
+
else if ((code & 3) === 3) events.push({ type: "mouse", kind: "click", x, y });
|
|
1944
|
+
else events.push({ type: "mouse", kind: "press", x, y });
|
|
1945
|
+
i += legacy[0].length;
|
|
1946
|
+
continue;
|
|
1947
|
+
}
|
|
1948
|
+
if (/^\x1B\[M[\s\S]{0,2}$/.test(rest)) {
|
|
1949
|
+
return { events, rest };
|
|
1950
|
+
}
|
|
1951
|
+
const arrow = rest.match(/^\x1B[[O]([ABCD])/);
|
|
1952
|
+
if (arrow) {
|
|
1953
|
+
const names = { A: "up", B: "down", C: "right", D: "left" };
|
|
1954
|
+
events.push({ type: "key", name: names[arrow[1]] });
|
|
1955
|
+
i += arrow[0].length;
|
|
1956
|
+
continue;
|
|
1957
|
+
}
|
|
1958
|
+
if (rest.startsWith("\x1B[3~")) {
|
|
1959
|
+
events.push({ type: "key", name: "delete" });
|
|
1960
|
+
i += 4;
|
|
1961
|
+
continue;
|
|
1962
|
+
}
|
|
1963
|
+
const csi = rest.match(/^\x1B\[[0-?]*[ -/]*[@-~]/);
|
|
1964
|
+
if (csi) {
|
|
1965
|
+
i += csi[0].length;
|
|
1966
|
+
continue;
|
|
1967
|
+
}
|
|
1968
|
+
if (/^\x1B\[[0-?]*[ -/]*$/.test(rest)) {
|
|
1969
|
+
return { events, rest };
|
|
1970
|
+
}
|
|
1971
|
+
if (rest.length === 2) {
|
|
1972
|
+
return { events, rest };
|
|
1973
|
+
}
|
|
1974
|
+
i += 2;
|
|
1975
|
+
continue;
|
|
1976
|
+
}
|
|
1977
|
+
i += 2;
|
|
1978
|
+
continue;
|
|
1979
|
+
}
|
|
1980
|
+
if (ch >= " ") {
|
|
1981
|
+
const code = buffer.codePointAt(i);
|
|
1982
|
+
const char = String.fromCodePoint(code);
|
|
1983
|
+
events.push({ type: "char", char });
|
|
1984
|
+
i += char.length;
|
|
1985
|
+
continue;
|
|
1986
|
+
}
|
|
1987
|
+
i++;
|
|
1988
|
+
}
|
|
1989
|
+
return { events, rest: "" };
|
|
1990
|
+
}
|
|
1991
|
+
var ESC, ESC_TIMEOUT_MS, RawInput;
|
|
1992
|
+
var init_input = __esm({
|
|
1993
|
+
"src/cli/input.ts"() {
|
|
1994
|
+
"use strict";
|
|
1995
|
+
ESC = "\x1B";
|
|
1996
|
+
ESC_TIMEOUT_MS = 40;
|
|
1997
|
+
RawInput = class {
|
|
1998
|
+
constructor(handler) {
|
|
1999
|
+
this.handler = handler;
|
|
2000
|
+
}
|
|
2001
|
+
handler;
|
|
2002
|
+
buffer = "";
|
|
2003
|
+
escTimer = null;
|
|
2004
|
+
active = false;
|
|
2005
|
+
onData = (chunk) => {
|
|
2006
|
+
this.buffer += chunk.toString("utf-8");
|
|
2007
|
+
this.drain();
|
|
2008
|
+
};
|
|
2009
|
+
start() {
|
|
2010
|
+
if (this.active) return;
|
|
2011
|
+
this.active = true;
|
|
2012
|
+
stdin.setRawMode(true);
|
|
2013
|
+
stdin.resume();
|
|
2014
|
+
stdin.on("data", this.onData);
|
|
2015
|
+
}
|
|
2016
|
+
stop() {
|
|
2017
|
+
if (!this.active) return;
|
|
2018
|
+
this.active = false;
|
|
2019
|
+
if (this.escTimer) clearTimeout(this.escTimer);
|
|
2020
|
+
this.escTimer = null;
|
|
2021
|
+
stdin.removeListener("data", this.onData);
|
|
2022
|
+
stdin.setRawMode(false);
|
|
2023
|
+
stdin.pause();
|
|
2024
|
+
}
|
|
2025
|
+
drain() {
|
|
2026
|
+
if (this.escTimer) {
|
|
2027
|
+
clearTimeout(this.escTimer);
|
|
2028
|
+
this.escTimer = null;
|
|
2029
|
+
}
|
|
2030
|
+
const { events, rest } = parseInput(this.buffer);
|
|
2031
|
+
this.buffer = rest;
|
|
2032
|
+
for (const event of events) {
|
|
2033
|
+
if (!this.active) return;
|
|
2034
|
+
this.handler(event);
|
|
2035
|
+
}
|
|
2036
|
+
if (rest === ESC) {
|
|
2037
|
+
this.escTimer = setTimeout(() => {
|
|
2038
|
+
if (this.buffer === ESC) {
|
|
2039
|
+
this.buffer = "";
|
|
2040
|
+
if (this.active) this.handler({ type: "key", name: "escape" });
|
|
2041
|
+
}
|
|
2042
|
+
}, ESC_TIMEOUT_MS);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
};
|
|
2046
|
+
}
|
|
2047
|
+
});
|
|
2048
|
+
|
|
1884
2049
|
// src/cli/box.ts
|
|
1885
2050
|
import chalk3 from "chalk";
|
|
1886
2051
|
function maxWidth() {
|
|
@@ -1983,77 +2148,203 @@ var init_box = __esm({
|
|
|
1983
2148
|
// src/cli/backdrop.ts
|
|
1984
2149
|
import chalk4 from "chalk";
|
|
1985
2150
|
import { stdout } from "process";
|
|
1986
|
-
function
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
return Math.
|
|
1991
|
-
}
|
|
1992
|
-
|
|
2151
|
+
function fract(v) {
|
|
2152
|
+
return v - Math.floor(v);
|
|
2153
|
+
}
|
|
2154
|
+
function hash11(n) {
|
|
2155
|
+
return fract(Math.sin(n) * 43758.5453);
|
|
2156
|
+
}
|
|
2157
|
+
function mix(a, b, t) {
|
|
2158
|
+
return a + (b - a) * t;
|
|
2159
|
+
}
|
|
2160
|
+
function vnoise(px, py, pz) {
|
|
2161
|
+
const ix = Math.floor(px);
|
|
2162
|
+
const iy = Math.floor(py);
|
|
2163
|
+
const iz = Math.floor(pz);
|
|
2164
|
+
const fx = px - ix;
|
|
2165
|
+
const fy = py - iy;
|
|
2166
|
+
const fz = pz - iz;
|
|
2167
|
+
const dot = (ox, oy, oz) => (ix + ox) * 1 + (iy + oy) * 57 + (iz + oz) * 113;
|
|
2168
|
+
const n000 = hash11(dot(0, 0, 0));
|
|
2169
|
+
const n100 = hash11(dot(1, 0, 0));
|
|
2170
|
+
const n010 = hash11(dot(0, 1, 0));
|
|
2171
|
+
const n110 = hash11(dot(1, 1, 0));
|
|
2172
|
+
const n001 = hash11(dot(0, 0, 1));
|
|
2173
|
+
const n101 = hash11(dot(1, 0, 1));
|
|
2174
|
+
const n011 = hash11(dot(0, 1, 1));
|
|
2175
|
+
const n111 = hash11(dot(1, 1, 1));
|
|
2176
|
+
const wx = fx * fx * fx * (fx * (fx * 6 - 15) + 10);
|
|
2177
|
+
const wy = fy * fy * fy * (fy * (fy * 6 - 15) + 10);
|
|
2178
|
+
const wz = fz * fz * fz * (fz * (fz * 6 - 15) + 10);
|
|
2179
|
+
const x00 = mix(n000, n100, wx);
|
|
2180
|
+
const x10 = mix(n010, n110, wx);
|
|
2181
|
+
const x01 = mix(n001, n101, wx);
|
|
2182
|
+
const x11 = mix(n011, n111, wx);
|
|
2183
|
+
const y0 = mix(x00, x10, wy);
|
|
2184
|
+
const y1 = mix(x01, x11, wy);
|
|
2185
|
+
return mix(y0, y1, wz) * 2 - 1;
|
|
2186
|
+
}
|
|
2187
|
+
function fbm2(ux, uy, t) {
|
|
2188
|
+
const px = ux * PATTERN_SCALE;
|
|
2189
|
+
const py = uy * PATTERN_SCALE;
|
|
2190
|
+
let amp = 1;
|
|
2191
|
+
let freq = 1;
|
|
2192
|
+
let sum = 1;
|
|
2193
|
+
for (let i = 0; i < FBM_OCTAVES; i++) {
|
|
2194
|
+
sum += amp * vnoise(px * freq, py * freq, t * freq);
|
|
2195
|
+
freq *= FBM_LACUNARITY;
|
|
2196
|
+
amp *= FBM_GAIN;
|
|
2197
|
+
}
|
|
2198
|
+
return sum * 0.5 + 0.5;
|
|
2199
|
+
}
|
|
2200
|
+
function bayer2exact(x, y) {
|
|
2201
|
+
const ax = Math.floor(x);
|
|
2202
|
+
const ay = Math.floor(y);
|
|
2203
|
+
return fract(ax / 2 + ay * ay * 0.75);
|
|
2204
|
+
}
|
|
2205
|
+
function bayer4(x, y) {
|
|
2206
|
+
return bayer2exact(0.5 * x, 0.5 * y) * 0.25 + bayer2exact(x, y);
|
|
2207
|
+
}
|
|
2208
|
+
function bayer8(x, y) {
|
|
2209
|
+
return bayer4(0.5 * x, 0.5 * y) * 0.25 + bayer2exact(x, y);
|
|
2210
|
+
}
|
|
2211
|
+
var FRAME_MS, FBM_OCTAVES, FBM_LACUNARITY, FBM_GAIN, PATTERN_SCALE, PATTERN_DENSITY, PIXEL_JITTER, SPEED, EDGE_FADE, RIPPLE_SPEED, RIPPLE_THICKNESS, RIPPLE_INTENSITY, MAX_CLICKS, DAMP_T, DAMP_R, CELL_PX, GLYPHS, COLORS, Backdrop;
|
|
1993
2212
|
var init_backdrop = __esm({
|
|
1994
2213
|
"src/cli/backdrop.ts"() {
|
|
1995
2214
|
"use strict";
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2215
|
+
FRAME_MS = 100;
|
|
2216
|
+
FBM_OCTAVES = 5;
|
|
2217
|
+
FBM_LACUNARITY = 1.25;
|
|
2218
|
+
FBM_GAIN = 1;
|
|
2219
|
+
PATTERN_SCALE = 3;
|
|
2220
|
+
PATTERN_DENSITY = 1.1;
|
|
2221
|
+
PIXEL_JITTER = 0.4;
|
|
2222
|
+
SPEED = 0.5;
|
|
2223
|
+
EDGE_FADE = 0.18;
|
|
2224
|
+
RIPPLE_SPEED = 0.4;
|
|
2225
|
+
RIPPLE_THICKNESS = 0.12;
|
|
2226
|
+
RIPPLE_INTENSITY = 1.4;
|
|
2227
|
+
MAX_CLICKS = 10;
|
|
2228
|
+
DAMP_T = 1;
|
|
2229
|
+
DAMP_R = 10;
|
|
2230
|
+
CELL_PX = 8;
|
|
2231
|
+
GLYPHS = ["\xB7", "\u2022", "\u25AA", "\u25CF"];
|
|
2232
|
+
COLORS = ["#54402f", "#6b4c37", "#82593d", "#8f6244"];
|
|
2000
2233
|
Backdrop = class {
|
|
2001
2234
|
timer = null;
|
|
2002
|
-
|
|
2003
|
-
prev = [];
|
|
2235
|
+
disabled = false;
|
|
2004
2236
|
exclude = null;
|
|
2237
|
+
prev = /* @__PURE__ */ new Map();
|
|
2238
|
+
clicks = [];
|
|
2239
|
+
clickIx = 0;
|
|
2240
|
+
timeOffset = Math.random() * 1e3;
|
|
2241
|
+
startedAt = Date.now();
|
|
2005
2242
|
constructor() {
|
|
2006
|
-
if (process.env.FRAMER_EXPORT_NO_BG) this.
|
|
2243
|
+
if (process.env.FRAMER_EXPORT_NO_BG) this.disabled = true;
|
|
2007
2244
|
}
|
|
2008
2245
|
setExclude(rect) {
|
|
2009
2246
|
this.exclude = rect;
|
|
2010
2247
|
}
|
|
2248
|
+
addClick(col, row2) {
|
|
2249
|
+
if (this.clicks.length < MAX_CLICKS) {
|
|
2250
|
+
this.clicks.push({ x: col, y: row2 * 2, time: this.now() });
|
|
2251
|
+
} else {
|
|
2252
|
+
this.clicks[this.clickIx] = { x: col, y: row2 * 2, time: this.now() };
|
|
2253
|
+
}
|
|
2254
|
+
this.clickIx = (this.clickIx + 1) % MAX_CLICKS;
|
|
2255
|
+
}
|
|
2011
2256
|
start() {
|
|
2012
|
-
if (this.
|
|
2257
|
+
if (this.disabled || !stdout.isTTY || this.timer) return;
|
|
2258
|
+
this.startedAt = Date.now();
|
|
2013
2259
|
this.paint();
|
|
2014
2260
|
this.timer = setInterval(() => this.paint(), FRAME_MS);
|
|
2015
2261
|
}
|
|
2016
2262
|
stop() {
|
|
2017
2263
|
if (this.timer) clearInterval(this.timer);
|
|
2018
2264
|
this.timer = null;
|
|
2019
|
-
this.
|
|
2020
|
-
|
|
2265
|
+
this.erase();
|
|
2266
|
+
}
|
|
2267
|
+
now() {
|
|
2268
|
+
return this.timeOffset + (Date.now() - this.startedAt) / 1e3 * SPEED;
|
|
2021
2269
|
}
|
|
2022
2270
|
inExclude(x, y) {
|
|
2023
2271
|
const r = this.exclude;
|
|
2024
2272
|
if (!r) return false;
|
|
2025
2273
|
return y >= r.top && y < r.top + r.height && x >= r.left && x < r.left + r.width;
|
|
2026
2274
|
}
|
|
2027
|
-
|
|
2028
|
-
if (this.prev.
|
|
2275
|
+
erase() {
|
|
2276
|
+
if (this.prev.size === 0) return;
|
|
2277
|
+
const columns = stdout.columns || 80;
|
|
2029
2278
|
let out = "";
|
|
2030
|
-
for (const
|
|
2279
|
+
for (const key of this.prev.keys()) {
|
|
2280
|
+
const x = key % columns + 1;
|
|
2281
|
+
const y = Math.floor(key / columns) + 1;
|
|
2031
2282
|
out += `\x1B[${y};${x}H `;
|
|
2032
2283
|
}
|
|
2033
2284
|
stdout.write(out);
|
|
2285
|
+
this.prev.clear();
|
|
2034
2286
|
}
|
|
2035
2287
|
paint() {
|
|
2036
2288
|
const rows = stdout.rows || 24;
|
|
2037
2289
|
const columns = stdout.columns || 80;
|
|
2038
|
-
|
|
2290
|
+
const resX = columns;
|
|
2291
|
+
const resY = rows * 2;
|
|
2292
|
+
const aspect = resX / resY;
|
|
2293
|
+
const t = this.now();
|
|
2294
|
+
const next = /* @__PURE__ */ new Map();
|
|
2039
2295
|
let out = "";
|
|
2040
|
-
for (
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
const
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2296
|
+
for (let row2 = 1; row2 <= rows; row2++) {
|
|
2297
|
+
const fy = row2 * 2 - resY * 0.5;
|
|
2298
|
+
for (let col = 1; col <= columns; col++) {
|
|
2299
|
+
if (this.inExclude(col, row2)) continue;
|
|
2300
|
+
const fx = col - resX * 0.5;
|
|
2301
|
+
const cellX = Math.floor(fx / CELL_PX) * CELL_PX;
|
|
2302
|
+
const cellY = Math.floor(fy / CELL_PX) * CELL_PX;
|
|
2303
|
+
const ux = cellX / resX * aspect;
|
|
2304
|
+
const uy = cellY / resY;
|
|
2305
|
+
let base = fbm2(ux, uy, t * 0.05);
|
|
2306
|
+
base = base * 0.5 - 0.65;
|
|
2307
|
+
let feed = base + (PATTERN_DENSITY - 0.5) * 0.3;
|
|
2308
|
+
for (const click of this.clicks) {
|
|
2309
|
+
const cux = (click.x - resX * 0.5 - CELL_PX * 0.5) / resX * aspect;
|
|
2310
|
+
const cuy = (click.y - resY * 0.5 - CELL_PX * 0.5) / resY;
|
|
2311
|
+
const dt = Math.max(t - click.time, 0);
|
|
2312
|
+
const r = Math.hypot(ux - cux, uy - cuy);
|
|
2313
|
+
const waveR = RIPPLE_SPEED * dt;
|
|
2314
|
+
const ring = Math.exp(-(((r - waveR) / RIPPLE_THICKNESS) ** 2));
|
|
2315
|
+
const atten = Math.exp(-DAMP_T * dt) * Math.exp(-DAMP_R * r);
|
|
2316
|
+
feed = Math.max(feed, ring * atten * RIPPLE_INTENSITY);
|
|
2317
|
+
}
|
|
2318
|
+
const bayer = bayer8(fx, fy) - 0.5;
|
|
2319
|
+
const bw = feed + bayer > 0.5 ? 1 : 0;
|
|
2320
|
+
if (!bw) continue;
|
|
2321
|
+
const h = fract(Math.sin(Math.floor(fx) * 127.1 + Math.floor(fy) * 311.7) * 43758.5453);
|
|
2322
|
+
const jitterScale = 1 + (h - 0.5) * PIXEL_JITTER;
|
|
2323
|
+
let coverage = bw * jitterScale;
|
|
2324
|
+
if (EDGE_FADE > 0) {
|
|
2325
|
+
const nx = col / columns;
|
|
2326
|
+
const ny = row2 / rows;
|
|
2327
|
+
const edge = Math.min(nx, ny, 1 - nx, 1 - ny);
|
|
2328
|
+
const fade = Math.min(1, Math.max(0, edge / EDGE_FADE));
|
|
2329
|
+
coverage *= fade * fade * (3 - 2 * fade);
|
|
2330
|
+
}
|
|
2331
|
+
if (coverage < 0.35) continue;
|
|
2332
|
+
const level = Math.min(3, Math.floor(h * 4));
|
|
2333
|
+
const key = (row2 - 1) * columns + (col - 1);
|
|
2334
|
+
next.set(key, level);
|
|
2335
|
+
if (this.prev.get(key) !== level) {
|
|
2336
|
+
out += `\x1B[${row2};${col}H${chalk4.hex(COLORS[level])(GLYPHS[level])}`;
|
|
2337
|
+
}
|
|
2338
|
+
this.prev.delete(key);
|
|
2053
2339
|
}
|
|
2054
2340
|
}
|
|
2341
|
+
for (const key of this.prev.keys()) {
|
|
2342
|
+
const x = key % columns + 1;
|
|
2343
|
+
const y = Math.floor(key / columns) + 1;
|
|
2344
|
+
if (!this.inExclude(x, y)) out += `\x1B[${y};${x}H `;
|
|
2345
|
+
}
|
|
2055
2346
|
this.prev = next;
|
|
2056
|
-
stdout.write(out);
|
|
2347
|
+
if (out) stdout.write(out);
|
|
2057
2348
|
}
|
|
2058
2349
|
};
|
|
2059
2350
|
}
|
|
@@ -2062,7 +2353,7 @@ var init_backdrop = __esm({
|
|
|
2062
2353
|
// src/cli/select.ts
|
|
2063
2354
|
import readline from "readline";
|
|
2064
2355
|
import chalk5 from "chalk";
|
|
2065
|
-
import { stdin, stdout as stdout2 } from "process";
|
|
2356
|
+
import { stdin as stdin2, stdout as stdout2 } from "process";
|
|
2066
2357
|
function panelRow(width, content = "") {
|
|
2067
2358
|
const visible = stripAnsi(content).length;
|
|
2068
2359
|
const pad = Math.max(0, width - visible);
|
|
@@ -2081,7 +2372,7 @@ function titleRow(width, title) {
|
|
|
2081
2372
|
return chalk5.bgHex(THEME.panel)(left + " ".repeat(gap) + right);
|
|
2082
2373
|
}
|
|
2083
2374
|
async function select(question, options, defaultIndex = 0, config = {}) {
|
|
2084
|
-
const isTTY =
|
|
2375
|
+
const isTTY = stdin2.isTTY && stdout2.isTTY;
|
|
2085
2376
|
if (!isTTY) {
|
|
2086
2377
|
const flat = options.map((o) => o.heading ? { ...o, disabled: true } : o);
|
|
2087
2378
|
return fallbackPrompt(question, flat, defaultIndex, config);
|
|
@@ -2089,7 +2380,7 @@ async function select(question, options, defaultIndex = 0, config = {}) {
|
|
|
2089
2380
|
return arrowSelect(question, options, defaultIndex, config);
|
|
2090
2381
|
}
|
|
2091
2382
|
async function promptInput(question, defaultValue = "", config = {}) {
|
|
2092
|
-
if (!
|
|
2383
|
+
if (!stdin2.isTTY || !stdout2.isTTY) {
|
|
2093
2384
|
return fallbackInput(question, defaultValue);
|
|
2094
2385
|
}
|
|
2095
2386
|
return fullscreenInput(question, defaultValue, config);
|
|
@@ -2098,22 +2389,33 @@ async function arrowSelect(question, options, defaultIndex, config) {
|
|
|
2098
2389
|
const actions = config.actions ?? [];
|
|
2099
2390
|
const headerLines = config.headerLines ?? [];
|
|
2100
2391
|
const searchable = config.searchable === true;
|
|
2101
|
-
const width = Math.max(50, Math.min(maxWidth(), 64));
|
|
2102
|
-
const inner = width - 4;
|
|
2103
2392
|
const hasActions = actions.length > 0;
|
|
2104
2393
|
const headerCount = headerLines.length;
|
|
2105
|
-
const rows = process.stdout.rows || 24;
|
|
2106
|
-
const columns = process.stdout.columns || 80;
|
|
2107
2394
|
const searchRows = searchable ? 1 : 0;
|
|
2108
2395
|
const optionStartOffset = 3 + searchRows + headerCount + (headerCount > 0 ? 1 : 0);
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2396
|
+
let width = 0;
|
|
2397
|
+
let inner = 0;
|
|
2398
|
+
let visibleCount = 0;
|
|
2399
|
+
let actionLineOffset = 0;
|
|
2400
|
+
let lineCount = 0;
|
|
2401
|
+
let panelTopRow = 0;
|
|
2402
|
+
let panelLeftCol = 0;
|
|
2403
|
+
let footerRow = 0;
|
|
2404
|
+
const recomputeLayout = () => {
|
|
2405
|
+
width = Math.max(50, Math.min(maxWidth(), 64));
|
|
2406
|
+
inner = width - 4;
|
|
2407
|
+
const rows = process.stdout.rows || 24;
|
|
2408
|
+
const columns = process.stdout.columns || 80;
|
|
2409
|
+
const chromeLines = optionStartOffset + (hasActions ? 3 : 1) + 2;
|
|
2410
|
+
const maxVisible = Math.max(4, rows - chromeLines);
|
|
2411
|
+
visibleCount = Math.min(options.length, maxVisible);
|
|
2412
|
+
actionLineOffset = optionStartOffset + visibleCount + 1;
|
|
2413
|
+
lineCount = actionLineOffset + (hasActions ? 2 : 1);
|
|
2414
|
+
panelTopRow = Math.max(2, Math.floor((rows - lineCount) / 2) + 1);
|
|
2415
|
+
panelLeftCol = Math.max(1, Math.floor((columns - width) / 2) + 1);
|
|
2416
|
+
footerRow = Math.min(rows, panelTopRow + lineCount + 1);
|
|
2417
|
+
};
|
|
2418
|
+
recomputeLayout();
|
|
2117
2419
|
return new Promise((resolve) => {
|
|
2118
2420
|
let query = "";
|
|
2119
2421
|
const buildView = () => {
|
|
@@ -2153,6 +2455,8 @@ async function arrowSelect(question, options, defaultIndex, config) {
|
|
|
2153
2455
|
}
|
|
2154
2456
|
let selectedAction = null;
|
|
2155
2457
|
let scrollOffset = 0;
|
|
2458
|
+
let prevLines = [];
|
|
2459
|
+
let prevFooter = "";
|
|
2156
2460
|
const move = (direction) => {
|
|
2157
2461
|
let next = selected + direction;
|
|
2158
2462
|
while (next >= 0 && next < view.length) {
|
|
@@ -2174,14 +2478,18 @@ async function arrowSelect(question, options, defaultIndex, config) {
|
|
|
2174
2478
|
scrollOffset = Math.max(0, Math.min(scrollOffset, view.length - visibleCount));
|
|
2175
2479
|
};
|
|
2176
2480
|
const backdrop = new Backdrop();
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2481
|
+
const syncBackdropExclude = () => {
|
|
2482
|
+
backdrop.setExclude({
|
|
2483
|
+
top: panelTopRow - 1,
|
|
2484
|
+
left: panelLeftCol - 2,
|
|
2485
|
+
width: width + 4,
|
|
2486
|
+
height: lineCount + 3
|
|
2487
|
+
});
|
|
2488
|
+
};
|
|
2489
|
+
syncBackdropExclude();
|
|
2183
2490
|
const searchRow = () => {
|
|
2184
|
-
const
|
|
2491
|
+
const clipped = truncatePlain(query, Math.max(10, inner - 6));
|
|
2492
|
+
const shown = query ? `${chalk5.hex(THEME.text)(clipped)}${chalk5.hex(THEME.primary)("\u258C")}` : ui.muted("type to search");
|
|
2185
2493
|
const content = ` ${chalk5.hex(THEME.text)("\u258F")} ${shown}`;
|
|
2186
2494
|
const visible = stripAnsi(content).length;
|
|
2187
2495
|
return chalk5.bgHex(THEME.element)(content + " ".repeat(Math.max(0, width - visible)));
|
|
@@ -2222,17 +2530,23 @@ async function arrowSelect(question, options, defaultIndex, config) {
|
|
|
2222
2530
|
lines.push(panelRow(width, renderActions(actions, selectedAction)));
|
|
2223
2531
|
lines.push(panelRow(width));
|
|
2224
2532
|
}
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2533
|
+
const sameLength = prevLines.length === lines.length;
|
|
2534
|
+
lines.forEach((line, index) => {
|
|
2535
|
+
if (!sameLength || prevLines[index] !== line) {
|
|
2536
|
+
writeAt(panelTopRow + index, panelLeftCol, line);
|
|
2537
|
+
}
|
|
2538
|
+
});
|
|
2539
|
+
prevLines = lines;
|
|
2540
|
+
const footer = centerText(
|
|
2541
|
+
ui.muted(
|
|
2542
|
+
config.footer || (searchable ? "type to search \u2191\u2193 move enter select esc close" : "\u2191\u2193 move enter select mouse click esc close")
|
|
2543
|
+
),
|
|
2544
|
+
width
|
|
2235
2545
|
);
|
|
2546
|
+
if (footer !== prevFooter) {
|
|
2547
|
+
writeAt(footerRow, panelLeftCol, footer);
|
|
2548
|
+
prevFooter = footer;
|
|
2549
|
+
}
|
|
2236
2550
|
};
|
|
2237
2551
|
const refilter = () => {
|
|
2238
2552
|
view = buildView();
|
|
@@ -2252,97 +2566,128 @@ async function arrowSelect(question, options, defaultIndex, config) {
|
|
|
2252
2566
|
);
|
|
2253
2567
|
resolve(value);
|
|
2254
2568
|
};
|
|
2255
|
-
const
|
|
2256
|
-
const
|
|
2257
|
-
if (
|
|
2258
|
-
if (
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
}
|
|
2268
|
-
if (hasActions && mouse.y === panelTopRow + actionLineOffset) {
|
|
2269
|
-
const actionIdx = actionIndexAtX(actions, mouse.x, panelLeftCol, inner);
|
|
2569
|
+
const hitOption = (x, y) => {
|
|
2570
|
+
const relative = y - panelTopRow - optionStartOffset;
|
|
2571
|
+
if (relative < 0 || relative >= visibleCount) return null;
|
|
2572
|
+
if (x < panelLeftCol || x >= panelLeftCol + width) return null;
|
|
2573
|
+
const pos = scrollOffset + relative;
|
|
2574
|
+
if (pos >= view.length || !selectableAt(pos)) return null;
|
|
2575
|
+
return pos;
|
|
2576
|
+
};
|
|
2577
|
+
const onMouse = (kind, x, y) => {
|
|
2578
|
+
if (kind === "click") backdrop.addClick(x, y);
|
|
2579
|
+
if (hasActions && y === panelTopRow + actionLineOffset) {
|
|
2580
|
+
const actionIdx = actionIndexAtX(actions, x, panelLeftCol, inner);
|
|
2270
2581
|
if (actionIdx === null || actions[actionIdx].disabled) return;
|
|
2271
2582
|
if (selectedAction !== actionIdx) {
|
|
2272
2583
|
selectedAction = actionIdx;
|
|
2273
2584
|
render();
|
|
2274
2585
|
}
|
|
2275
|
-
if (
|
|
2586
|
+
if (kind === "click") choose(actions[actionIdx].value);
|
|
2276
2587
|
return;
|
|
2277
2588
|
}
|
|
2278
|
-
const
|
|
2279
|
-
if (
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2589
|
+
const pos = hitOption(x, y);
|
|
2590
|
+
if (pos === null) {
|
|
2591
|
+
if (kind === "move" && selectedAction !== null) {
|
|
2592
|
+
selectedAction = null;
|
|
2593
|
+
render();
|
|
2594
|
+
}
|
|
2595
|
+
return;
|
|
2596
|
+
}
|
|
2597
|
+
if (selected !== pos || selectedAction !== null) {
|
|
2283
2598
|
selected = pos;
|
|
2284
2599
|
selectedAction = null;
|
|
2285
2600
|
render();
|
|
2286
2601
|
}
|
|
2287
|
-
if (
|
|
2288
|
-
|
|
2602
|
+
if (kind === "click") choose();
|
|
2603
|
+
};
|
|
2604
|
+
const onEvent = (event) => {
|
|
2605
|
+
if (event.type === "mouse") {
|
|
2606
|
+
if (event.kind === "wheel-up") {
|
|
2607
|
+
move(-1);
|
|
2608
|
+
render();
|
|
2609
|
+
} else if (event.kind === "wheel-down") {
|
|
2610
|
+
move(1);
|
|
2611
|
+
render();
|
|
2612
|
+
} else {
|
|
2613
|
+
onMouse(event.kind, event.x, event.y);
|
|
2614
|
+
}
|
|
2615
|
+
return;
|
|
2616
|
+
}
|
|
2617
|
+
if (event.type === "key") {
|
|
2618
|
+
switch (event.name) {
|
|
2619
|
+
case "up":
|
|
2620
|
+
move(-1);
|
|
2621
|
+
selectedAction = null;
|
|
2622
|
+
render();
|
|
2623
|
+
return;
|
|
2624
|
+
case "down":
|
|
2625
|
+
move(1);
|
|
2626
|
+
selectedAction = null;
|
|
2627
|
+
render();
|
|
2628
|
+
return;
|
|
2629
|
+
case "tab":
|
|
2630
|
+
if (hasActions) {
|
|
2631
|
+
selectedAction = selectedAction === null ? 0 : null;
|
|
2632
|
+
render();
|
|
2633
|
+
}
|
|
2634
|
+
return;
|
|
2635
|
+
case "return":
|
|
2636
|
+
if (selectedAction !== null) choose(actions[selectedAction].value);
|
|
2637
|
+
else choose();
|
|
2638
|
+
return;
|
|
2639
|
+
case "ctrl-c":
|
|
2640
|
+
cleanup();
|
|
2641
|
+
process.exit(0);
|
|
2642
|
+
return;
|
|
2643
|
+
case "escape":
|
|
2644
|
+
if (searchable && query) {
|
|
2645
|
+
query = "";
|
|
2646
|
+
refilter();
|
|
2647
|
+
return;
|
|
2648
|
+
}
|
|
2649
|
+
cleanup();
|
|
2650
|
+
process.exit(0);
|
|
2651
|
+
return;
|
|
2652
|
+
case "backspace":
|
|
2653
|
+
if (searchable) {
|
|
2654
|
+
query = query.slice(0, -1);
|
|
2655
|
+
refilter();
|
|
2656
|
+
}
|
|
2657
|
+
return;
|
|
2658
|
+
default:
|
|
2659
|
+
return;
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
if (event.type === "char" && searchable && query.length < 40) {
|
|
2663
|
+
query += cleanInputValue(event.char);
|
|
2664
|
+
refilter();
|
|
2289
2665
|
}
|
|
2290
2666
|
};
|
|
2667
|
+
const input = new RawInput(onEvent);
|
|
2668
|
+
const onResize = () => {
|
|
2669
|
+
recomputeLayout();
|
|
2670
|
+
syncBackdropExclude();
|
|
2671
|
+
prevLines = [];
|
|
2672
|
+
prevFooter = "";
|
|
2673
|
+
stdout2.write("\x1B[2J");
|
|
2674
|
+
render();
|
|
2675
|
+
};
|
|
2291
2676
|
const cleanup = () => {
|
|
2292
2677
|
backdrop.stop();
|
|
2678
|
+
stdout2.removeListener("resize", onResize);
|
|
2679
|
+
input.stop();
|
|
2293
2680
|
leaveInteractiveScreen();
|
|
2294
|
-
stdin.setRawMode(false);
|
|
2295
|
-
stdin.removeListener("keypress", onKeypress);
|
|
2296
|
-
stdin.removeListener("data", onMouseData);
|
|
2297
|
-
stdin.pause();
|
|
2298
2681
|
};
|
|
2299
|
-
readline.emitKeypressEvents(stdin);
|
|
2300
|
-
stdin.setRawMode(true);
|
|
2301
2682
|
enterInteractiveScreen(true);
|
|
2302
2683
|
render();
|
|
2303
2684
|
backdrop.start();
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
if (key.name === "up") {
|
|
2307
|
-
move(-1);
|
|
2308
|
-
selectedAction = null;
|
|
2309
|
-
render();
|
|
2310
|
-
} else if (key.name === "down") {
|
|
2311
|
-
move(1);
|
|
2312
|
-
selectedAction = null;
|
|
2313
|
-
render();
|
|
2314
|
-
} else if (key.name === "tab" && hasActions) {
|
|
2315
|
-
selectedAction = selectedAction === null ? 0 : null;
|
|
2316
|
-
render();
|
|
2317
|
-
} else if (key.name === "return") {
|
|
2318
|
-
if (selectedAction !== null) choose(actions[selectedAction].value);
|
|
2319
|
-
else choose();
|
|
2320
|
-
} else if (key.ctrl && key.name === "c") {
|
|
2321
|
-
cleanup();
|
|
2322
|
-
process.exit(0);
|
|
2323
|
-
} else if (key.name === "escape") {
|
|
2324
|
-
if (searchable && query) {
|
|
2325
|
-
query = "";
|
|
2326
|
-
refilter();
|
|
2327
|
-
return;
|
|
2328
|
-
}
|
|
2329
|
-
cleanup();
|
|
2330
|
-
process.exit(0);
|
|
2331
|
-
} else if (searchable && key.name === "backspace") {
|
|
2332
|
-
query = query.slice(0, -1);
|
|
2333
|
-
refilter();
|
|
2334
|
-
} else if (searchable && str && !key.ctrl && !key.meta && str >= " " && !isTerminalSequence(str, key)) {
|
|
2335
|
-
query += cleanInputValue(str.replace(/[\r\n]/g, ""));
|
|
2336
|
-
refilter();
|
|
2337
|
-
}
|
|
2338
|
-
};
|
|
2339
|
-
stdin.resume();
|
|
2340
|
-
stdin.on("data", onMouseData);
|
|
2341
|
-
stdin.on("keypress", onKeypress);
|
|
2685
|
+
stdout2.on("resize", onResize);
|
|
2686
|
+
input.start();
|
|
2342
2687
|
});
|
|
2343
2688
|
}
|
|
2344
2689
|
async function fallbackPrompt(question, options, defaultIndex, config) {
|
|
2345
|
-
if (!
|
|
2690
|
+
if (!stdin2.isTTY) {
|
|
2346
2691
|
const firstEnabled = options.findIndex((option) => !option.disabled);
|
|
2347
2692
|
const enabledDefault = options[defaultIndex]?.disabled ? firstEnabled : defaultIndex;
|
|
2348
2693
|
const def = String(enabledDefault + 1);
|
|
@@ -2371,7 +2716,7 @@ async function fallbackPrompt(question, options, defaultIndex, config) {
|
|
|
2371
2716
|
}
|
|
2372
2717
|
}
|
|
2373
2718
|
return new Promise((resolve) => {
|
|
2374
|
-
const rl = readline.createInterface({ input:
|
|
2719
|
+
const rl = readline.createInterface({ input: stdin2, output: stdout2 });
|
|
2375
2720
|
const firstEnabled = options.findIndex((option) => !option.disabled);
|
|
2376
2721
|
const enabledDefault = options[defaultIndex]?.disabled ? firstEnabled : defaultIndex;
|
|
2377
2722
|
printFallbackOptions(question, options, enabledDefault, config);
|
|
@@ -2421,24 +2766,37 @@ async function fallbackPrompt(question, options, defaultIndex, config) {
|
|
|
2421
2766
|
}
|
|
2422
2767
|
function fullscreenInput(question, defaultValue, config) {
|
|
2423
2768
|
const headerLines = config.headerLines ?? [];
|
|
2424
|
-
const width = Math.max(50, Math.min(maxWidth(), 64));
|
|
2425
|
-
const inner = width - 4;
|
|
2426
2769
|
const headerCount = headerLines.length;
|
|
2427
2770
|
const lineCount = 3 + headerCount + (headerCount > 0 ? 1 : 0) + 2;
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2771
|
+
let width = 0;
|
|
2772
|
+
let inner = 0;
|
|
2773
|
+
let panelTopRow = 0;
|
|
2774
|
+
let panelLeftCol = 0;
|
|
2775
|
+
let footerRow = 0;
|
|
2776
|
+
const recomputeLayout = () => {
|
|
2777
|
+
width = Math.max(50, Math.min(maxWidth(), 64));
|
|
2778
|
+
inner = width - 4;
|
|
2779
|
+
const rows = process.stdout.rows || 24;
|
|
2780
|
+
const columns = process.stdout.columns || 80;
|
|
2781
|
+
panelTopRow = Math.max(2, Math.floor((rows - lineCount) / 2) + 1);
|
|
2782
|
+
panelLeftCol = Math.max(1, Math.floor((columns - width) / 2) + 1);
|
|
2783
|
+
footerRow = Math.min(rows, panelTopRow + lineCount + 1);
|
|
2784
|
+
};
|
|
2785
|
+
recomputeLayout();
|
|
2433
2786
|
return new Promise((resolve) => {
|
|
2434
2787
|
let value = defaultValue;
|
|
2788
|
+
let prevLines = [];
|
|
2789
|
+
let prevFooter = "";
|
|
2435
2790
|
const backdrop = new Backdrop();
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2791
|
+
const syncBackdropExclude = () => {
|
|
2792
|
+
backdrop.setExclude({
|
|
2793
|
+
top: panelTopRow - 1,
|
|
2794
|
+
left: panelLeftCol - 2,
|
|
2795
|
+
width: width + 4,
|
|
2796
|
+
height: lineCount + 3
|
|
2797
|
+
});
|
|
2798
|
+
};
|
|
2799
|
+
syncBackdropExclude();
|
|
2442
2800
|
const render = () => {
|
|
2443
2801
|
const shown = value || "";
|
|
2444
2802
|
const clipped = truncatePlain(shown, Math.max(12, inner - 6));
|
|
@@ -2457,67 +2815,86 @@ function fullscreenInput(question, defaultValue, config) {
|
|
|
2457
2815
|
if (headerCount > 0) lines.push(panelRow(width));
|
|
2458
2816
|
lines.push(inputRow);
|
|
2459
2817
|
lines.push(panelRow(width));
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2818
|
+
const sameLength = prevLines.length === lines.length;
|
|
2819
|
+
lines.forEach((line, index) => {
|
|
2820
|
+
if (!sameLength || prevLines[index] !== line) {
|
|
2821
|
+
writeAt(panelTopRow + index, panelLeftCol, line);
|
|
2822
|
+
}
|
|
2823
|
+
});
|
|
2824
|
+
prevLines = lines;
|
|
2825
|
+
const footer = centerText(
|
|
2826
|
+
ui.muted(config.footer || "type value enter confirm esc close"),
|
|
2827
|
+
width
|
|
2465
2828
|
);
|
|
2829
|
+
if (footer !== prevFooter) {
|
|
2830
|
+
writeAt(footerRow, panelLeftCol, footer);
|
|
2831
|
+
prevFooter = footer;
|
|
2832
|
+
}
|
|
2833
|
+
};
|
|
2834
|
+
const onResize = () => {
|
|
2835
|
+
recomputeLayout();
|
|
2836
|
+
syncBackdropExclude();
|
|
2837
|
+
prevLines = [];
|
|
2838
|
+
prevFooter = "";
|
|
2839
|
+
stdout2.write("\x1B[2J");
|
|
2840
|
+
render();
|
|
2466
2841
|
};
|
|
2467
2842
|
const cleanup = () => {
|
|
2468
2843
|
backdrop.stop();
|
|
2844
|
+
stdout2.removeListener("resize", onResize);
|
|
2845
|
+
input.stop();
|
|
2469
2846
|
leaveInteractiveScreen();
|
|
2470
|
-
stdin.setRawMode(false);
|
|
2471
|
-
stdin.removeListener("keypress", onKeypress);
|
|
2472
|
-
stdin.pause();
|
|
2473
2847
|
};
|
|
2474
2848
|
const submit = () => {
|
|
2475
2849
|
const output2 = cleanInputValue(value.trim() || defaultValue);
|
|
2476
2850
|
cleanup();
|
|
2477
2851
|
resolve(output2);
|
|
2478
2852
|
};
|
|
2479
|
-
const
|
|
2480
|
-
if (
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2853
|
+
const onEvent = (event) => {
|
|
2854
|
+
if (event.type === "key") {
|
|
2855
|
+
switch (event.name) {
|
|
2856
|
+
case "ctrl-c":
|
|
2857
|
+
case "escape":
|
|
2858
|
+
cleanup();
|
|
2859
|
+
process.exit(0);
|
|
2860
|
+
return;
|
|
2861
|
+
case "return":
|
|
2862
|
+
submit();
|
|
2863
|
+
return;
|
|
2864
|
+
case "backspace":
|
|
2865
|
+
value = value.slice(0, -1);
|
|
2866
|
+
render();
|
|
2867
|
+
return;
|
|
2868
|
+
case "delete":
|
|
2869
|
+
value = "";
|
|
2870
|
+
render();
|
|
2871
|
+
return;
|
|
2872
|
+
default:
|
|
2873
|
+
return;
|
|
2874
|
+
}
|
|
2497
2875
|
}
|
|
2498
|
-
if (
|
|
2499
|
-
value += cleanInputValue(
|
|
2876
|
+
if (event.type === "char") {
|
|
2877
|
+
value += cleanInputValue(event.char);
|
|
2500
2878
|
render();
|
|
2501
2879
|
}
|
|
2502
2880
|
};
|
|
2503
|
-
|
|
2504
|
-
stdin.setRawMode(true);
|
|
2881
|
+
const input = new RawInput(onEvent);
|
|
2505
2882
|
enterInteractiveScreen(false);
|
|
2506
2883
|
render();
|
|
2507
2884
|
backdrop.start();
|
|
2508
|
-
|
|
2509
|
-
|
|
2885
|
+
stdout2.on("resize", onResize);
|
|
2886
|
+
input.start();
|
|
2510
2887
|
});
|
|
2511
2888
|
}
|
|
2512
2889
|
async function fallbackInput(question, defaultValue) {
|
|
2513
|
-
if (!
|
|
2890
|
+
if (!stdin2.isTTY) {
|
|
2514
2891
|
const suffix = defaultValue ? ui.muted(` (${defaultValue})`) : "";
|
|
2515
2892
|
console.log(` ${ui.primary(">")} ${ui.text.bold(question)}${suffix}: `);
|
|
2516
2893
|
const answer = await readPipedLine();
|
|
2517
2894
|
return cleanInputValue(answer.trim() || defaultValue);
|
|
2518
2895
|
}
|
|
2519
2896
|
return new Promise((resolve) => {
|
|
2520
|
-
const rl = readline.createInterface({ input:
|
|
2897
|
+
const rl = readline.createInterface({ input: stdin2, output: stdout2 });
|
|
2521
2898
|
const suffix = defaultValue ? ui.muted(` (${defaultValue})`) : "";
|
|
2522
2899
|
rl.question(` ${ui.primary(">")} ${ui.text.bold(question)}${suffix}: `, (answer) => {
|
|
2523
2900
|
rl.close();
|
|
@@ -2550,14 +2927,14 @@ function readPipedLine() {
|
|
|
2550
2927
|
if (!pipedLinesPromise) {
|
|
2551
2928
|
pipedLinesPromise = new Promise((resolve) => {
|
|
2552
2929
|
let data = "";
|
|
2553
|
-
|
|
2554
|
-
|
|
2930
|
+
stdin2.setEncoding("utf8");
|
|
2931
|
+
stdin2.on("data", (chunk) => {
|
|
2555
2932
|
data += chunk;
|
|
2556
2933
|
});
|
|
2557
|
-
|
|
2934
|
+
stdin2.on("end", () => {
|
|
2558
2935
|
resolve(data.split(/\r?\n/));
|
|
2559
2936
|
});
|
|
2560
|
-
|
|
2937
|
+
stdin2.on("error", () => {
|
|
2561
2938
|
resolve([]);
|
|
2562
2939
|
});
|
|
2563
2940
|
});
|
|
@@ -2586,21 +2963,32 @@ function labelForValue(value, options, actions) {
|
|
|
2586
2963
|
options.find((option) => option.value === value)?.label || actions.find((action) => action.value === value)?.label || value
|
|
2587
2964
|
);
|
|
2588
2965
|
}
|
|
2966
|
+
function betaBadge() {
|
|
2967
|
+
return chalk5.bgHex(THEME.warning).hex(THEME.background).bold(" beta ");
|
|
2968
|
+
}
|
|
2969
|
+
function splitBetaLabel(plain) {
|
|
2970
|
+
if (plain.endsWith(BETA_SUFFIX)) {
|
|
2971
|
+
return { base: plain.slice(0, -BETA_SUFFIX.length).trimEnd(), beta: true };
|
|
2972
|
+
}
|
|
2973
|
+
return { base: plain, beta: false };
|
|
2974
|
+
}
|
|
2589
2975
|
function renderOption(option, isSelected, isDefault, width, inner) {
|
|
2590
2976
|
const plain = truncatePlain(stripAnsi(option.label), Math.max(10, inner - 2));
|
|
2591
2977
|
if (option.heading) {
|
|
2592
2978
|
return panelRow(width, ` ${ui.accent.bold(plain)}`);
|
|
2593
2979
|
}
|
|
2980
|
+
const { base, beta } = splitBetaLabel(plain);
|
|
2594
2981
|
if (isSelected && !option.disabled) {
|
|
2595
2982
|
return selectedRow(width, ` ${isDefault ? "\u25CF" : " "} ${plain}`);
|
|
2596
2983
|
}
|
|
2984
|
+
const badge = beta ? ` ${betaBadge()}` : "";
|
|
2597
2985
|
if (option.disabled) {
|
|
2598
|
-
return panelRow(width, ` ${ui.muted(
|
|
2986
|
+
return panelRow(width, ` ${ui.muted(base)}${badge}`);
|
|
2599
2987
|
}
|
|
2600
2988
|
if (isDefault) {
|
|
2601
|
-
return panelRow(width, ` ${ui.primary("\u25CF")} ${ui.primary(
|
|
2989
|
+
return panelRow(width, ` ${ui.primary("\u25CF")} ${ui.primary(base)}${badge}`);
|
|
2602
2990
|
}
|
|
2603
|
-
return panelRow(width, ` ${ui.text(
|
|
2991
|
+
return panelRow(width, ` ${ui.text(base)}${badge}`);
|
|
2604
2992
|
}
|
|
2605
2993
|
function enterInteractiveScreen(enableMouse) {
|
|
2606
2994
|
stdout2.write("\x1B[?1049h\x1B[2J\x1B[H\x1B[?25l");
|
|
@@ -2613,51 +3001,23 @@ function leaveInteractiveScreen() {
|
|
|
2613
3001
|
"\x1B[?1003l\x1B[?1002l\x1B[?1000l\x1B[?1006l\x1B[?25h\x1B[?1049l"
|
|
2614
3002
|
);
|
|
2615
3003
|
}
|
|
2616
|
-
function parseMouseEvent(chunk) {
|
|
2617
|
-
const text = chunk.toString("utf-8");
|
|
2618
|
-
const match = text.match(/\x1B\[<(\d+);(\d+);(\d+)([mM])/);
|
|
2619
|
-
if (!match) return parseLegacyMouseEvent(text);
|
|
2620
|
-
const code = Number(match[1]);
|
|
2621
|
-
const x = Number(match[2]);
|
|
2622
|
-
const y = Number(match[3]);
|
|
2623
|
-
const state2 = match[4];
|
|
2624
|
-
if (code === 64) return { kind: "wheel-up", x, y };
|
|
2625
|
-
if (code === 65) return { kind: "wheel-down", x, y };
|
|
2626
|
-
if (state2 === "m") return { kind: "click", x, y };
|
|
2627
|
-
if ((code & 32) === 32 || code === 35) return { kind: "hover", x, y };
|
|
2628
|
-
if ((code & 3) === 0) return { kind: "hover", x, y };
|
|
2629
|
-
return null;
|
|
2630
|
-
}
|
|
2631
|
-
function parseLegacyMouseEvent(text) {
|
|
2632
|
-
const match = text.match(/\x1B\[M([\s\S])([\s\S])([\s\S])/);
|
|
2633
|
-
if (!match) return null;
|
|
2634
|
-
const code = match[1].charCodeAt(0) - 32;
|
|
2635
|
-
const x = match[2].charCodeAt(0) - 32;
|
|
2636
|
-
const y = match[3].charCodeAt(0) - 32;
|
|
2637
|
-
if (code === 64) return { kind: "wheel-up", x, y };
|
|
2638
|
-
if (code === 65) return { kind: "wheel-down", x, y };
|
|
2639
|
-
if ((code & 3) === 3) return { kind: "click", x, y };
|
|
2640
|
-
if ((code & 32) === 32) return { kind: "hover", x, y };
|
|
2641
|
-
return { kind: "hover", x, y };
|
|
2642
|
-
}
|
|
2643
3004
|
function writeAt(row2, col, text) {
|
|
2644
3005
|
stdout2.write(`\x1B[${row2};${col}H${text}`);
|
|
2645
3006
|
}
|
|
2646
|
-
function isTerminalSequence(str, key) {
|
|
2647
|
-
return str.includes("\x1B") || !!key.sequence?.includes("\x1B") || /^(?:\d+;){2}\d+[mM]$/.test(str);
|
|
2648
|
-
}
|
|
2649
3007
|
function cleanInputValue(value) {
|
|
2650
3008
|
return value.replace(/\x1B\[<\d+;\d+;\d+[mM]/g, "").replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "").replace(/(?:\d+;){2}\d+[mM]/g, "").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
|
|
2651
3009
|
}
|
|
2652
|
-
var pipedLinesPromise, pipedLineIndex;
|
|
3010
|
+
var pipedLinesPromise, pipedLineIndex, BETA_SUFFIX;
|
|
2653
3011
|
var init_select = __esm({
|
|
2654
3012
|
"src/cli/select.ts"() {
|
|
2655
3013
|
"use strict";
|
|
3014
|
+
init_input();
|
|
2656
3015
|
init_box();
|
|
2657
3016
|
init_backdrop();
|
|
2658
3017
|
init_theme();
|
|
2659
3018
|
pipedLinesPromise = null;
|
|
2660
3019
|
pipedLineIndex = 0;
|
|
3020
|
+
BETA_SUFFIX = "[beta]";
|
|
2661
3021
|
}
|
|
2662
3022
|
});
|
|
2663
3023
|
|
|
@@ -2763,11 +3123,13 @@ var init_page = __esm({
|
|
|
2763
3123
|
.badge-beta {
|
|
2764
3124
|
font-size: 10px;
|
|
2765
3125
|
font-weight: 700;
|
|
2766
|
-
color:
|
|
2767
|
-
|
|
3126
|
+
color: #131010;
|
|
3127
|
+
background: var(--warning);
|
|
2768
3128
|
border-radius: 3px;
|
|
2769
|
-
padding:
|
|
2770
|
-
letter-spacing: 0.
|
|
3129
|
+
padding: 2px 7px;
|
|
3130
|
+
letter-spacing: 0.05em;
|
|
3131
|
+
text-transform: uppercase;
|
|
3132
|
+
box-shadow: 0 0 10px rgba(245, 167, 66, 0.35);
|
|
2771
3133
|
}
|
|
2772
3134
|
.search-wrap { max-width: 420px; margin-bottom: 1.6rem; }
|
|
2773
3135
|
.card .hint { font-size: 12px; color: var(--muted); margin-top: 8px; opacity: 0; transition: opacity .15s ease; }
|
|
@@ -3687,12 +4049,12 @@ var init_asset_map = __esm({
|
|
|
3687
4049
|
}
|
|
3688
4050
|
let filename;
|
|
3689
4051
|
const baseName = path.basename(pathname.split("?")[0]);
|
|
3690
|
-
const
|
|
4052
|
+
const hash = crypto.createHash("md5").update(urlStr).digest("hex").slice(0, 6);
|
|
3691
4053
|
if (baseName && baseName.length > 1 && baseName !== "/") {
|
|
3692
4054
|
const clean = baseName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
3693
|
-
filename = clean.includes(".") ? clean : `${clean}-${
|
|
4055
|
+
filename = clean.includes(".") ? clean : `${clean}-${hash}`;
|
|
3694
4056
|
} else {
|
|
3695
|
-
filename = `asset-${
|
|
4057
|
+
filename = `asset-${hash}${ext || ""}`;
|
|
3696
4058
|
}
|
|
3697
4059
|
if (ext === ".mjs" || ext === ".js") {
|
|
3698
4060
|
filename = baseName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
@@ -5135,10 +5497,10 @@ var init_summary = __esm({
|
|
|
5135
5497
|
// src/ai/prompt-assistant.ts
|
|
5136
5498
|
import fs4 from "fs/promises";
|
|
5137
5499
|
import path5 from "path";
|
|
5138
|
-
import { stdin as
|
|
5500
|
+
import { stdin as stdin3, stdout as stdout4 } from "process";
|
|
5139
5501
|
import { spawn } from "child_process";
|
|
5140
5502
|
async function runAiPromptAssistant(exporter) {
|
|
5141
|
-
if (!
|
|
5503
|
+
if (!stdin3.isTTY || !stdout4.isTTY) return;
|
|
5142
5504
|
const serveCommand = buildServeCommand(exporter);
|
|
5143
5505
|
const shouldConvert = await runExportCompletePrompt(exporter, serveCommand);
|
|
5144
5506
|
if (!shouldConvert) return;
|
|
@@ -6195,7 +6557,7 @@ __export(setup_exports, {
|
|
|
6195
6557
|
runSetup: () => runSetup
|
|
6196
6558
|
});
|
|
6197
6559
|
import readline2 from "readline/promises";
|
|
6198
|
-
import { stdin as
|
|
6560
|
+
import { stdin as stdin4, stdout as stdout5 } from "process";
|
|
6199
6561
|
import path8 from "path";
|
|
6200
6562
|
import { URL as URL5 } from "url";
|
|
6201
6563
|
import chalk9 from "chalk";
|
|
@@ -6332,7 +6694,7 @@ async function runSetup(legacyMode = false) {
|
|
|
6332
6694
|
});
|
|
6333
6695
|
}
|
|
6334
6696
|
async function runLegacySetup() {
|
|
6335
|
-
const rl = readline2.createInterface({ input:
|
|
6697
|
+
const rl = readline2.createInterface({ input: stdin4, output: stdout5 });
|
|
6336
6698
|
const ask = async (question, defaultVal) => {
|
|
6337
6699
|
const suffix = defaultVal ? chalk9.gray(` (${defaultVal})`) : "";
|
|
6338
6700
|
const prompt = ` ${ui.primary("\u25CF")} ${ui.text.bold(question)}${suffix} ${ui.muted(">")} `;
|