cssprobe-cli 0.1.0 → 0.1.2
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 +12 -5
- package/dist/browser/launcher.d.ts +2 -0
- package/dist/browser/launcher.js +19 -0
- package/dist/cli/commands.d.ts +3 -0
- package/dist/cli/commands.js +2 -1
- package/dist/cli/program.js +19 -5
- package/dist/engine/renderer.d.ts +2 -2
- package/dist/engine/renderer.js +142 -15
- package/dist/help.json +4 -2
- package/dist/installer/skill-template.js +9 -9
- package/docs/guide/installation.md +7 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,10 +24,10 @@ cssprobe-cli skill-install
|
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
# With explicit selector
|
|
27
|
-
cssprobe-cli inspect https://
|
|
27
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout ".container"
|
|
28
28
|
|
|
29
29
|
# Auto-detect root element
|
|
30
|
-
cssprobe-cli inspect https://
|
|
30
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout
|
|
31
31
|
|
|
32
32
|
# Local HTML file
|
|
33
33
|
cssprobe-cli inspect ./test.html ".container"
|
|
@@ -49,8 +49,8 @@ cssprobe-cli inspect https://mysite.com/page ".target" --state ~/.cssprobe-cli/s
|
|
|
49
49
|
### 3. JSON Output
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
cssprobe-cli inspect https://
|
|
53
|
-
cssprobe-cli
|
|
52
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json
|
|
53
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json | jq '.findings[] | {id, confidence, message}'
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
---
|
|
@@ -74,6 +74,12 @@ cssprobe-cli login <url> # Interactive login, save state
|
|
|
74
74
|
cssprobe-cli state-import [file] # Import cookies from Netscape format
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
### Inspection
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body
|
|
81
|
+
```
|
|
82
|
+
|
|
77
83
|
### Configuration
|
|
78
84
|
|
|
79
85
|
```bash
|
|
@@ -101,10 +107,11 @@ Options:
|
|
|
101
107
|
--headed Show browser window
|
|
102
108
|
--browser <engine> chromium|firefox|webkit (default chromium)
|
|
103
109
|
--zoom Run 1x/0.5x viewport diagnosis
|
|
104
|
-
--depth <n> DOM tree depth (default
|
|
110
|
+
--depth <n> DOM tree depth (default: auto)
|
|
105
111
|
--max-nodes <n> Node count cap (default 60)
|
|
106
112
|
--up-to <tag> Ancestor stop tag (default html)
|
|
107
113
|
--state <file> Load saved state (cookies + localStorage)
|
|
114
|
+
--brief Compact output: tree sketch + warnings/errors only
|
|
108
115
|
```
|
|
109
116
|
|
|
110
117
|
---
|
|
@@ -13,6 +13,8 @@ export declare class BrowserLauncher {
|
|
|
13
13
|
constructor(options?: LauncherOptions);
|
|
14
14
|
open(url: string): Promise<void>;
|
|
15
15
|
collect(cfg: CollectConfig): Promise<Snapshot>;
|
|
16
|
+
/** Measure the DOM tree depth from a root selector to the deepest leaf. */
|
|
17
|
+
measureDepth(selector: string): Promise<number>;
|
|
16
18
|
/** Scan the page for likely root elements (modals, dialogs, scroll containers). */
|
|
17
19
|
autoDetectRoot(): Promise<string[]>;
|
|
18
20
|
/**
|
package/dist/browser/launcher.js
CHANGED
|
@@ -106,6 +106,25 @@ class BrowserLauncher {
|
|
|
106
106
|
}, cfg);
|
|
107
107
|
return snapshot;
|
|
108
108
|
}
|
|
109
|
+
/** Measure the DOM tree depth from a root selector to the deepest leaf. */
|
|
110
|
+
async measureDepth(selector) {
|
|
111
|
+
if (!this.page)
|
|
112
|
+
throw new Error('Browser not opened. Call open() first.');
|
|
113
|
+
return this.page.evaluate((sel) => {
|
|
114
|
+
const root = document.querySelector(sel);
|
|
115
|
+
if (!root)
|
|
116
|
+
return 0;
|
|
117
|
+
let maxDepth = 0;
|
|
118
|
+
const walk = (el, depth) => {
|
|
119
|
+
if (depth > maxDepth)
|
|
120
|
+
maxDepth = depth;
|
|
121
|
+
for (const child of Array.from(el.children))
|
|
122
|
+
walk(child, depth + 1);
|
|
123
|
+
};
|
|
124
|
+
walk(root, 0);
|
|
125
|
+
return maxDepth;
|
|
126
|
+
}, selector);
|
|
127
|
+
}
|
|
109
128
|
/** Scan the page for likely root elements (modals, dialogs, scroll containers). */
|
|
110
129
|
async autoDetectRoot() {
|
|
111
130
|
if (!this.page)
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare const inspectCommand: import("./command").CommandSchema<z.ZodObje
|
|
|
21
21
|
'max-nodes': z.ZodOptional<z.ZodEffects<z.ZodNumber, number, unknown>>;
|
|
22
22
|
'up-to': z.ZodOptional<z.ZodString>;
|
|
23
23
|
state: z.ZodOptional<z.ZodString>;
|
|
24
|
+
brief: z.ZodOptional<z.ZodBoolean>;
|
|
24
25
|
}, "strip", z.ZodTypeAny, {
|
|
25
26
|
json?: boolean | undefined;
|
|
26
27
|
headed?: boolean | undefined;
|
|
@@ -30,6 +31,7 @@ export declare const inspectCommand: import("./command").CommandSchema<z.ZodObje
|
|
|
30
31
|
'max-nodes'?: number | undefined;
|
|
31
32
|
'up-to'?: string | undefined;
|
|
32
33
|
state?: string | undefined;
|
|
34
|
+
brief?: boolean | undefined;
|
|
33
35
|
}, {
|
|
34
36
|
json?: boolean | undefined;
|
|
35
37
|
headed?: boolean | undefined;
|
|
@@ -39,4 +41,5 @@ export declare const inspectCommand: import("./command").CommandSchema<z.ZodObje
|
|
|
39
41
|
'max-nodes'?: unknown;
|
|
40
42
|
'up-to'?: string | undefined;
|
|
41
43
|
state?: string | undefined;
|
|
44
|
+
brief?: boolean | undefined;
|
|
42
45
|
}>>;
|
package/dist/cli/commands.js
CHANGED
|
@@ -58,10 +58,11 @@ const inspect = (0, command_1.declareCommand)({
|
|
|
58
58
|
headed: z.boolean().optional().describe('show the browser window'),
|
|
59
59
|
browser: z.enum(['chromium', 'firefox', 'webkit']).optional().describe('browser engine (default chromium)'),
|
|
60
60
|
zoom: z.boolean().optional().describe('run 1x/0.5x viewport diagnosis'),
|
|
61
|
-
depth: numberArg.optional().describe('DOM tree depth (default
|
|
61
|
+
depth: numberArg.optional().describe('DOM tree depth (default: auto, max 20)'),
|
|
62
62
|
'max-nodes': numberArg.optional().describe('node count cap (default 60)'),
|
|
63
63
|
'up-to': z.string().optional().describe('ancestor stop tag (default html)'),
|
|
64
64
|
state: z.string().optional().describe('path to saved state file (cookies + localStorage)'),
|
|
65
|
+
brief: z.boolean().optional().describe('compact output: tree sketch + warnings/errors only'),
|
|
65
66
|
}),
|
|
66
67
|
});
|
|
67
68
|
const login = (0, command_1.declareCommand)({
|
package/dist/cli/program.js
CHANGED
|
@@ -100,12 +100,20 @@ async function handleInspect(command, cmdEntry, args, output) {
|
|
|
100
100
|
const url = parsed.url;
|
|
101
101
|
const selector = parsed.selector;
|
|
102
102
|
const zoom = !!parsed.zoom;
|
|
103
|
-
const
|
|
103
|
+
const depthRaw = parsed.depth;
|
|
104
|
+
let depth;
|
|
105
|
+
if (depthRaw === 'auto' || depthRaw === undefined) {
|
|
106
|
+
depth = 0; // placeholder, resolved after browser opens
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
depth = Number(depthRaw);
|
|
110
|
+
}
|
|
104
111
|
const maxNodes = parsed['max-nodes'] || 60;
|
|
105
112
|
const upTo = parsed['up-to'] || 'html';
|
|
106
113
|
const headed = !!parsed.headed || config.headed;
|
|
107
114
|
const browser = parsed.browser || config.browser;
|
|
108
115
|
const state = parsed.state || undefined;
|
|
116
|
+
const brief = !!parsed.brief;
|
|
109
117
|
if (!url)
|
|
110
118
|
output.error('URL is required. Usage: cssprobe-cli inspect <url> [selector]');
|
|
111
119
|
// Auto-detect root selector if not provided
|
|
@@ -119,22 +127,28 @@ async function handleInspect(command, cmdEntry, args, output) {
|
|
|
119
127
|
rootSelector = detected;
|
|
120
128
|
console.error(`Auto-detected root: ${rootSelector}`);
|
|
121
129
|
}
|
|
130
|
+
const launcher = new launcher_1.BrowserLauncher({ browser, headed, state });
|
|
131
|
+
await launcher.open(url);
|
|
132
|
+
// Resolve auto depth
|
|
133
|
+
if (depth === 0) {
|
|
134
|
+
const measured = await launcher.measureDepth(rootSelector);
|
|
135
|
+
depth = Math.min(measured, 20) || 6;
|
|
136
|
+
console.error(`Auto-detected depth: ${measured} (using ${depth})`);
|
|
137
|
+
}
|
|
122
138
|
const collectCfg = {
|
|
123
139
|
rootSelector,
|
|
124
140
|
upTo,
|
|
125
141
|
downDepth: depth,
|
|
126
142
|
maxNodes,
|
|
127
143
|
};
|
|
128
|
-
const launcher = new launcher_1.BrowserLauncher({ browser, headed, state });
|
|
129
|
-
await launcher.open(url);
|
|
130
144
|
const snapshot = await launcher.collect(collectCfg);
|
|
131
145
|
await launcher.close();
|
|
132
146
|
const findings = (0, analyzer_1.analyze)(snapshot);
|
|
133
147
|
if (output.json) {
|
|
134
|
-
console.log(output.format((0, renderer_1.renderJSON)(snapshot, findings)));
|
|
148
|
+
console.log(output.format((0, renderer_1.renderJSON)(snapshot, findings, brief)));
|
|
135
149
|
}
|
|
136
150
|
else {
|
|
137
|
-
console.log((0, renderer_1.renderMarkdown)(snapshot, findings));
|
|
151
|
+
console.log((0, renderer_1.renderMarkdown)(snapshot, findings, brief));
|
|
138
152
|
}
|
|
139
153
|
}
|
|
140
154
|
catch (e) {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Snapshot, Finding } from './types';
|
|
2
|
-
export declare function renderMarkdown(snapshot: Snapshot, findings: Finding[]): string;
|
|
3
|
-
export declare function renderJSON(snapshot: Snapshot, findings: Finding[]): object;
|
|
2
|
+
export declare function renderMarkdown(snapshot: Snapshot, findings: Finding[], brief?: boolean): string;
|
|
3
|
+
export declare function renderJSON(snapshot: Snapshot, findings: Finding[], brief?: boolean): object;
|
package/dist/engine/renderer.js
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.renderMarkdown = renderMarkdown;
|
|
6
6
|
exports.renderJSON = renderJSON;
|
|
7
|
+
// ─── Node label (matches analyzer.ts nodeLabel) ───
|
|
8
|
+
function nodeLabel(node) {
|
|
9
|
+
const cls = node.classes.length ? `.${node.classes.join('.')}` : '';
|
|
10
|
+
const id = node.id ? `#${node.id}` : '';
|
|
11
|
+
return `${node.tag}${id}${cls}`;
|
|
12
|
+
}
|
|
7
13
|
// ─── Node rendering (DOM tree) ───
|
|
8
14
|
function renderNode(node, indent) {
|
|
9
15
|
const lines = [];
|
|
@@ -57,6 +63,79 @@ function renderAncestors(chain) {
|
|
|
57
63
|
(a.inlineStyle ? ` style="${a.inlineStyle}"` : '');
|
|
58
64
|
});
|
|
59
65
|
}
|
|
66
|
+
function buildSketchTree(node, issueLabels) {
|
|
67
|
+
if (!node)
|
|
68
|
+
return null;
|
|
69
|
+
const label = nodeLabel(node);
|
|
70
|
+
const s = node.shape || {};
|
|
71
|
+
const shapeStr = s.role ? `[${s.role} h:${s.heightStrategy} w:${s.widthStrategy}]` : '';
|
|
72
|
+
const flags = [];
|
|
73
|
+
if (node.flags.overflowsParent)
|
|
74
|
+
flags.push('\u26A0parent-overflow');
|
|
75
|
+
if (node.flags.overflowsViewport)
|
|
76
|
+
flags.push('\u26A0viewport-overflow');
|
|
77
|
+
if (node.metrics.clientHeight === 0 && node.metrics.offsetHeight === 0)
|
|
78
|
+
flags.push('\u26A0collapsed');
|
|
79
|
+
if (node.flags.scrollable)
|
|
80
|
+
flags.push('\u2714scrollable');
|
|
81
|
+
if (node.containingBlockModifiers.length)
|
|
82
|
+
flags.push(`CB:${node.containingBlockModifiers.join(' ')}`);
|
|
83
|
+
const hasIssue = issueLabels.has(label) || flags.length > 0;
|
|
84
|
+
const children = [];
|
|
85
|
+
let omitted = 0;
|
|
86
|
+
for (const child of node.children) {
|
|
87
|
+
const sketchChild = buildSketchTree(child, issueLabels);
|
|
88
|
+
if (!sketchChild)
|
|
89
|
+
continue;
|
|
90
|
+
if (sketchChild.hasIssue || hasDescendantIssue(sketchChild)) {
|
|
91
|
+
children.push(sketchChild);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
omitted++;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { label, shape: shapeStr, flags, children, hasIssue, omitted };
|
|
98
|
+
}
|
|
99
|
+
function hasDescendantIssue(node) {
|
|
100
|
+
if (node.hasIssue)
|
|
101
|
+
return true;
|
|
102
|
+
return node.children.some(c => hasDescendantIssue(c));
|
|
103
|
+
}
|
|
104
|
+
function renderSketchNode(node, prefix, isLast) {
|
|
105
|
+
const lines = [];
|
|
106
|
+
const connector = isLast ? '\u2514\u2500 ' : '\u251C\u2500 ';
|
|
107
|
+
const flagStr = node.flags.length ? ` ${node.flags.join(' ')}` : '';
|
|
108
|
+
const issueMark = node.hasIssue && node.flags.length === 0 ? ' \u26A0' : '';
|
|
109
|
+
lines.push(`${prefix}${connector}${node.label} ${node.shape}${flagStr}${issueMark}`);
|
|
110
|
+
const childPrefix = prefix + (isLast ? ' ' : '\u2502 ');
|
|
111
|
+
const totalChildren = node.children.length + (node.omitted > 0 ? 1 : 0);
|
|
112
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
113
|
+
lines.push(...renderSketchNode(node.children[i], childPrefix, i === totalChildren - 1));
|
|
114
|
+
}
|
|
115
|
+
if (node.omitted > 0) {
|
|
116
|
+
const omConnector = '\u2514\u2500 ';
|
|
117
|
+
lines.push(`${childPrefix}${omConnector}... (${node.omitted} subtrees omitted)`);
|
|
118
|
+
}
|
|
119
|
+
return lines;
|
|
120
|
+
}
|
|
121
|
+
function renderSketch(tree, findings) {
|
|
122
|
+
if (!tree)
|
|
123
|
+
return ['(empty tree)'];
|
|
124
|
+
const issueLabels = new Set();
|
|
125
|
+
for (const f of findings) {
|
|
126
|
+
if (f.level === 'warning' || f.level === 'error') {
|
|
127
|
+
if (f.location)
|
|
128
|
+
issueLabels.add(f.location);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const sketchRoot = buildSketchTree(tree, issueLabels);
|
|
132
|
+
if (!sketchRoot)
|
|
133
|
+
return ['(empty tree)'];
|
|
134
|
+
if (!hasDescendantIssue(sketchRoot) && !sketchRoot.hasIssue) {
|
|
135
|
+
return [`${sketchRoot.label} ${sketchRoot.shape} (no issues found in tree)`];
|
|
136
|
+
}
|
|
137
|
+
return renderSketchNode(sketchRoot, '', true);
|
|
138
|
+
}
|
|
60
139
|
// ─── Findings rendering ───
|
|
61
140
|
const CONF_BADGE = {
|
|
62
141
|
DEFINITE: 'DEFINITE',
|
|
@@ -85,6 +164,22 @@ function renderFindings(findings) {
|
|
|
85
164
|
}
|
|
86
165
|
return lines;
|
|
87
166
|
}
|
|
167
|
+
function renderBriefFindings(findings) {
|
|
168
|
+
const lines = [];
|
|
169
|
+
lines.push('## Findings');
|
|
170
|
+
const important = findings.filter(f => f.level === 'warning' || f.level === 'error');
|
|
171
|
+
if (important.length === 0) {
|
|
172
|
+
lines.push('- No warnings or errors');
|
|
173
|
+
return lines;
|
|
174
|
+
}
|
|
175
|
+
for (const f of important) {
|
|
176
|
+
const badge = `[${CONF_BADGE[f.confidence]}]`;
|
|
177
|
+
const loc = f.location ? ` @ ${f.location}` : '';
|
|
178
|
+
const icon = f.level === 'error' ? '\u26A0' : '\u26A0';
|
|
179
|
+
lines.push(`- ${icon} ${f.message} ${badge}${loc}`);
|
|
180
|
+
}
|
|
181
|
+
return lines;
|
|
182
|
+
}
|
|
88
183
|
function confidenceSummary(findings) {
|
|
89
184
|
const counts = findings.reduce((acc, f) => {
|
|
90
185
|
acc[f.confidence] = (acc[f.confidence] || 0) + 1;
|
|
@@ -98,7 +193,7 @@ function confidenceSummary(findings) {
|
|
|
98
193
|
return parts.join(' | ');
|
|
99
194
|
}
|
|
100
195
|
// ─── Markdown ───
|
|
101
|
-
function renderMarkdown(snapshot, findings) {
|
|
196
|
+
function renderMarkdown(snapshot, findings, brief = false) {
|
|
102
197
|
const lines = [];
|
|
103
198
|
const vp = snapshot.viewport ? `${snapshot.viewport.width}\u00D7${snapshot.viewport.height}` : 'unknown';
|
|
104
199
|
lines.push('# cssprobe-cli report');
|
|
@@ -117,13 +212,22 @@ function renderMarkdown(snapshot, findings) {
|
|
|
117
212
|
lines.push('```');
|
|
118
213
|
lines.push(...renderAncestors(snapshot.ancestors));
|
|
119
214
|
lines.push('```');
|
|
215
|
+
if (brief) {
|
|
216
|
+
lines.push('');
|
|
217
|
+
lines.push('## Tree Sketch (issues only)');
|
|
218
|
+
lines.push('```');
|
|
219
|
+
lines.push(...renderSketch(snapshot.tree, findings));
|
|
220
|
+
lines.push('```');
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
lines.push('');
|
|
224
|
+
lines.push(`## DOM tree (${snapshot.downDepth} levels deep)`);
|
|
225
|
+
lines.push('```');
|
|
226
|
+
lines.push(...renderNode(snapshot.tree, 0));
|
|
227
|
+
lines.push('```');
|
|
228
|
+
}
|
|
120
229
|
lines.push('');
|
|
121
|
-
lines.push(
|
|
122
|
-
lines.push('```');
|
|
123
|
-
lines.push(...renderNode(snapshot.tree, 0));
|
|
124
|
-
lines.push('```');
|
|
125
|
-
lines.push('');
|
|
126
|
-
lines.push(...renderFindings(findings));
|
|
230
|
+
lines.push(...(brief ? renderBriefFindings(findings) : renderFindings(findings)));
|
|
127
231
|
if (snapshot.crossOriginBlocked && snapshot.crossOriginBlocked > 0) {
|
|
128
232
|
lines.push('');
|
|
129
233
|
lines.push('## Cross-origin limitation');
|
|
@@ -135,19 +239,42 @@ function renderMarkdown(snapshot, findings) {
|
|
|
135
239
|
return lines.join('\n');
|
|
136
240
|
}
|
|
137
241
|
// ─── JSON ───
|
|
138
|
-
function renderJSON(snapshot, findings) {
|
|
242
|
+
function renderJSON(snapshot, findings, brief = false) {
|
|
139
243
|
const counts = findings.reduce((acc, f) => {
|
|
140
244
|
acc[f.confidence] = (acc[f.confidence] || 0) + 1;
|
|
141
245
|
return acc;
|
|
142
246
|
}, {});
|
|
247
|
+
const meta = {
|
|
248
|
+
rootSelector: snapshot.rootSelector,
|
|
249
|
+
viewport: snapshot.viewport,
|
|
250
|
+
nodeCount: snapshot.nodeCount,
|
|
251
|
+
crossOriginBlocked: snapshot.crossOriginBlocked,
|
|
252
|
+
blockedSheetUrls: snapshot.blockedSheetUrls,
|
|
253
|
+
};
|
|
254
|
+
if (brief) {
|
|
255
|
+
const important = findings.filter(f => f.level === 'warning' || f.level === 'error');
|
|
256
|
+
const briefFindings = important.map(f => ({
|
|
257
|
+
id: f.id,
|
|
258
|
+
level: f.level,
|
|
259
|
+
message: f.message,
|
|
260
|
+
confidence: f.confidence,
|
|
261
|
+
location: f.location,
|
|
262
|
+
evidence: f.evidence.slice(0, 1),
|
|
263
|
+
}));
|
|
264
|
+
return {
|
|
265
|
+
meta,
|
|
266
|
+
snapshot: { rootSelector: snapshot.rootSelector, nodeCount: snapshot.nodeCount, downDepth: snapshot.downDepth },
|
|
267
|
+
findings: briefFindings,
|
|
268
|
+
summary: {
|
|
269
|
+
total: findings.length,
|
|
270
|
+
warnings: important.filter(f => f.level === 'warning').length,
|
|
271
|
+
errors: important.filter(f => f.level === 'error').length,
|
|
272
|
+
confidence: { DEFINITE: counts.DEFINITE || 0, INDEFINITE: counts.INDEFINITE || 0, UNVERIFIABLE: counts.UNVERIFIABLE || 0 },
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
}
|
|
143
276
|
return {
|
|
144
|
-
meta
|
|
145
|
-
rootSelector: snapshot.rootSelector,
|
|
146
|
-
viewport: snapshot.viewport,
|
|
147
|
-
nodeCount: snapshot.nodeCount,
|
|
148
|
-
crossOriginBlocked: snapshot.crossOriginBlocked,
|
|
149
|
-
blockedSheetUrls: snapshot.blockedSheetUrls,
|
|
150
|
-
},
|
|
277
|
+
meta,
|
|
151
278
|
snapshot: snapshot.error ? { error: snapshot.error, candidates: snapshot.candidates } : snapshot,
|
|
152
279
|
findings,
|
|
153
280
|
summary: {
|
package/dist/help.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"global": "Usage: cssprobe-cli <command> [args] [options]\n\n\nInspection:\n inspect <url> [selector] inspect the runtime css of a page (layout, scroll, colors, fonts, backgrounds)\n login <url> open browser for interactive login, then save state for later use\n state-import [file] import cookies from netscape format file into a playwright state file\n\nConfiguration:\n config-show show current configuration\n config-set <key> <value> set a configuration value\n config-list list all profiles\n config-use <name> switch active profile\n config-new <name> create a new profile\n config-path show configuration file path\n\nAgent Skills:\n skill-install install agent skill for cssprobe-cli (teaches agents how to use the cli)\n skill-uninstall remove agent skill for cssprobe-cli\n\nGlobal options:\n --help [command] print help\n --json output response as JSON\n --raw output only the result value\n --version print version\n -p, --profile <name> use named profile (or CSSPROBE_PROFILE env)",
|
|
3
3
|
"commands": {
|
|
4
4
|
"inspect": {
|
|
5
|
-
"help": "cssprobe-cli inspect <url> [selector]\n\nInspect the runtime CSS of a page (layout, scroll, colors, fonts, backgrounds)\n\nArguments:\n <url> url, file:// path, or local html file path\n [selector] css selector for the root element (auto-detected if omitted)\nOptions:\n --json output structured json instead of markdown\n --headed show the browser window\n --browser browser engine (default chromium)\n --zoom run 1x/0.5x viewport diagnosis\n --depth dom tree depth (default
|
|
5
|
+
"help": "cssprobe-cli inspect <url> [selector]\n\nInspect the runtime CSS of a page (layout, scroll, colors, fonts, backgrounds)\n\nArguments:\n <url> url, file:// path, or local html file path\n [selector] css selector for the root element (auto-detected if omitted)\nOptions:\n --json output structured json instead of markdown\n --headed show the browser window\n --browser browser engine (default chromium)\n --zoom run 1x/0.5x viewport diagnosis\n --depth dom tree depth (default: auto, max 20)\n --max-nodes node count cap (default 60)\n --up-to ancestor stop tag (default html)\n --state path to saved state file (cookies + localstorage)\n --brief compact output: tree sketch + warnings/errors only\n\nGlobal options:\n --json output as JSON\n --profile, -p <name> use named profile",
|
|
6
6
|
"flags": {
|
|
7
7
|
"json": "boolean",
|
|
8
8
|
"headed": "boolean",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"depth": "string",
|
|
12
12
|
"max-nodes": "string",
|
|
13
13
|
"up-to": "string",
|
|
14
|
-
"state": "string"
|
|
14
|
+
"state": "string",
|
|
15
|
+
"brief": "boolean"
|
|
15
16
|
},
|
|
16
17
|
"args": [
|
|
17
18
|
"url",
|
|
@@ -102,6 +103,7 @@
|
|
|
102
103
|
"json",
|
|
103
104
|
"headed",
|
|
104
105
|
"zoom",
|
|
106
|
+
"brief",
|
|
105
107
|
"local"
|
|
106
108
|
]
|
|
107
109
|
}
|
|
@@ -40,7 +40,7 @@ function buildSkillMd() {
|
|
|
40
40
|
'npx playwright install chromium',
|
|
41
41
|
BT3,
|
|
42
42
|
'',
|
|
43
|
-
'Verify: ' + BT + 'cssprobe-cli
|
|
43
|
+
'Verify: ' + BT + 'cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json | head -5' + BT,
|
|
44
44
|
'',
|
|
45
45
|
'## Command Discovery',
|
|
46
46
|
'',
|
|
@@ -56,10 +56,10 @@ function buildSkillMd() {
|
|
|
56
56
|
'',
|
|
57
57
|
BT3 + 'bash',
|
|
58
58
|
'# With explicit selector',
|
|
59
|
-
'cssprobe-cli
|
|
59
|
+
'cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body',
|
|
60
60
|
'',
|
|
61
61
|
'# Auto-detect root element (picks modal/dialog/scroll-container)',
|
|
62
|
-
'cssprobe-cli inspect https://
|
|
62
|
+
'cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout',
|
|
63
63
|
'',
|
|
64
64
|
'# Local HTML file',
|
|
65
65
|
'cssprobe-cli inspect ./test.html ".container"',
|
|
@@ -101,8 +101,8 @@ function buildSkillMd() {
|
|
|
101
101
|
'Always pass ' + BT + '--json' + BT + ' when consuming output programmatically:',
|
|
102
102
|
'',
|
|
103
103
|
BT3 + 'bash',
|
|
104
|
-
'cssprobe-cli inspect https://
|
|
105
|
-
'cssprobe-cli
|
|
104
|
+
'cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json',
|
|
105
|
+
'cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json | jq ' + BT + "'.findings[] | {id, confidence, message}'" + BT,
|
|
106
106
|
BT3,
|
|
107
107
|
'',
|
|
108
108
|
'Without ' + BT + '--json' + BT + ', output is a Markdown report with ancestor chain,',
|
|
@@ -134,7 +134,7 @@ function buildSkillMd() {
|
|
|
134
134
|
' --headed Show browser window',
|
|
135
135
|
' --browser <engine> chromium|firefox|webkit (default chromium)',
|
|
136
136
|
' --zoom Run 1x/0.5x viewport diagnosis',
|
|
137
|
-
' --depth <n> DOM tree depth (default
|
|
137
|
+
' --depth <n> DOM tree depth (default: auto)',
|
|
138
138
|
' --max-nodes <n> Node count cap (default 60)',
|
|
139
139
|
' --up-to <tag> Ancestor stop tag (default html)',
|
|
140
140
|
' --state <file> Load saved state (cookies + localStorage)',
|
|
@@ -176,10 +176,10 @@ function buildSkillMd() {
|
|
|
176
176
|
'',
|
|
177
177
|
BT3 + 'bash',
|
|
178
178
|
'# Auto-detect and analyze',
|
|
179
|
-
'cssprobe-cli inspect https://
|
|
179
|
+
'cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout',
|
|
180
180
|
'',
|
|
181
181
|
'# Look for findings with level "warning" or "error"',
|
|
182
|
-
'cssprobe-cli
|
|
182
|
+
'cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json | jq ' + BT + "'.findings[] | select(.level != \"info\")'" + BT,
|
|
183
183
|
BT3,
|
|
184
184
|
'',
|
|
185
185
|
'### 3. Inspect with authentication',
|
|
@@ -196,7 +196,7 @@ function buildSkillMd() {
|
|
|
196
196
|
'',
|
|
197
197
|
BT3 + 'bash',
|
|
198
198
|
'# Use --zoom to compare 1x vs 0.5x viewport',
|
|
199
|
-
'cssprobe-cli inspect https://
|
|
199
|
+
'cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --zoom',
|
|
200
200
|
BT3,
|
|
201
201
|
'',
|
|
202
202
|
'## Anti-patterns',
|
|
@@ -27,7 +27,7 @@ npm install -g cssprobe-cli
|
|
|
27
27
|
Or run without installing (slower but zero setup):
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
npx cssprobe-cli inspect https://
|
|
30
|
+
npx cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
Verify:
|
|
@@ -55,7 +55,7 @@ npx playwright install chromium
|
|
|
55
55
|
Verify:
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
cssprobe-cli inspect https://
|
|
58
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json | head -5
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
JSON output = it works. `Browser not installed` = run the install command above.
|
|
@@ -68,10 +68,10 @@ JSON output = it works. `Browser not installed` = run the install command above.
|
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
70
|
# With explicit selector
|
|
71
|
-
cssprobe-cli inspect https://
|
|
71
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body
|
|
72
72
|
|
|
73
73
|
# Auto-detect root element
|
|
74
|
-
cssprobe-cli inspect https://
|
|
74
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout
|
|
75
75
|
|
|
76
76
|
# Local HTML file
|
|
77
77
|
cssprobe-cli inspect ./test.html ".container"
|
|
@@ -80,8 +80,8 @@ cssprobe-cli inspect ./test.html ".container"
|
|
|
80
80
|
### JSON Output (for programmatic consumption)
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
|
-
cssprobe-cli inspect https://
|
|
84
|
-
cssprobe-cli
|
|
83
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json
|
|
84
|
+
cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body --json | jq '.findings[] | {id, confidence, message}'
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
---
|
|
@@ -218,7 +218,7 @@ Priority (highest to lowest):
|
|
|
218
218
|
For agents that trust copy-paste:
|
|
219
219
|
|
|
220
220
|
```bash
|
|
221
|
-
npm install -g cssprobe-cli && npx playwright install chromium && cssprobe-cli inspect https://
|
|
221
|
+
npm install -g cssprobe-cli && npx playwright install chromium && cssprobe-cli inspect https://getbootstrap.com/docs/5.3/examples/checkout body
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
---
|
package/package.json
CHANGED