haltija 1.2.4 → 1.2.7
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/apps/desktop/main.js +16 -3
- package/apps/desktop/package.json +1 -1
- package/apps/desktop/renderer.js +1 -1
- package/apps/desktop/resources/component.js +83 -7
- package/apps/desktop/webview-preload.js +1 -1
- package/bin/cli-subcommand.mjs +109 -7
- package/bin/format-tree.mjs +5 -3
- package/bin/hints.json +1 -1
- package/bin/hj.mjs +16 -1
- package/bin/tosijs-dev.mjs +2 -0
- package/dist/component.js +83 -7
- package/dist/hj.js +108 -9
- package/dist/index.js +186 -28
- package/dist/server.js +186 -28
- package/package.json +1 -1
package/dist/component.js
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
// src/version.ts
|
|
49
|
-
var VERSION = "1.2.
|
|
49
|
+
var VERSION = "1.2.7";
|
|
50
50
|
|
|
51
51
|
// src/text-selector.ts
|
|
52
52
|
var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\(/;
|
|
@@ -1310,9 +1310,22 @@
|
|
|
1310
1310
|
}
|
|
1311
1311
|
return summary;
|
|
1312
1312
|
}
|
|
1313
|
+
function pruneNonInteractive(node) {
|
|
1314
|
+
const isInteractive = node.flags?.interactive || node.flags?.hasEvents;
|
|
1315
|
+
const children = node.children?.map((c) => pruneNonInteractive(c)).filter((c) => c !== null);
|
|
1316
|
+
const shadowChildren = node.shadowChildren?.map((c) => pruneNonInteractive(c)).filter((c) => c !== null);
|
|
1317
|
+
const hasInteractiveDescendant = children && children.length > 0 || shadowChildren && shadowChildren.length > 0;
|
|
1318
|
+
if (!isInteractive && !hasInteractiveDescendant)
|
|
1319
|
+
return null;
|
|
1320
|
+
return {
|
|
1321
|
+
...node,
|
|
1322
|
+
children: children?.length ? children : undefined,
|
|
1323
|
+
shadowChildren: shadowChildren?.length ? shadowChildren : undefined
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1313
1326
|
function buildDomTree(el, options, currentDepth = 0) {
|
|
1314
1327
|
const {
|
|
1315
|
-
depth =
|
|
1328
|
+
depth = -1,
|
|
1316
1329
|
includeText = true,
|
|
1317
1330
|
allAttributes = false,
|
|
1318
1331
|
includeStyles = false,
|
|
@@ -1703,6 +1716,7 @@
|
|
|
1703
1716
|
windowId;
|
|
1704
1717
|
isElectron = false;
|
|
1705
1718
|
browserId = uid();
|
|
1719
|
+
sessionToken = "";
|
|
1706
1720
|
killed = false;
|
|
1707
1721
|
isActive = true;
|
|
1708
1722
|
homeLeft = 0;
|
|
@@ -1775,7 +1789,7 @@
|
|
|
1775
1789
|
selectionBox = null;
|
|
1776
1790
|
highlightedElements = [];
|
|
1777
1791
|
static get observedAttributes() {
|
|
1778
|
-
return ["server", "hidden"];
|
|
1792
|
+
return ["server", "hidden", "session"];
|
|
1779
1793
|
}
|
|
1780
1794
|
static async runTests() {
|
|
1781
1795
|
const el = document.querySelector(TAG_NAME);
|
|
@@ -1871,10 +1885,16 @@
|
|
|
1871
1885
|
}
|
|
1872
1886
|
this.windowId = storedWindowId;
|
|
1873
1887
|
}
|
|
1888
|
+
if (config?.session) {
|
|
1889
|
+
this.sessionToken = config.session;
|
|
1890
|
+
} else {
|
|
1891
|
+
this.sessionToken = uid();
|
|
1892
|
+
}
|
|
1874
1893
|
}
|
|
1875
1894
|
connectedCallback() {
|
|
1876
1895
|
this.killed = false;
|
|
1877
1896
|
this.serverUrl = this.getAttribute("server") || this.serverUrl;
|
|
1897
|
+
this.sessionToken = this.getAttribute("session") || this.sessionToken;
|
|
1878
1898
|
this.render();
|
|
1879
1899
|
const rect = this.getBoundingClientRect();
|
|
1880
1900
|
this.homeLeft = window.innerWidth - rect.width - 16;
|
|
@@ -1902,6 +1922,11 @@
|
|
|
1902
1922
|
this.connect();
|
|
1903
1923
|
}
|
|
1904
1924
|
}
|
|
1925
|
+
if (name === "session") {
|
|
1926
|
+
this.sessionToken = value;
|
|
1927
|
+
this.disconnect();
|
|
1928
|
+
this.connect();
|
|
1929
|
+
}
|
|
1905
1930
|
}
|
|
1906
1931
|
render() {
|
|
1907
1932
|
if (this.shadowRoot.querySelector(".widget")) {
|
|
@@ -2087,6 +2112,25 @@
|
|
|
2087
2112
|
.btn.info-btn:hover {
|
|
2088
2113
|
background: #2563eb;
|
|
2089
2114
|
}
|
|
2115
|
+
.session-badge {
|
|
2116
|
+
display: flex;
|
|
2117
|
+
align-items: center;
|
|
2118
|
+
gap: 2px;
|
|
2119
|
+
font-size: 9px;
|
|
2120
|
+
color: #666;
|
|
2121
|
+
background: rgba(255,255,255,0.05);
|
|
2122
|
+
padding: 2px 4px;
|
|
2123
|
+
border-radius: 3px;
|
|
2124
|
+
cursor: pointer;
|
|
2125
|
+
user-select: none;
|
|
2126
|
+
}
|
|
2127
|
+
.session-badge:hover {
|
|
2128
|
+
background: rgba(255,255,255,0.1);
|
|
2129
|
+
color: #aaa;
|
|
2130
|
+
}
|
|
2131
|
+
.session-badge.copied {
|
|
2132
|
+
color: #22c55e;
|
|
2133
|
+
}
|
|
2090
2134
|
@keyframes pulse {
|
|
2091
2135
|
0%, 100% { opacity: 1; }
|
|
2092
2136
|
50% { opacity: 0.5; }
|
|
@@ -2449,6 +2493,8 @@
|
|
|
2449
2493
|
<span class="logo">\uD83E\uDDDD</span>
|
|
2450
2494
|
</div>
|
|
2451
2495
|
<div class="title">${PRODUCT_NAME}</div>
|
|
2496
|
+
<span class="session-badge" data-action="copy-session" title="Session: ${this.sessionToken}
|
|
2497
|
+
Click to copy session command">${this.sessionToken.slice(0, 8)}</span>
|
|
2452
2498
|
<div class="controls">
|
|
2453
2499
|
<button class="btn" data-action="select" title="Select elements (drag to select area)" aria-label="Select elements">\uD83D\uDC46</button>
|
|
2454
2500
|
<button class="btn" data-action="record" title="Record test (click to start/stop)" aria-label="Record test">REC</button>
|
|
@@ -2535,6 +2581,8 @@
|
|
|
2535
2581
|
this.startSelection();
|
|
2536
2582
|
if (action2 === "stats")
|
|
2537
2583
|
this.copyStatsToClipboard();
|
|
2584
|
+
if (action2 === "copy-session")
|
|
2585
|
+
this.copySessionToken(e.currentTarget);
|
|
2538
2586
|
if (action2 === "close-modal")
|
|
2539
2587
|
this.closeTestModal();
|
|
2540
2588
|
if (action2 === "copy-test")
|
|
@@ -3160,6 +3208,28 @@
|
|
|
3160
3208
|
});
|
|
3161
3209
|
}
|
|
3162
3210
|
}
|
|
3211
|
+
async copySessionToken(badge) {
|
|
3212
|
+
const cmd = `export HALTIJA_SESSION=${this.sessionToken}`;
|
|
3213
|
+
try {
|
|
3214
|
+
await navigator.clipboard.writeText(cmd);
|
|
3215
|
+
badge.textContent = "copied!";
|
|
3216
|
+
badge.classList.add("copied");
|
|
3217
|
+
setTimeout(() => {
|
|
3218
|
+
badge.textContent = this.sessionToken.slice(0, 8);
|
|
3219
|
+
badge.classList.remove("copied");
|
|
3220
|
+
}, 1500);
|
|
3221
|
+
} catch {
|
|
3222
|
+
try {
|
|
3223
|
+
await navigator.clipboard.writeText(this.sessionToken);
|
|
3224
|
+
badge.textContent = "copied!";
|
|
3225
|
+
badge.classList.add("copied");
|
|
3226
|
+
setTimeout(() => {
|
|
3227
|
+
badge.textContent = this.sessionToken.slice(0, 8);
|
|
3228
|
+
badge.classList.remove("copied");
|
|
3229
|
+
}, 1500);
|
|
3230
|
+
} catch {}
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3163
3233
|
async copyStatsToClipboard() {
|
|
3164
3234
|
const refStats = refRegistry.getStats();
|
|
3165
3235
|
stats.refsStale = refStats.stale;
|
|
@@ -4926,6 +4996,7 @@ ${elementSummary}${moreText}`;
|
|
|
4926
4996
|
this.send("system", "connected", {
|
|
4927
4997
|
windowId: this.windowId,
|
|
4928
4998
|
browserId: this.browserId,
|
|
4999
|
+
session: this.sessionToken,
|
|
4929
5000
|
version: VERSION2,
|
|
4930
5001
|
serverSessionId: SERVER_SESSION_ID,
|
|
4931
5002
|
url: location.href,
|
|
@@ -5351,7 +5422,7 @@ ${elementSummary}${moreText}`;
|
|
|
5351
5422
|
const haltija = window.haltija;
|
|
5352
5423
|
if (action2 === "open") {
|
|
5353
5424
|
if (haltija?.openTab) {
|
|
5354
|
-
haltija.openTab(payload2.url).then((opened) => {
|
|
5425
|
+
haltija.openTab(payload2.url, payload2.session).then((opened) => {
|
|
5355
5426
|
this.respond(msg2.id, true, { opened });
|
|
5356
5427
|
}).catch((err) => {
|
|
5357
5428
|
this.respond(msg2.id, false, null, err.message);
|
|
@@ -5471,7 +5542,10 @@ ${elementSummary}${moreText}`;
|
|
|
5471
5542
|
const summary = buildActionableSummary(el);
|
|
5472
5543
|
this.respond(msg2.id, true, summary);
|
|
5473
5544
|
} else {
|
|
5474
|
-
|
|
5545
|
+
let tree = buildDomTree(el, request);
|
|
5546
|
+
if (request.interactiveOnly && tree) {
|
|
5547
|
+
tree = pruneNonInteractive(tree);
|
|
5548
|
+
}
|
|
5475
5549
|
if (request.ancestors && tree) {
|
|
5476
5550
|
const ancestors = [];
|
|
5477
5551
|
let parent = el.parentElement;
|
|
@@ -7207,7 +7281,7 @@ ${elementSummary}${moreText}`;
|
|
|
7207
7281
|
}
|
|
7208
7282
|
registerDevChannel();
|
|
7209
7283
|
var WIDGET_ID = "haltija-widget";
|
|
7210
|
-
function inject(serverUrl2 = "wss://localhost:8700/ws/browser") {
|
|
7284
|
+
function inject(serverUrl2 = "wss://localhost:8700/ws/browser", options) {
|
|
7211
7285
|
const existing = document.getElementById(WIDGET_ID);
|
|
7212
7286
|
if (existing) {
|
|
7213
7287
|
console.log(`${LOG_PREFIX} Already injected`);
|
|
@@ -7222,6 +7296,8 @@ ${elementSummary}${moreText}`;
|
|
|
7222
7296
|
const el = DevChannel.elementCreator()();
|
|
7223
7297
|
el.id = WIDGET_ID;
|
|
7224
7298
|
el.setAttribute("server", serverUrl2);
|
|
7299
|
+
if (options?.session)
|
|
7300
|
+
el.setAttribute("session", options.session);
|
|
7225
7301
|
el.setAttribute("data-version", VERSION2);
|
|
7226
7302
|
document.body.appendChild(el);
|
|
7227
7303
|
console.log(`${LOG_PREFIX} Injected`);
|
|
@@ -7233,7 +7309,7 @@ ${elementSummary}${moreText}`;
|
|
|
7233
7309
|
const config = window.__haltija_config__;
|
|
7234
7310
|
if (config?.autoInject !== false) {
|
|
7235
7311
|
if (config) {
|
|
7236
|
-
inject(config.serverUrl || config.wsUrl);
|
|
7312
|
+
inject(config.serverUrl || config.wsUrl, { session: config.session });
|
|
7237
7313
|
return;
|
|
7238
7314
|
}
|
|
7239
7315
|
}
|
package/dist/hj.js
CHANGED
|
@@ -10,13 +10,15 @@ import { fileURLToPath } from "url";
|
|
|
10
10
|
|
|
11
11
|
// bin/format-tree.mjs
|
|
12
12
|
var MAX_TEXT_LEN = 80;
|
|
13
|
-
function formatTree(node, indent = 0) {
|
|
13
|
+
function formatTree(node, indent = 0, { depth } = {}) {
|
|
14
14
|
if (!node)
|
|
15
15
|
return "";
|
|
16
16
|
const lines = [];
|
|
17
17
|
formatNode(node, indent, lines);
|
|
18
|
+
const d = depth ?? -1;
|
|
19
|
+
const depthLabel = d === -1 ? "unlimited" : String(d);
|
|
18
20
|
lines.push("---");
|
|
19
|
-
lines.push(
|
|
21
|
+
lines.push(`depth=${depthLabel} | -d N | -i (interactive) | --visible | --json`);
|
|
20
22
|
return lines.join(`
|
|
21
23
|
`);
|
|
22
24
|
}
|
|
@@ -898,7 +900,11 @@ function parseTreeArgs(args) {
|
|
|
898
900
|
body.compact = true;
|
|
899
901
|
continue;
|
|
900
902
|
}
|
|
901
|
-
if (a === "--
|
|
903
|
+
if (a === "--interactive" || a === "-i") {
|
|
904
|
+
body.interactiveOnly = true;
|
|
905
|
+
continue;
|
|
906
|
+
}
|
|
907
|
+
if (a === "--visible" || a === "-v") {
|
|
902
908
|
body.visibleOnly = true;
|
|
903
909
|
continue;
|
|
904
910
|
}
|
|
@@ -1140,6 +1146,13 @@ function clean(obj) {
|
|
|
1140
1146
|
}
|
|
1141
1147
|
return Object.keys(result).length ? result : undefined;
|
|
1142
1148
|
}
|
|
1149
|
+
function getSessionId() {
|
|
1150
|
+
if (process.env.HALTIJA_SESSION)
|
|
1151
|
+
return process.env.HALTIJA_SESSION;
|
|
1152
|
+
const id = `hj_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1153
|
+
process.env.HALTIJA_SESSION = id;
|
|
1154
|
+
return id;
|
|
1155
|
+
}
|
|
1143
1156
|
async function isServerRunning(port) {
|
|
1144
1157
|
try {
|
|
1145
1158
|
const resp = await fetch(`http://localhost:${port}/status`, {
|
|
@@ -1198,9 +1211,75 @@ async function startServerInBackground(port) {
|
|
|
1198
1211
|
}
|
|
1199
1212
|
return false;
|
|
1200
1213
|
}
|
|
1201
|
-
async function
|
|
1214
|
+
async function launchElectronApp() {
|
|
1215
|
+
const { execSync, spawn: spawnChild } = await import("child_process");
|
|
1216
|
+
if (process.platform === "darwin") {
|
|
1217
|
+
const appPaths = [
|
|
1218
|
+
"/Applications/Haltija.app",
|
|
1219
|
+
`${process.env.HOME}/Applications/Haltija.app`
|
|
1220
|
+
];
|
|
1221
|
+
for (const p of appPaths) {
|
|
1222
|
+
if (existsSync(p)) {
|
|
1223
|
+
spawnChild("open", ["-a", p], { stdio: "ignore", detached: true }).unref();
|
|
1224
|
+
return true;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
try {
|
|
1228
|
+
const result = execSync('mdfind "kMDItemCFBundleIdentifier == com.electron.haltija" | head -1', { encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }).trim();
|
|
1229
|
+
if (result) {
|
|
1230
|
+
spawnChild("open", ["-a", result], { stdio: "ignore", detached: true }).unref();
|
|
1231
|
+
return true;
|
|
1232
|
+
}
|
|
1233
|
+
} catch {}
|
|
1234
|
+
return false;
|
|
1235
|
+
}
|
|
1236
|
+
return false;
|
|
1237
|
+
}
|
|
1238
|
+
async function ensureBrowserConnected(port) {
|
|
1239
|
+
try {
|
|
1240
|
+
const resp = await fetch(`http://localhost:${port}/status`, {
|
|
1241
|
+
signal: AbortSignal.timeout(2000)
|
|
1242
|
+
});
|
|
1243
|
+
const status = await resp.json();
|
|
1244
|
+
if (status.ok)
|
|
1245
|
+
return true;
|
|
1246
|
+
} catch {
|
|
1247
|
+
return false;
|
|
1248
|
+
}
|
|
1249
|
+
if (process.platform !== "darwin")
|
|
1250
|
+
return false;
|
|
1251
|
+
process.stderr.write("\x1B[2mLaunching Haltija browser...\x1B[0m");
|
|
1252
|
+
const launched = await launchElectronApp();
|
|
1253
|
+
if (!launched) {
|
|
1254
|
+
process.stderr.write(`\x1B[2m not found\x1B[0m
|
|
1255
|
+
`);
|
|
1256
|
+
return false;
|
|
1257
|
+
}
|
|
1258
|
+
const maxWait = 1e4;
|
|
1259
|
+
const start = Date.now();
|
|
1260
|
+
while (Date.now() - start < maxWait) {
|
|
1261
|
+
try {
|
|
1262
|
+
const resp = await fetch(`http://localhost:${port}/status`, {
|
|
1263
|
+
signal: AbortSignal.timeout(1000)
|
|
1264
|
+
});
|
|
1265
|
+
const status = await resp.json();
|
|
1266
|
+
if (status.ok) {
|
|
1267
|
+
process.stderr.write(`\x1B[2m ready\x1B[0m
|
|
1268
|
+
`);
|
|
1269
|
+
return true;
|
|
1270
|
+
}
|
|
1271
|
+
} catch {}
|
|
1272
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
1273
|
+
}
|
|
1274
|
+
process.stderr.write(`\x1B[2m timeout\x1B[0m
|
|
1275
|
+
`);
|
|
1276
|
+
return false;
|
|
1277
|
+
}
|
|
1278
|
+
var INFO_COMMANDS = new Set(["status", "windows", "version", "help"]);
|
|
1279
|
+
async function runSubcommand(subcommand, subArgs, port = "8700", options = {}) {
|
|
1202
1280
|
const baseUrl = `http://localhost:${port}`;
|
|
1203
1281
|
const jsonOutput = subArgs.includes("--json");
|
|
1282
|
+
const noLaunch = options.noLaunch || false;
|
|
1204
1283
|
let filteredArgs = subArgs.filter((a) => a !== "--json");
|
|
1205
1284
|
let targetWindowId = undefined;
|
|
1206
1285
|
const windowIdx = filteredArgs.indexOf("--window");
|
|
@@ -1208,6 +1287,11 @@ async function runSubcommand(subcommand, subArgs, port = "8700") {
|
|
|
1208
1287
|
targetWindowId = filteredArgs[windowIdx + 1];
|
|
1209
1288
|
filteredArgs = [...filteredArgs.slice(0, windowIdx), ...filteredArgs.slice(windowIdx + 2)];
|
|
1210
1289
|
}
|
|
1290
|
+
const sessionIdx = filteredArgs.indexOf("--session");
|
|
1291
|
+
if (sessionIdx !== -1) {
|
|
1292
|
+
process.env.HALTIJA_SESSION = filteredArgs[sessionIdx + 1];
|
|
1293
|
+
filteredArgs = [...filteredArgs.slice(0, sessionIdx), ...filteredArgs.slice(sessionIdx + 2)];
|
|
1294
|
+
}
|
|
1211
1295
|
if (!await isServerRunning(port)) {
|
|
1212
1296
|
process.stderr.write("\x1B[2mStarting Haltija server...\x1B[0m");
|
|
1213
1297
|
const started = await startServerInBackground(port);
|
|
@@ -1221,6 +1305,9 @@ async function runSubcommand(subcommand, subArgs, port = "8700") {
|
|
|
1221
1305
|
process.exit(1);
|
|
1222
1306
|
}
|
|
1223
1307
|
}
|
|
1308
|
+
if (!noLaunch && !INFO_COMMANDS.has(subcommand)) {
|
|
1309
|
+
await ensureBrowserConnected(port);
|
|
1310
|
+
}
|
|
1224
1311
|
if (subcommand === "send") {
|
|
1225
1312
|
const firstArg = filteredArgs[0]?.toLocaleLowerCase();
|
|
1226
1313
|
if (firstArg === "selection") {
|
|
@@ -1266,9 +1353,10 @@ async function runSubcommand(subcommand, subArgs, port = "8700") {
|
|
|
1266
1353
|
async function doRequest(url, method, body, context = {}) {
|
|
1267
1354
|
const { subcommand, jsonOutput } = context;
|
|
1268
1355
|
try {
|
|
1269
|
-
const
|
|
1356
|
+
const sessionId = getSessionId();
|
|
1357
|
+
const opts = { method, headers: { "X-Haltija-Session": sessionId } };
|
|
1270
1358
|
if (body) {
|
|
1271
|
-
opts.headers
|
|
1359
|
+
opts.headers["Content-Type"] = "application/json";
|
|
1272
1360
|
opts.body = JSON.stringify(body);
|
|
1273
1361
|
}
|
|
1274
1362
|
const resp = await fetch(url, opts);
|
|
@@ -1276,7 +1364,7 @@ async function doRequest(url, method, body, context = {}) {
|
|
|
1276
1364
|
if (contentType.includes("application/json")) {
|
|
1277
1365
|
const json = await resp.json();
|
|
1278
1366
|
if (!jsonOutput && subcommand === "tree" && json.success && json.data) {
|
|
1279
|
-
console.log(formatTree(json.data));
|
|
1367
|
+
console.log(formatTree(json.data, 0, { depth: body?.depth }));
|
|
1280
1368
|
} else if (!jsonOutput && subcommand === "events" && (json.events || Array.isArray(json))) {
|
|
1281
1369
|
console.log(formatEvents(json));
|
|
1282
1370
|
} else if (!jsonOutput && subcommand === "test-run" && json.test) {
|
|
@@ -1428,7 +1516,7 @@ function listSubcommands() {
|
|
|
1428
1516
|
return `
|
|
1429
1517
|
Subcommands (replace curl with simple commands):
|
|
1430
1518
|
${bold("Inspect")}
|
|
1431
|
-
tree [selector] [-d
|
|
1519
|
+
tree [selector] [-d N] [-i] [-v] DOM tree (full depth, -i=interactive, -v=visible)
|
|
1432
1520
|
query <selector> Find elements matching selector
|
|
1433
1521
|
inspect <@ref|selector> Detailed element info
|
|
1434
1522
|
inspectAll <selector> Deep inspect all matches
|
|
@@ -1558,6 +1646,17 @@ if (portIdx !== -1 && args[portIdx + 1]) {
|
|
|
1558
1646
|
port = args[portIdx + 1];
|
|
1559
1647
|
args.splice(portIdx, 2);
|
|
1560
1648
|
}
|
|
1649
|
+
var sessionIdx = args.indexOf("--session");
|
|
1650
|
+
if (sessionIdx !== -1 && args[sessionIdx + 1]) {
|
|
1651
|
+
process.env.HALTIJA_SESSION = args[sessionIdx + 1];
|
|
1652
|
+
args.splice(sessionIdx, 2);
|
|
1653
|
+
}
|
|
1654
|
+
var noLaunch = false;
|
|
1655
|
+
var noLaunchIdx = args.indexOf("--no-launch");
|
|
1656
|
+
if (noLaunchIdx !== -1) {
|
|
1657
|
+
noLaunch = true;
|
|
1658
|
+
args.splice(noLaunchIdx, 1);
|
|
1659
|
+
}
|
|
1561
1660
|
var subcommand = args[0];
|
|
1562
1661
|
var subArgs = args.slice(1).filter((a) => a !== "--window" || true);
|
|
1563
1662
|
if (!isSubcommand(subcommand)) {
|
|
@@ -1581,7 +1680,7 @@ Examples: hj tree, hj navigate <url>, hj click @42`);
|
|
|
1581
1680
|
console.error(`Run 'hj' for docs.`);
|
|
1582
1681
|
process.exit(1);
|
|
1583
1682
|
} else {
|
|
1584
|
-
runSubcommand(subcommand, subArgs, port);
|
|
1683
|
+
runSubcommand(subcommand, subArgs, port, { noLaunch });
|
|
1585
1684
|
}
|
|
1586
1685
|
function filterHelp(topic) {
|
|
1587
1686
|
const bold2 = (s) => `\x1B[1m${s}\x1B[0m`;
|