cssprobe-cli 0.2.16 → 0.2.22

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 CHANGED
@@ -130,6 +130,7 @@ cssprobe-cli inspect body --json | jq '.findings[] | {id, confidence, message}'
130
130
  | `open [url] --state <file>` | Open with saved cookies + localStorage |
131
131
  | `open [url] --viewport 1280x720` | Custom viewport size |
132
132
  | `close` | Close browser session |
133
+ | `close --all` | Close all sessions across all workspaces |
133
134
  | `status` | Show session status |
134
135
 
135
136
  ### CSS Inspection
@@ -63,6 +63,9 @@ const close = (0, command_1.declareCommand)({
63
63
  name: 'close',
64
64
  category: 'core',
65
65
  description: 'Close the browser session',
66
+ options: z.object({
67
+ all: z.boolean().optional().describe('close all sessions across all workspaces'),
68
+ }),
66
69
  });
67
70
  const status = (0, command_1.declareCommand)({
68
71
  name: 'status',
@@ -43,7 +43,7 @@ async function program() {
43
43
  await handleOpen(command, rawArgs, output);
44
44
  return;
45
45
  case 'close':
46
- await handleClose(output);
46
+ await handleClose(command, rawArgs, output);
47
47
  return;
48
48
  case 'status':
49
49
  await handleStatus(output);
@@ -172,19 +172,47 @@ async function waitForSession(timeoutMs) {
172
172
  }
173
173
  return undefined;
174
174
  }
175
- async function handleClose(output) {
175
+ async function handleClose(command, args, output) {
176
176
  try {
177
- const session = await (0, session_1.loadSession)();
178
- if (!session) {
179
- output.error('No active session. Run: cssprobe-cli open <url>');
180
- return;
181
- }
182
- await session.stop();
183
- if (output.json) {
184
- console.log(JSON.stringify({ closed: true, sessionId: 'default' }, null, 2));
177
+ const cmdArgs = splitArgs(args);
178
+ const parsed = (0, command_1.parseCommand)(command, cmdArgs);
179
+ if (parsed.all) {
180
+ const sessions = await (0, session_1.listAllSessions)();
181
+ if (sessions.length === 0) {
182
+ output.error('No active sessions found.');
183
+ return;
184
+ }
185
+ const results = [];
186
+ for (const session of sessions) {
187
+ try {
188
+ await session.stop();
189
+ results.push({ sessionId: session.name, closed: true });
190
+ }
191
+ catch (e) {
192
+ results.push({ sessionId: session.name, closed: false, error: e.message });
193
+ }
194
+ }
195
+ if (output.json) {
196
+ console.log(JSON.stringify({ closed: results }, null, 2));
197
+ }
198
+ else {
199
+ const closedCount = results.filter(r => r.closed).length;
200
+ console.log(`Closed ${closedCount} session(s).`);
201
+ }
185
202
  }
186
203
  else {
187
- console.log('Browser closed.');
204
+ const session = await (0, session_1.loadSession)();
205
+ if (!session) {
206
+ output.error('No active session. Run: cssprobe-cli open <url>');
207
+ return;
208
+ }
209
+ await session.stop();
210
+ if (output.json) {
211
+ console.log(JSON.stringify({ closed: true, sessionId: 'default' }, null, 2));
212
+ }
213
+ else {
214
+ console.log('Browser closed.');
215
+ }
188
216
  }
189
217
  }
190
218
  catch (e) {
@@ -50,3 +50,4 @@ export declare function createClientInfo(): ClientInfo;
50
50
  export declare function loadSession(): Promise<Session | undefined>;
51
51
  export declare function saveSession(config: SessionConfig): Promise<void>;
52
52
  export declare function deleteSession(): Promise<void>;
53
+ export declare function listAllSessions(): Promise<Session[]>;
@@ -13,6 +13,7 @@ exports.createClientInfo = createClientInfo;
13
13
  exports.loadSession = loadSession;
14
14
  exports.saveSession = saveSession;
15
15
  exports.deleteSession = deleteSession;
16
+ exports.listAllSessions = listAllSessions;
16
17
  const crypto_1 = __importDefault(require("crypto"));
17
18
  const fs_1 = __importDefault(require("fs"));
18
19
  const net_1 = __importDefault(require("net"));
@@ -229,4 +230,28 @@ async function deleteSession() {
229
230
  const sessionFile = path_1.default.join(clientInfo.daemonProfilesDir, 'default.session');
230
231
  await fs_1.default.promises.unlink(sessionFile).catch(() => { });
231
232
  }
233
+ async function listAllSessions() {
234
+ const sessions = [];
235
+ const baseDir = path_1.default.dirname(createClientInfo().daemonProfilesDir);
236
+ try {
237
+ const entries = await fs_1.default.promises.readdir(baseDir, { withFileTypes: true });
238
+ for (const entry of entries) {
239
+ if (!entry.isDirectory())
240
+ continue;
241
+ const sessionFile = path_1.default.join(baseDir, entry.name, 'default.session');
242
+ try {
243
+ const data = await fs_1.default.promises.readFile(sessionFile, 'utf-8');
244
+ const config = JSON.parse(data);
245
+ sessions.push(new Session({ file: sessionFile, config, daemonDir: path_1.default.join(baseDir, entry.name) }));
246
+ }
247
+ catch {
248
+ // Skip invalid session files
249
+ }
250
+ }
251
+ }
252
+ catch {
253
+ // Base directory doesn't exist
254
+ }
255
+ return sessions;
256
+ }
232
257
  //# sourceMappingURL=session.js.map
@@ -200,9 +200,14 @@ function analyzeScroll(snapshot) {
200
200
  message = `${nodeLabel(n)} no overflow, no scroll needed`;
201
201
  level = 'info';
202
202
  }
203
+ else if (n.props.overflowY === 'visible') {
204
+ id = 'overflow-visible';
205
+ message = `${nodeLabel(n)} content visually overflows (${n.metrics.scrollHeight}>${n.metrics.clientHeight}) but overflow=visible means content is NOT clipped`;
206
+ level = 'info';
207
+ }
203
208
  else {
204
209
  id = 'overflow-clipped';
205
- message = `${nodeLabel(n)} content overflows (${n.metrics.scrollHeight}>${n.metrics.clientHeight}) clipped by overflow=${n.props.overflowY} → height chain unconstrained (anchor issue)`;
210
+ message = `${nodeLabel(n)} content overflows (${n.metrics.scrollHeight}>${n.metrics.clientHeight}) clipped by overflow=${n.props.overflowY}`;
206
211
  level = 'warning';
207
212
  }
208
213
  findings.push(makeFinding({
@@ -7,7 +7,7 @@ function renderNode(node, indent) {
7
7
  return lines;
8
8
  const cls = node.classes.length ? `.${node.classes.join('.')}` : '';
9
9
  const id = node.id ? `#${node.id}` : '';
10
- const repeat = node.repeat ? ` \u00D7${node.repeat}` : '';
10
+ const repeat = node.repeat ? ` \u00D7${node.repeat} (first shown, use :nth-child(N) for others)` : '';
11
11
  const m = node.metrics;
12
12
  const s = node.shape || {};
13
13
  const flag = [];
package/dist/help.json CHANGED
@@ -14,8 +14,10 @@
14
14
  ]
15
15
  },
16
16
  "close": {
17
- "help": "cssprobe-cli close \n\nClose the browser session\n\n\nGlobal options:\n --json output as JSON\n --profile, -p <name> use named profile",
18
- "flags": {},
17
+ "help": "cssprobe-cli close \n\nClose the browser session\n\nOptions:\n --all close all sessions across all workspaces\n\nGlobal options:\n --json output as JSON\n --profile, -p <name> use named profile",
18
+ "flags": {
19
+ "all": "boolean"
20
+ },
19
21
  "args": []
20
22
  },
21
23
  "status": {
@@ -167,6 +169,7 @@
167
169
  },
168
170
  "booleanOptions": [
169
171
  "headed",
172
+ "all",
170
173
  "json",
171
174
  "brief",
172
175
  "layout",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cssprobe-cli",
3
- "version": "0.2.16",
3
+ "version": "0.2.22",
4
4
  "description": "Runtime CSS probe — inspect layout, colors, backgrounds, fonts and more in a live browser. AI agents and shell automation.",
5
5
  "keywords": [
6
6
  "css",
@@ -14,7 +14,10 @@
14
14
  "automation"
15
15
  ],
16
16
  "homepage": "https://github.com/mack-peng/cssprobe-cli#readme",
17
- "repository": "github:mack-peng/cssprobe-cli",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/mack-peng/cssprobe-cli.git"
20
+ },
18
21
  "license": "MIT",
19
22
  "author": "strikingly",
20
23
  "main": "dist/index.js",