@logicsync/pixelprobe 0.1.0
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/LICENSE +21 -0
- package/README.md +377 -0
- package/dist/bin/pixelprobe.d.ts +3 -0
- package/dist/bin/pixelprobe.d.ts.map +1 -0
- package/dist/bin/pixelprobe.js +218 -0
- package/dist/bin/pixelprobe.js.map +1 -0
- package/dist/browser/BrowserManager.d.ts +20 -0
- package/dist/browser/BrowserManager.d.ts.map +1 -0
- package/dist/browser/BrowserManager.js +64 -0
- package/dist/browser/BrowserManager.js.map +1 -0
- package/dist/browser/ViewportManager.d.ts +15 -0
- package/dist/browser/ViewportManager.d.ts.map +1 -0
- package/dist/browser/ViewportManager.js +65 -0
- package/dist/browser/ViewportManager.js.map +1 -0
- package/dist/cli/formatter.d.ts +4 -0
- package/dist/cli/formatter.d.ts.map +1 -0
- package/dist/cli/formatter.js +107 -0
- package/dist/cli/formatter.js.map +1 -0
- package/dist/comparator/DiffAggregator.d.ts +24 -0
- package/dist/comparator/DiffAggregator.d.ts.map +1 -0
- package/dist/comparator/DiffAggregator.js +94 -0
- package/dist/comparator/DiffAggregator.js.map +1 -0
- package/dist/comparator/LayoutComparator.d.ts +8 -0
- package/dist/comparator/LayoutComparator.d.ts.map +1 -0
- package/dist/comparator/LayoutComparator.js +68 -0
- package/dist/comparator/LayoutComparator.js.map +1 -0
- package/dist/comparator/PixelComparator.d.ts +9 -0
- package/dist/comparator/PixelComparator.d.ts.map +1 -0
- package/dist/comparator/PixelComparator.js +72 -0
- package/dist/comparator/PixelComparator.js.map +1 -0
- package/dist/comparator/StyleComparator.d.ts +8 -0
- package/dist/comparator/StyleComparator.d.ts.map +1 -0
- package/dist/comparator/StyleComparator.js +119 -0
- package/dist/comparator/StyleComparator.js.map +1 -0
- package/dist/core.d.ts +23 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +211 -0
- package/dist/core.js.map +1 -0
- package/dist/extractor/ScreenshotCapturer.d.ts +20 -0
- package/dist/extractor/ScreenshotCapturer.d.ts.map +1 -0
- package/dist/extractor/ScreenshotCapturer.js +56 -0
- package/dist/extractor/ScreenshotCapturer.js.map +1 -0
- package/dist/extractor/SectionExtractor.d.ts +26 -0
- package/dist/extractor/SectionExtractor.d.ts.map +1 -0
- package/dist/extractor/SectionExtractor.js +92 -0
- package/dist/extractor/SectionExtractor.js.map +1 -0
- package/dist/extractor/StyleExtractor.d.ts +23 -0
- package/dist/extractor/StyleExtractor.d.ts.map +1 -0
- package/dist/extractor/StyleExtractor.js +88 -0
- package/dist/extractor/StyleExtractor.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +203 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/reporter/HTMLReporter.d.ts +8 -0
- package/dist/reporter/HTMLReporter.d.ts.map +1 -0
- package/dist/reporter/HTMLReporter.js +219 -0
- package/dist/reporter/HTMLReporter.js.map +1 -0
- package/dist/reporter/JSONReporter.d.ts +17 -0
- package/dist/reporter/JSONReporter.d.ts.map +1 -0
- package/dist/reporter/JSONReporter.js +77 -0
- package/dist/reporter/JSONReporter.js.map +1 -0
- package/dist/types/comparison.d.ts +133 -0
- package/dist/types/comparison.d.ts.map +1 -0
- package/dist/types/comparison.js +3 -0
- package/dist/types/comparison.js.map +1 -0
- package/dist/types/config.d.ts +138 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +151 -0
- package/dist/types/config.js.map +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LogicSync
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# pixelprobe
|
|
2
|
+
|
|
3
|
+
Responsive visual & style diff for web page sections ā CLI + MCP.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
You're rebuilding a section from a live website. You want to know: does my local build match the original? Where are the styling differences? At which breakpoints do things break?
|
|
8
|
+
|
|
9
|
+
`pixelprobe` answers this by comparing **computed styles**, **layout metrics**, and **pixel-level screenshots** between a source URL and a target URL, across multiple responsive breakpoints.
|
|
10
|
+
|
|
11
|
+
It works on any element ā full page sections, individual cards, buttons, navbars, footers, or any element you can target with a CSS selector.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g pixelprobe
|
|
17
|
+
|
|
18
|
+
# Or use directly with npx
|
|
19
|
+
npx pixelprobe compare --help
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Requires Node.js 18+. On first run, Playwright will download a Chromium binary (~110MB) if one isn't already installed. You can also install it manually:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx playwright install chromium
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Compare a hero section between production and your local build
|
|
32
|
+
pixelprobe compare \
|
|
33
|
+
--source https://example.com \
|
|
34
|
+
--target http://localhost:3000 \
|
|
35
|
+
--selector ".hero-section"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This will compare the `.hero-section` element at 4 default breakpoints (mobile, tablet, desktop, desktop-lg) and output a color-coded terminal report plus HTML and JSON reports.
|
|
39
|
+
|
|
40
|
+
## CLI Usage
|
|
41
|
+
|
|
42
|
+
### `pixelprobe compare`
|
|
43
|
+
|
|
44
|
+
The main command. Compares a section between two URLs across breakpoints.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pixelprobe compare \
|
|
48
|
+
--source <url> \
|
|
49
|
+
--target <url> \
|
|
50
|
+
--selector <css-selector> \
|
|
51
|
+
[options]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### Options
|
|
55
|
+
|
|
56
|
+
| Flag | Short | Description | Default |
|
|
57
|
+
|------|-------|-------------|---------|
|
|
58
|
+
| `--source` | `-s` | Source URL (the reference/original page) | required |
|
|
59
|
+
| `--target` | `-t` | Target URL (your local build or new version) | required |
|
|
60
|
+
| `--selector` | `-S` | CSS selector for the section on the source page | required |
|
|
61
|
+
| `--target-selector` | `-T` | CSS selector on the target page (if different from source) | same as `--selector` |
|
|
62
|
+
| `--index` | `-i` | Element index if selector matches multiple elements | `0` |
|
|
63
|
+
| `--breakpoints` | `-b` | Comma-separated breakpoint names or `WIDTHxHEIGHT` | `mobile,tablet,desktop,desktop-lg` |
|
|
64
|
+
| `--output` | `-o` | Output directory for reports | `./pixelprobe-output` |
|
|
65
|
+
| `--format` | `-f` | Output format: `json`, `html`, or `both` | `both` |
|
|
66
|
+
| `--threshold` | | Pixel comparison sensitivity (0-1, lower = stricter) | `0.1` |
|
|
67
|
+
| `--wait` | `-w` | Wait N milliseconds after page load before capturing | `0` |
|
|
68
|
+
| `--json` | | Output compact JSON to stdout (for piping to other tools) | `false` |
|
|
69
|
+
| `--headed` | | Run browser in visible (non-headless) mode | `false` |
|
|
70
|
+
| `--no-visual` | | Skip pixel-level visual comparison | `false` |
|
|
71
|
+
| `--no-styles` | | Skip computed style comparison | `false` |
|
|
72
|
+
| `--no-layout` | | Skip layout metrics comparison | `false` |
|
|
73
|
+
|
|
74
|
+
### `pixelprobe enumerate`
|
|
75
|
+
|
|
76
|
+
List all elements matching a selector on a page. Useful when your selector matches multiple elements and you need to find the right `--index`.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pixelprobe enumerate --url <url> --selector <css-selector>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Example output:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Found 3 element(s) matching ".card":
|
|
86
|
+
|
|
87
|
+
[0] <div> (320Ć200 at 32,400) ā "Pricing Plan A..."
|
|
88
|
+
[1] <div> (320Ć200 at 384,400) ā "Pricing Plan B..."
|
|
89
|
+
[2] <div> (320Ć200 at 736,400) ā "Pricing Plan C..."
|
|
90
|
+
|
|
91
|
+
Use --index N with the compare command to select a specific element.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `pixelprobe breakpoints`
|
|
95
|
+
|
|
96
|
+
List all available breakpoint presets.
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
Available breakpoint presets:
|
|
100
|
+
|
|
101
|
+
mobile-sm 320Ć568 Mobile Small
|
|
102
|
+
mobile 375Ć812 Mobile
|
|
103
|
+
mobile-lg 428Ć926 Mobile Large
|
|
104
|
+
tablet 768Ć1024 Tablet
|
|
105
|
+
tablet-lg 1024Ć1366 Tablet Large
|
|
106
|
+
desktop 1280Ć800 Desktop
|
|
107
|
+
desktop-lg 1920Ć1080 Desktop Large
|
|
108
|
+
desktop-xl 2560Ć1440 Desktop XL
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Custom breakpoints use `WIDTHxHEIGHT` format and can be mixed with presets:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
--breakpoints "mobile,tablet,1440x900,1920x1080"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Examples
|
|
118
|
+
|
|
119
|
+
### Compare a header with different selectors on each site
|
|
120
|
+
|
|
121
|
+
When source and target use different markup (e.g. WordPress vs a custom build):
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
pixelprobe compare \
|
|
125
|
+
--source "https://mysite.com" \
|
|
126
|
+
--target "http://localhost:3000" \
|
|
127
|
+
--selector "#masthead" \
|
|
128
|
+
--target-selector "header" \
|
|
129
|
+
--breakpoints "384x812,768x1024,1024x1366,1280x800,1440x900,1920x1080" \
|
|
130
|
+
--wait 3000
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Compare a specific card in a grid
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# First, find which index your card is at
|
|
137
|
+
pixelprobe enumerate --url https://mysite.com --selector ".pricing-card"
|
|
138
|
+
|
|
139
|
+
# Then compare the 2nd card (index 1)
|
|
140
|
+
pixelprobe compare \
|
|
141
|
+
--source "https://mysite.com" \
|
|
142
|
+
--target "http://localhost:3000" \
|
|
143
|
+
--selector ".pricing-card" \
|
|
144
|
+
--index 1
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Pipe JSON output to another tool
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Get machine-readable output for CI/CD
|
|
151
|
+
pixelprobe compare \
|
|
152
|
+
--source "https://mysite.com" \
|
|
153
|
+
--target "http://localhost:3000" \
|
|
154
|
+
--selector ".hero" \
|
|
155
|
+
--json | jq '.summary'
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Exit codes: `0` = no differences (pass), `1` = differences found, `2` = error.
|
|
159
|
+
|
|
160
|
+
### Compare with strict pixel matching
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
pixelprobe compare \
|
|
164
|
+
--source "https://mysite.com" \
|
|
165
|
+
--target "http://localhost:3000" \
|
|
166
|
+
--selector ".hero" \
|
|
167
|
+
--threshold 0.05
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Style-only comparison (skip screenshots)
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pixelprobe compare \
|
|
174
|
+
--source "https://mysite.com" \
|
|
175
|
+
--target "http://localhost:3000" \
|
|
176
|
+
--selector ".footer" \
|
|
177
|
+
--no-visual
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Output
|
|
181
|
+
|
|
182
|
+
Each run creates a timestamped directory inside your output folder:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
pixelprobe-output/
|
|
186
|
+
āāā run_2026-03-25_14-30-22_a1b2c3d4/
|
|
187
|
+
ā āāā comparison-a1b2c3d4.json # Full JSON report
|
|
188
|
+
ā āāā report-a1b2c3d4.html # Interactive HTML report
|
|
189
|
+
ā āāā diff-mobile.png # Visual diff per breakpoint
|
|
190
|
+
ā āāā diff-tablet.png
|
|
191
|
+
ā āāā diff-desktop.png
|
|
192
|
+
ā āāā diff-desktop-lg.png
|
|
193
|
+
āāā run_2026-03-25_15-10-45_e5f6g7h8/
|
|
194
|
+
ā āāā ...
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Console output
|
|
198
|
+
|
|
199
|
+
Color-coded terminal output with severity indicators (critical, warning, info) for each breakpoint. Shows style property diffs, layout dimension changes, and pixel diff percentages.
|
|
200
|
+
|
|
201
|
+
### HTML report
|
|
202
|
+
|
|
203
|
+
Self-contained interactive report with breakpoint tabs, visual diff images, collapsible style diff tables, and layout comparison tables. Open directly in a browser.
|
|
204
|
+
|
|
205
|
+
### JSON report
|
|
206
|
+
|
|
207
|
+
Machine-readable diff data. Includes per-breakpoint style differences, layout deviations, pixel diff metrics, and summary statistics. Useful for CI/CD integration and automated pipelines.
|
|
208
|
+
|
|
209
|
+
## What it compares
|
|
210
|
+
|
|
211
|
+
### Style Comparison
|
|
212
|
+
|
|
213
|
+
Extracts `getComputedStyle()` for layout-critical CSS properties organized into categories: layout, flexbox, grid, spacing, sizing, typography, colors, borders, effects, and positioning.
|
|
214
|
+
|
|
215
|
+
Each difference is classified by severity based on visual impact:
|
|
216
|
+
|
|
217
|
+
- **Critical** ā display, position, width, height, flex-direction, grid-template, font-size, visibility
|
|
218
|
+
- **Warning** ā margin, padding, font-family, font-weight, color, background-color, border, gap, alignment
|
|
219
|
+
- **Info** ā everything else (transitions, animations, minor effects)
|
|
220
|
+
|
|
221
|
+
### Pixel Comparison
|
|
222
|
+
|
|
223
|
+
Uses [pixelmatch](https://github.com/mapbox/pixelmatch) for pixel-level screenshot comparison. Generates diff images highlighting changed pixels in red. Handles size mismatches by padding the smaller image with magenta so dimensional differences are immediately visible.
|
|
224
|
+
|
|
225
|
+
### Layout Comparison
|
|
226
|
+
|
|
227
|
+
Compares the box model: bounding box dimensions, margin, padding, border widths, and scroll dimensions. Reports both absolute (px) and percentage deviations. Thresholds: 10px+ = critical, 3px+ = warning.
|
|
228
|
+
|
|
229
|
+
## MCP Server (for AI Agents)
|
|
230
|
+
|
|
231
|
+
`pixelprobe` includes an MCP (Model Context Protocol) server so AI agents can use it as a tool.
|
|
232
|
+
|
|
233
|
+
### Setup
|
|
234
|
+
|
|
235
|
+
Add to your Claude Desktop or Claude Code MCP config:
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"mcpServers": {
|
|
240
|
+
"pixelprobe": {
|
|
241
|
+
"command": "node",
|
|
242
|
+
"args": ["/path/to/pixelprobe/dist/mcp/server.js"]
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### MCP Tools
|
|
249
|
+
|
|
250
|
+
#### `compare_sections`
|
|
251
|
+
|
|
252
|
+
Full comparison across breakpoints. Accepts `sourceUrl`, `targetUrl`, `selector`, `targetSelector`, `breakpoints`, `pixelThreshold`, and other options. Returns structured JSON diff and saves HTML/JSON reports.
|
|
253
|
+
|
|
254
|
+
#### `capture_section`
|
|
255
|
+
|
|
256
|
+
Inspect and enumerate elements matching a selector on a page. Useful for discovering element structure before running a comparison.
|
|
257
|
+
|
|
258
|
+
#### `list_breakpoints`
|
|
259
|
+
|
|
260
|
+
Returns all available breakpoint presets with their dimensions.
|
|
261
|
+
|
|
262
|
+
## Programmatic API
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { WebSectionComparator } from 'pixelprobe';
|
|
266
|
+
|
|
267
|
+
const comparator = new WebSectionComparator({ headless: true });
|
|
268
|
+
|
|
269
|
+
const result = await comparator.compare({
|
|
270
|
+
sourceUrl: 'https://example.com',
|
|
271
|
+
targetUrl: 'http://localhost:3000',
|
|
272
|
+
selector: '.hero-section',
|
|
273
|
+
targetSelector: '.hero', // optional, if target uses different markup
|
|
274
|
+
breakpoints: ['mobile', 'tablet', 'desktop'],
|
|
275
|
+
pixelThreshold: 0.1,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
console.log(result.summary);
|
|
279
|
+
// {
|
|
280
|
+
// overallSeverity: 'warning',
|
|
281
|
+
// totalBreakpoints: 3,
|
|
282
|
+
// breakpointsWithDifferences: 2,
|
|
283
|
+
// totalStyleDifferences: 12,
|
|
284
|
+
// totalLayoutDifferences: 4,
|
|
285
|
+
// averagePixelDiff: 3.5,
|
|
286
|
+
// worstBreakpoint: 'mobile'
|
|
287
|
+
// }
|
|
288
|
+
|
|
289
|
+
// Enumerate elements before comparing
|
|
290
|
+
const elements = await comparator.enumerate('https://example.com', '.card');
|
|
291
|
+
// [{ index: 0, tagName: 'div', textPreview: '...', boundingBox: {...} }, ...]
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Tips
|
|
295
|
+
|
|
296
|
+
- **Use `--wait`** for sites with animations, lazy-loading, or web fonts. 2000-3000ms is usually enough.
|
|
297
|
+
- **Use `--headed`** to watch the browser and debug selector issues.
|
|
298
|
+
- **Use `--target-selector`** when source and target have different markup (e.g. WordPress vs a custom React build).
|
|
299
|
+
- **Use `enumerate`** first when you're unsure which element your selector is matching.
|
|
300
|
+
- **Use `--no-visual`** to speed things up if you only care about computed style differences.
|
|
301
|
+
- **Custom breakpoints** let you test at the exact widths your design uses: `--breakpoints "375x812,768x1024,1440x900"`.
|
|
302
|
+
|
|
303
|
+
## Contributing
|
|
304
|
+
|
|
305
|
+
Contributions are welcome! Here's how to get started:
|
|
306
|
+
|
|
307
|
+
### Setup
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
git clone https://github.com/user/pixelprobe.git
|
|
311
|
+
cd pixelprobe
|
|
312
|
+
npm install
|
|
313
|
+
npx playwright install chromium
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Development
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
# Type-check
|
|
320
|
+
npx tsc --noEmit
|
|
321
|
+
|
|
322
|
+
# Build
|
|
323
|
+
npx tsc
|
|
324
|
+
|
|
325
|
+
# Run CLI during development
|
|
326
|
+
node dist/bin/pixelprobe.js compare --help
|
|
327
|
+
|
|
328
|
+
# Run tests
|
|
329
|
+
npm test
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Project Structure
|
|
333
|
+
|
|
334
|
+
```
|
|
335
|
+
src/
|
|
336
|
+
āāā types/ # TypeScript interfaces (config, comparison results)
|
|
337
|
+
āāā browser/ # Playwright browser lifecycle and viewport management
|
|
338
|
+
āāā extractor/ # Section selection, style extraction, screenshots
|
|
339
|
+
āāā comparator/ # Style diff, pixel diff, layout diff, aggregation
|
|
340
|
+
āāā reporter/ # JSON and HTML report generation
|
|
341
|
+
āāā cli/ # Terminal output formatting
|
|
342
|
+
āāā mcp/ # MCP server (tools and handlers)
|
|
343
|
+
āāā bin/ # CLI entry point
|
|
344
|
+
āāā core.ts # Main orchestrator
|
|
345
|
+
āāā index.ts # Public API exports
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Guidelines
|
|
349
|
+
|
|
350
|
+
- Keep it dependency-light. The core should only need Playwright and pixelmatch.
|
|
351
|
+
- All comparison logic lives in `src/comparator/`. Reporters just format what comparators produce.
|
|
352
|
+
- Add types to `src/types/` before implementing. The types are the contract.
|
|
353
|
+
- Test with real URLs when possible ā CSS rendering has endless edge cases.
|
|
354
|
+
- CLI and MCP are thin wrappers over `core.ts`. Don't put business logic in them.
|
|
355
|
+
|
|
356
|
+
### Reporting Issues
|
|
357
|
+
|
|
358
|
+
When filing a bug, please include:
|
|
359
|
+
|
|
360
|
+
- The full command you ran
|
|
361
|
+
- The error message or unexpected output
|
|
362
|
+
- Your Node.js version (`node --version`)
|
|
363
|
+
- Your OS
|
|
364
|
+
|
|
365
|
+
## Roadmap
|
|
366
|
+
|
|
367
|
+
- [ ] Pseudo-state comparison (hover, focus, active)
|
|
368
|
+
- [ ] Watch mode for live development
|
|
369
|
+
- [ ] CI/CD integration examples (GitHub Actions, GitLab CI)
|
|
370
|
+
- [ ] Side-by-side source/target screenshots in HTML report
|
|
371
|
+
- [ ] Config file support (`.pixelproberc.json`)
|
|
372
|
+
- [ ] Accessibility attribute comparison
|
|
373
|
+
- [ ] Performance metrics comparison (LCP, CLS)
|
|
374
|
+
|
|
375
|
+
## License
|
|
376
|
+
|
|
377
|
+
MIT License ā see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pixelprobe.d.ts","sourceRoot":"","sources":["../../src/bin/pixelprobe.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import yargs from "yargs";
|
|
4
|
+
import { hideBin } from "yargs/helpers";
|
|
5
|
+
import { WebSectionComparator } from "../core.js";
|
|
6
|
+
import { JSONReporter } from "../reporter/JSONReporter.js";
|
|
7
|
+
import { HTMLReporter } from "../reporter/HTMLReporter.js";
|
|
8
|
+
import { formatResult } from "../cli/formatter.js";
|
|
9
|
+
import { PRESET_BREAKPOINTS } from "../types/config.js";
|
|
10
|
+
const cli = yargs(hideBin(process.argv))
|
|
11
|
+
.scriptName("pixelprobe")
|
|
12
|
+
.usage("$0 <command> [options]")
|
|
13
|
+
.command("compare", "Compare a section between source and target URLs across breakpoints", (y) => y
|
|
14
|
+
.option("source", {
|
|
15
|
+
alias: "s",
|
|
16
|
+
type: "string",
|
|
17
|
+
describe: "Source URL (the reference page)",
|
|
18
|
+
demandOption: true,
|
|
19
|
+
})
|
|
20
|
+
.option("target", {
|
|
21
|
+
alias: "t",
|
|
22
|
+
type: "string",
|
|
23
|
+
describe: "Target URL (your local build)",
|
|
24
|
+
demandOption: true,
|
|
25
|
+
})
|
|
26
|
+
.option("selector", {
|
|
27
|
+
alias: "S",
|
|
28
|
+
type: "string",
|
|
29
|
+
describe: "CSS selector for the section on the source page",
|
|
30
|
+
demandOption: true,
|
|
31
|
+
})
|
|
32
|
+
.option("target-selector", {
|
|
33
|
+
alias: "T",
|
|
34
|
+
type: "string",
|
|
35
|
+
describe: "CSS selector for the section on the target page (if different from source). Falls back to --selector.",
|
|
36
|
+
})
|
|
37
|
+
.option("index", {
|
|
38
|
+
alias: "i",
|
|
39
|
+
type: "number",
|
|
40
|
+
describe: "Element index if selector matches multiple elements",
|
|
41
|
+
default: 0,
|
|
42
|
+
})
|
|
43
|
+
.option("breakpoints", {
|
|
44
|
+
alias: "b",
|
|
45
|
+
type: "string",
|
|
46
|
+
describe: 'Comma-separated breakpoint names or WIDTHxHEIGHT (e.g. "mobile,tablet,1440x900")',
|
|
47
|
+
default: "mobile,tablet,desktop,desktop-lg",
|
|
48
|
+
})
|
|
49
|
+
.option("output", {
|
|
50
|
+
alias: "o",
|
|
51
|
+
type: "string",
|
|
52
|
+
describe: "Output directory for reports and artifacts",
|
|
53
|
+
default: "./pixelprobe-output",
|
|
54
|
+
})
|
|
55
|
+
.option("format", {
|
|
56
|
+
alias: "f",
|
|
57
|
+
type: "string",
|
|
58
|
+
describe: 'Output formats: "json", "html", "both"',
|
|
59
|
+
default: "both",
|
|
60
|
+
})
|
|
61
|
+
.option("threshold", {
|
|
62
|
+
type: "number",
|
|
63
|
+
describe: "Pixel comparison threshold (0-1, lower = stricter)",
|
|
64
|
+
default: 0.1,
|
|
65
|
+
})
|
|
66
|
+
.option("no-visual", {
|
|
67
|
+
type: "boolean",
|
|
68
|
+
describe: "Skip visual (pixel) comparison",
|
|
69
|
+
default: false,
|
|
70
|
+
})
|
|
71
|
+
.option("no-styles", {
|
|
72
|
+
type: "boolean",
|
|
73
|
+
describe: "Skip computed style comparison",
|
|
74
|
+
default: false,
|
|
75
|
+
})
|
|
76
|
+
.option("no-layout", {
|
|
77
|
+
type: "boolean",
|
|
78
|
+
describe: "Skip layout metrics comparison",
|
|
79
|
+
default: false,
|
|
80
|
+
})
|
|
81
|
+
.option("wait", {
|
|
82
|
+
alias: "w",
|
|
83
|
+
type: "number",
|
|
84
|
+
describe: "Wait N ms after page load before capturing",
|
|
85
|
+
default: 0,
|
|
86
|
+
})
|
|
87
|
+
.option("headed", {
|
|
88
|
+
type: "boolean",
|
|
89
|
+
describe: "Run browser in headed mode (visible)",
|
|
90
|
+
default: false,
|
|
91
|
+
})
|
|
92
|
+
.option("json", {
|
|
93
|
+
type: "boolean",
|
|
94
|
+
describe: "Output compact JSON to stdout (for piping)",
|
|
95
|
+
default: false,
|
|
96
|
+
}), async (argv) => {
|
|
97
|
+
const breakpoints = argv.breakpoints.split(",").map((s) => s.trim());
|
|
98
|
+
const comparator = new WebSectionComparator({
|
|
99
|
+
headless: !argv.headed,
|
|
100
|
+
timeout: 30000,
|
|
101
|
+
});
|
|
102
|
+
// Progress display
|
|
103
|
+
const spinnerFrames = ["ā ", "ā ", "ā ¹", "ā ø", "ā ¼", "ā “", "ā ¦", "ā §", "ā ", "ā "];
|
|
104
|
+
let spinnerIdx = 0;
|
|
105
|
+
let spinnerInterval;
|
|
106
|
+
if (!argv.json) {
|
|
107
|
+
spinnerInterval = setInterval(() => {
|
|
108
|
+
spinnerIdx = (spinnerIdx + 1) % spinnerFrames.length;
|
|
109
|
+
}, 80);
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const result = await comparator.compare({
|
|
113
|
+
sourceUrl: argv.source,
|
|
114
|
+
targetUrl: argv.target,
|
|
115
|
+
selector: argv.selector,
|
|
116
|
+
targetSelector: argv["target-selector"],
|
|
117
|
+
elementIndex: argv.index,
|
|
118
|
+
breakpoints,
|
|
119
|
+
pixelThreshold: argv.threshold,
|
|
120
|
+
includeVisual: !argv["no-visual"],
|
|
121
|
+
includeStyles: !argv["no-styles"],
|
|
122
|
+
includeLayout: !argv["no-layout"],
|
|
123
|
+
waitForTimeout: argv.wait,
|
|
124
|
+
}, !argv.json
|
|
125
|
+
? (event) => {
|
|
126
|
+
process.stderr.write(`\r${spinnerFrames[spinnerIdx]} ${event.message} (${Math.round(event.progress)}%) `);
|
|
127
|
+
}
|
|
128
|
+
: undefined);
|
|
129
|
+
if (spinnerInterval)
|
|
130
|
+
clearInterval(spinnerInterval);
|
|
131
|
+
// JSON-only mode (for piping)
|
|
132
|
+
if (argv.json) {
|
|
133
|
+
console.log(JSON.stringify(JSONReporter.toCompactSummary(result), null, 2));
|
|
134
|
+
process.exit(result.summary.overallSeverity === "pass" ? 0 : 1);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// Clear spinner line
|
|
138
|
+
process.stderr.write("\r" + " ".repeat(80) + "\r");
|
|
139
|
+
// Console output
|
|
140
|
+
console.log(formatResult(result));
|
|
141
|
+
// Create a timestamped run directory inside the output dir
|
|
142
|
+
const timestamp = new Date()
|
|
143
|
+
.toISOString()
|
|
144
|
+
.replace(/[:.]/g, "-")
|
|
145
|
+
.replace("T", "_")
|
|
146
|
+
.slice(0, 19);
|
|
147
|
+
const runDir = join(argv.output, `run_${timestamp}_${result.id}`);
|
|
148
|
+
// Generate reports into the run directory
|
|
149
|
+
const format = argv.format;
|
|
150
|
+
if (format === "json" || format === "both") {
|
|
151
|
+
const jsonPath = await JSONReporter.generate(result, runDir);
|
|
152
|
+
console.log(` š JSON report: ${jsonPath}`);
|
|
153
|
+
}
|
|
154
|
+
if (format === "html" || format === "both") {
|
|
155
|
+
const htmlPath = await HTMLReporter.generate(result, runDir);
|
|
156
|
+
console.log(` š HTML report: ${htmlPath}`);
|
|
157
|
+
}
|
|
158
|
+
console.log("");
|
|
159
|
+
// Exit with non-zero if differences found
|
|
160
|
+
process.exit(result.summary.overallSeverity === "pass" ? 0 : 1);
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
if (spinnerInterval)
|
|
164
|
+
clearInterval(spinnerInterval);
|
|
165
|
+
process.stderr.write("\r" + " ".repeat(80) + "\r");
|
|
166
|
+
console.error(`\nā Error: ${err.message}`);
|
|
167
|
+
process.exit(2);
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
.command("enumerate", "List all elements matching a selector on a page", (y) => y
|
|
171
|
+
.option("url", {
|
|
172
|
+
alias: "u",
|
|
173
|
+
type: "string",
|
|
174
|
+
describe: "URL to inspect",
|
|
175
|
+
demandOption: true,
|
|
176
|
+
})
|
|
177
|
+
.option("selector", {
|
|
178
|
+
alias: "S",
|
|
179
|
+
type: "string",
|
|
180
|
+
describe: "CSS selector",
|
|
181
|
+
demandOption: true,
|
|
182
|
+
}), async (argv) => {
|
|
183
|
+
const comparator = new WebSectionComparator({ headless: true });
|
|
184
|
+
try {
|
|
185
|
+
const elements = await comparator.enumerate(argv.url, argv.selector);
|
|
186
|
+
if (elements.length === 0) {
|
|
187
|
+
console.log(`No elements found matching "${argv.selector}"`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
console.log(`\nFound ${elements.length} element(s) matching "${argv.selector}":\n`);
|
|
192
|
+
for (const el of elements) {
|
|
193
|
+
const box = el.boundingBox;
|
|
194
|
+
console.log(` [${el.index}] <${el.tagName}> (${box.width}Ć${box.height} at ${box.x},${box.y})`);
|
|
195
|
+
if (el.textPreview) {
|
|
196
|
+
console.log(` "${el.textPreview}"`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
console.log(`\nUse --index N with the compare command to select a specific element.`);
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
console.error(`ā Error: ${err.message}`);
|
|
203
|
+
process.exit(2);
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
.command("breakpoints", "List available breakpoint presets", () => { }, () => {
|
|
207
|
+
console.log("\nAvailable breakpoint presets:\n");
|
|
208
|
+
for (const [name, bp] of Object.entries(PRESET_BREAKPOINTS)) {
|
|
209
|
+
console.log(` ${name.padEnd(14)} ${bp.width}Ć${bp.height} ${bp.label}`);
|
|
210
|
+
}
|
|
211
|
+
console.log(`\nYou can also use custom breakpoints in WIDTHxHEIGHT format (e.g. 1440x900).`);
|
|
212
|
+
})
|
|
213
|
+
.demandCommand(1, "Please specify a command")
|
|
214
|
+
.help()
|
|
215
|
+
.version("0.1.0")
|
|
216
|
+
.strict();
|
|
217
|
+
cli.parse();
|
|
218
|
+
//# sourceMappingURL=pixelprobe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pixelprobe.js","sourceRoot":"","sources":["../../src/bin/pixelprobe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Page } from "playwright";
|
|
2
|
+
import type { Breakpoint } from "../types/config.js";
|
|
3
|
+
export interface BrowserManagerOptions {
|
|
4
|
+
headless?: boolean;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class BrowserManager {
|
|
8
|
+
private browser;
|
|
9
|
+
private options;
|
|
10
|
+
constructor(options?: BrowserManagerOptions);
|
|
11
|
+
launch(): Promise<void>;
|
|
12
|
+
createPage(breakpoint: Breakpoint): Promise<Page>;
|
|
13
|
+
navigateAndWait(page: Page, url: string, options?: {
|
|
14
|
+
waitForSelector?: string;
|
|
15
|
+
waitForTimeout?: number;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
get isLaunched(): boolean;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=BrowserManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserManager.d.ts","sourceRoot":"","sources":["../../src/browser/BrowserManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAAkC;gBAErC,OAAO,GAAE,qBAA0B;IAOzC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAOvB,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBjD,eAAe,CACnB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;QACP,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,CAAC;KACpB,GACL,OAAO,CAAC,IAAI,CAAC;IAwBV,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,IAAI,UAAU,IAAI,OAAO,CAExB;CACF"}
|