@juangadm/pre-post 0.3.0 → 1.0.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.
Files changed (125) hide show
  1. package/README.md +102 -240
  2. package/dist/bin/cli.js +200 -454
  3. package/dist/bin/cli.js.map +1 -1
  4. package/dist/browser.d.ts +42 -27
  5. package/dist/browser.d.ts.map +1 -1
  6. package/dist/browser.js +358 -105
  7. package/dist/browser.js.map +1 -1
  8. package/dist/capture.d.ts +1 -6
  9. package/dist/capture.d.ts.map +1 -1
  10. package/dist/capture.js +12 -36
  11. package/dist/capture.js.map +1 -1
  12. package/dist/commands/compare.d.ts +18 -0
  13. package/dist/commands/compare.d.ts.map +1 -0
  14. package/dist/commands/compare.js +64 -0
  15. package/dist/commands/compare.js.map +1 -0
  16. package/dist/commands/detect.d.ts +20 -0
  17. package/dist/commands/detect.d.ts.map +1 -0
  18. package/dist/commands/detect.js +19 -0
  19. package/dist/commands/detect.js.map +1 -0
  20. package/dist/commands/doctor.d.ts +10 -0
  21. package/dist/commands/doctor.d.ts.map +1 -0
  22. package/dist/commands/doctor.js +38 -0
  23. package/dist/commands/doctor.js.map +1 -0
  24. package/dist/commands/login.d.ts +6 -0
  25. package/dist/commands/login.d.ts.map +1 -0
  26. package/dist/commands/login.js +34 -0
  27. package/dist/commands/login.js.map +1 -0
  28. package/dist/commands/pr.d.ts +28 -0
  29. package/dist/commands/pr.d.ts.map +1 -0
  30. package/dist/commands/pr.js +159 -0
  31. package/dist/commands/pr.js.map +1 -0
  32. package/dist/commands/prune.d.ts +10 -0
  33. package/dist/commands/prune.d.ts.map +1 -0
  34. package/dist/commands/prune.js +13 -0
  35. package/dist/commands/prune.js.map +1 -0
  36. package/dist/config.d.ts +36 -0
  37. package/dist/config.d.ts.map +1 -0
  38. package/dist/config.js +60 -0
  39. package/dist/config.js.map +1 -0
  40. package/dist/diff-pool.d.ts +17 -0
  41. package/dist/diff-pool.d.ts.map +1 -0
  42. package/dist/diff-pool.js +89 -0
  43. package/dist/diff-pool.js.map +1 -0
  44. package/dist/diff-worker.d.ts +29 -0
  45. package/dist/diff-worker.d.ts.map +1 -0
  46. package/dist/diff-worker.js +38 -0
  47. package/dist/diff-worker.js.map +1 -0
  48. package/dist/diff.d.ts +37 -0
  49. package/dist/diff.d.ts.map +1 -0
  50. package/dist/diff.js +171 -0
  51. package/dist/diff.js.map +1 -0
  52. package/dist/doctor.d.ts +38 -0
  53. package/dist/doctor.d.ts.map +1 -0
  54. package/dist/doctor.js +72 -0
  55. package/dist/doctor.js.map +1 -0
  56. package/dist/errors.d.ts +38 -0
  57. package/dist/errors.d.ts.map +1 -0
  58. package/dist/errors.js +59 -0
  59. package/dist/errors.js.map +1 -0
  60. package/dist/git.d.ts +23 -0
  61. package/dist/git.d.ts.map +1 -0
  62. package/dist/git.js +86 -0
  63. package/dist/git.js.map +1 -0
  64. package/dist/github.d.ts +73 -0
  65. package/dist/github.d.ts.map +1 -0
  66. package/dist/github.js +240 -0
  67. package/dist/github.js.map +1 -0
  68. package/dist/index.d.ts +22 -23
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +17 -67
  71. package/dist/index.js.map +1 -1
  72. package/dist/pkg.d.ts +8 -0
  73. package/dist/pkg.d.ts.map +1 -0
  74. package/dist/pkg.js +35 -0
  75. package/dist/pkg.js.map +1 -0
  76. package/dist/report.d.ts +20 -0
  77. package/dist/report.d.ts.map +1 -0
  78. package/dist/report.js +107 -0
  79. package/dist/report.js.map +1 -0
  80. package/dist/routes/imports.d.ts +46 -0
  81. package/dist/routes/imports.d.ts.map +1 -0
  82. package/dist/routes/imports.js +208 -0
  83. package/dist/routes/imports.js.map +1 -0
  84. package/dist/routes/vite.d.ts +15 -0
  85. package/dist/routes/vite.d.ts.map +1 -0
  86. package/dist/routes/vite.js +130 -0
  87. package/dist/routes/vite.js.map +1 -0
  88. package/dist/routes.d.ts +41 -14
  89. package/dist/routes.d.ts.map +1 -1
  90. package/dist/routes.js +271 -141
  91. package/dist/routes.js.map +1 -1
  92. package/dist/run.d.ts +36 -0
  93. package/dist/run.d.ts.map +1 -0
  94. package/dist/run.js +128 -0
  95. package/dist/run.js.map +1 -0
  96. package/dist/sessions.d.ts +50 -0
  97. package/dist/sessions.d.ts.map +1 -0
  98. package/dist/sessions.js +74 -0
  99. package/dist/sessions.js.map +1 -0
  100. package/dist/types.d.ts +118 -69
  101. package/dist/types.d.ts.map +1 -1
  102. package/dist/types.js +1 -0
  103. package/dist/types.js.map +1 -1
  104. package/dist/viewport.d.ts +6 -1
  105. package/dist/viewport.d.ts.map +1 -1
  106. package/dist/viewport.js +13 -7
  107. package/dist/viewport.js.map +1 -1
  108. package/package.json +21 -14
  109. package/skill/SKILL.md +31 -229
  110. package/dist/clipboard.d.ts +0 -9
  111. package/dist/clipboard.d.ts.map +0 -1
  112. package/dist/clipboard.js +0 -26
  113. package/dist/clipboard.js.map +0 -1
  114. package/dist/upload.d.ts +0 -39
  115. package/dist/upload.d.ts.map +0 -1
  116. package/dist/upload.js +0 -159
  117. package/dist/upload.js.map +0 -1
  118. package/dist/video.d.ts +0 -19
  119. package/dist/video.d.ts.map +0 -1
  120. package/dist/video.js +0 -263
  121. package/dist/video.js.map +0 -1
  122. package/skill/scripts/adapters/0x0st.sh +0 -36
  123. package/skill/scripts/adapters/blob.sh +0 -55
  124. package/skill/scripts/adapters/git-native.sh +0 -51
  125. package/skill/scripts/upload-and-copy.sh +0 -230
package/README.md CHANGED
@@ -1,273 +1,135 @@
1
1
  # pre-post
2
2
 
3
- Visual diff tool that captures pre/post screenshots for PRs. Use it as a Claude Code skill for automatic visual documentation, or run it directly from the CLI.
4
-
5
- > Originally forked from [before-and-after](https://github.com/vercel-labs/before-and-after) by [James Clements](https://github.com/jamesclement) / Vercel Labs.
6
-
7
- ## What Changed from the Original
8
-
9
- | Area | before-and-after | pre-post |
10
- |------|-----------------|----------|
11
- | Browser engine | `agent-browser` (Vercel-proprietary) | **Playwright** (direct dependency) |
12
- | Screenshot quality | 1x | **2x retina** (`deviceScaleFactor: 2`) |
13
- | Route detection | Manual | **Automatic** from `git diff` (Next.js App/Pages Router, generic fallback) |
14
- | Responsive capture | Single viewport | **Desktop + mobile** per route (`--responsive`) |
15
- | CLI subcommands | URL pairs only | `detect`, `compare`, `run` subcommands |
16
- | Skill orchestration | Basic capture | Full workflow: route detection, Claude refinement, user approval, PR posting |
17
- | Font/animation handling | None | Waits for `document.fonts.ready`, disables CSS animations |
18
-
19
- ## How It Works
20
-
21
- ```mermaid
22
- flowchart TD
23
- A[pre-post] --> B{Mode?}
24
-
25
- B -->|Manual| C["pre-post url1 url2"]
26
- B -->|Subcommand| D{"detect | compare | run"}
27
- B -->|Claude Code Skill| E["/pre-post"]
28
-
29
- D -->|detect| F["Git: diff, staged, unstaged, untracked"]
30
- D -->|compare| J
31
- D -->|run| F
32
-
33
- F --> G{Detect framework}
34
- G -->|Next.js App Router| H[Map files routes]
35
- G -->|Next.js Pages Router| H
36
- G -->|Generic| H
37
- H --> I{Routes found?}
38
- I -->|Yes| J[Route list with confidence]
39
- I -->|No| J2["Default to /"]
40
- J2 --> J
41
-
42
- E --> E1[Pre-flight checks]
43
- E1 --> F
44
- E1 --> K[Claude refines routes]
45
- K --> K1[User approves routes]
46
- K1 --> J
47
-
48
- C --> L[Playwright]
49
- J --> L
50
-
51
- L --> M{Launch Chromium}
52
- M -->|"PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH"| M1[Custom path — fail hard if invalid]
53
- M -->|Auto-detect| M2[System Chrome → Bundled → Cached]
54
- M1 --> P[Navigate + wait for network idle]
55
- M2 --> P
56
-
57
- P --> Q[Disable CSS animations]
58
- Q --> R[Wait for document.fonts.ready]
59
- R --> S[Take 2x retina screenshot]
60
-
61
- S --> T[Save to ~/Downloads]
62
- T --> T1{--markdown?}
63
- T1 -->|No| U[Done]
64
- T1 -->|Yes| V{Upload method}
65
- V -->|Default| W["git-native: commit to .pre-post/"]
66
- V -->|--upload-url| Y["HTTP: 0x0.st / Vercel Blob / PUT"]
67
- W --> X[Build blob+SHA URL]
68
- Y --> X
69
- X --> Z[Markdown table]
70
-
71
- Z --> Z1{Skill mode?}
72
- Z1 -->|Yes| Z2[User approves screenshots]
73
- Z2 --> Z3["gh pr edit — append to PR body"]
74
- Z1 -->|No| Z4[Copy to clipboard]
75
-
76
- style A fill:#4f46e5,color:#fff
77
- style L fill:#2563eb,color:#fff
78
- style S fill:#059669,color:#fff
79
- ```
80
-
81
- ## Prerequisites
82
-
83
- - **Node.js** 18+
84
- - **Chromium** — install once via Playwright:
85
-
86
- ```bash
87
- npx playwright install chromium
88
- ```
89
-
90
- ## CI / Sandboxed Environments
91
-
92
- pre-post needs a Chromium binary. In restricted environments where `npx playwright install chromium` fails (CDN blocked):
93
-
94
- ```bash
95
- # Point to a pre-installed Chrome/Chromium binary
96
- export PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/path/to/chrome
97
-
98
- # This is treated as an explicit override — pre-post will fail with a
99
- # clear error if the path is wrong, rather than silently falling back.
100
- ```
101
-
102
- When no custom path is set, pre-post auto-detects in order: system Chrome, bundled Playwright Chromium, then any builds in `~/.cache/ms-playwright/`.
103
-
104
- If no browser is available at all, use image-only mode:
105
-
106
- ```bash
107
- pre-post before.png after.png --markdown
108
- ```
109
-
110
- **Proxy URLs**: If your git remote uses a proxy (e.g., `http://proxy@host/git/owner/repo`), set the repo explicitly:
111
-
112
- ```bash
113
- export GH_REPO=owner/repo
114
- ```
115
-
116
- **Google Fonts**: Container egress proxies typically block `fonts.googleapis.com`.
117
- Screenshots will render with system font fallbacks. This is cosmetic only —
118
- `document.fonts.ready` still resolves and layout is preserved.
3
+ Before/after screenshots for pull requests. One command detects the routes your branch
4
+ changed, captures them on production ("Pre") and on your dev server ("Post"), pixel-diffs
5
+ them, uploads the images to GitHub, and posts a single comment on the PR that a reviewer
6
+ can judge at a glance.
7
+
8
+ > Originally forked from [before-and-after](https://github.com/vercel-labs/before-and-after) by James Clements / Vercel Labs.
9
+
10
+ ```
11
+ $ npx -y @juangadm/pre-post@latest pr
12
+
13
+ Routes (nextjs-app, 41ms): /, /pricing
14
+ / medium src/app/page.tsx imports src/components/ui/button.tsx (2 hops)
15
+ /pricing medium src/app/pricing/page.tsx imports src/components/ui/button.tsx (2 hops)
16
+ Capturing 8 screenshots (2 route(s) × 2 viewport(s)) ...
17
+ changed /pricing @ mobile (1.42%, 1811ms)
18
+ changed /pricing @ desktop (0.64%, 2036ms)
19
+ same / @ mobile (0.00%, 1990ms)
20
+ same / @ desktop (0.00%, 2211ms)
21
+ Publishing 10 image(s) to acme/web@pre-post-assets ...
22
+ Updated PR comment: https://github.com/acme/web/pull/42#issuecomment-1
23
+ pre-post · PR #42 · 2 route(s) · 2 viewport(s) · 6.8s
24
+ / desktop no change
25
+ / mobile no change
26
+ /pricing desktop 0.64% changed
27
+ /pricing mobile 1.4% changed
28
+ Comment: https://github.com/acme/web/pull/42#issuecomment-1
29
+ ```
30
+
31
+ ## How it works
32
+
33
+ 1. **Routes.** Diffs the branch against the merge base with `main`, then follows the import
34
+ graph: a change to `components/ui/button.tsx` marks every page that imports it. Next.js
35
+ App Router and Pages Router, Vite apps (React Router, file-based `src/pages`), and a
36
+ generic fallback. Monorepos are handled by picking the app that owns the changed files.
37
+ 2. **Capture.** Playwright + Chromium headless shell. Fixed clock, reduced motion,
38
+ animations finished, caret hidden, fonts and images settled, layout stable across frames,
39
+ lazy content primed. 2x device scale, full page (capped at 2400 CSS px), desktop + mobile.
40
+ All routes and viewports run concurrently.
41
+ 3. **Diff.** Pure-JS pixel comparison in worker threads. Reports the percentage changed,
42
+ the bounding box, a red-highlight image, and a tight crop of the changed region.
43
+ 4. **Publish.** Images go to a `pre-post-assets` branch in the same repository via the GitHub
44
+ API, as one commit per run. Nothing is committed to the PR branch, no CI is triggered,
45
+ and the blob URLs render on private repos. `pre-post prune` removes images for PRs
46
+ closed more than 90 days ago.
47
+ 5. **Comment.** One sticky comment per PR, updated in place on every run. Changed routes show
48
+ a Pre/Post crop with the full page and diff collapsed underneath; unchanged routes fold
49
+ into a single line.
119
50
 
120
51
  ## Install
121
52
 
122
- ```bash
123
- npm install -D @juangadm/pre-post
124
- ```
125
-
126
- ## Basic Use
53
+ Nothing to install. `npx -y @juangadm/pre-post@latest pr` downloads the CLI and, on first
54
+ use, the Chromium headless shell (~80 MB). You need Node 20+ and a GitHub token: either
55
+ `gh auth login` or `GH_TOKEN`.
127
56
 
128
- ### As a Claude Code Skill (recommended)
129
-
130
- After making visual UI changes, say `/pre-post` or "take pre and post screenshots". Claude will:
131
-
132
- 1. Detect affected routes from your git diff
133
- 2. Propose routes for your approval
134
- 3. Capture desktop + mobile screenshots (production vs localhost)
135
- 4. Show you the screenshots for approval
136
- 5. Upload and append markdown to your PR
137
-
138
- ### From the CLI
139
-
140
- Capture any two URLs:
57
+ As a Claude Code skill:
141
58
 
142
59
  ```bash
143
- pre-post site.com localhost:3000
60
+ npx skills add juangadm/pre-post -y
144
61
  ```
145
62
 
146
- Use existing images:
63
+ Then say `/pre-post` after making UI changes.
147
64
 
148
- ```bash
149
- pre-post before.png after.png
150
- ```
151
-
152
- ## CLI Subcommands
153
-
154
- ### `detect` -- Route Detection
155
-
156
- Detect affected routes from git changes:
157
-
158
- ```bash
159
- pre-post detect # Auto-detect framework
160
- pre-post detect --framework nextjs-app # Force framework
161
- ```
162
-
163
- Outputs JSON with route paths, confidence levels, and source files.
164
-
165
- ### `compare` -- URL Comparison
166
-
167
- Compare pre/post states across routes:
168
-
169
- ```bash
170
- pre-post compare --before-base https://prod.com --after-base http://localhost:3000
171
- pre-post compare --before-base URL --after-base URL --routes /dashboard,/settings
172
- pre-post compare --before-base URL --after-base URL --responsive # Desktop + mobile
173
- ```
174
-
175
- ### `run` -- Full Auto
176
-
177
- Combines `detect` + `compare`:
178
-
179
- ```bash
180
- pre-post run --before-base https://prod.com --after-base http://localhost:3000
181
- ```
182
-
183
- ## Options
184
-
185
- Capture a specific element using a CSS selector:
186
-
187
- ```bash
188
- pre-post url1 url2 ".hero"
189
- ```
190
-
191
- Use different selectors for pre and post:
65
+ ## Usage
192
66
 
193
67
  ```bash
194
- pre-post url1 url2 ".old" ".new"
195
- ```
68
+ pre-post pr # everything, on the current branch's PR
69
+ pre-post pr --before https://acme.com # first run in a repo (saved to .pre-post.json)
70
+ pre-post pr --routes /pricing,/docs # explicit routes
71
+ pre-post pr --viewports desktop,1440x900 # custom viewports
72
+ pre-post pr --dry-run # capture + diff locally, post nothing
73
+ pre-post pr --json # machine-readable output
196
74
 
197
- Capture at mobile (375x812), tablet (768x1024), or custom viewport:
198
-
199
- ```bash
200
- pre-post url1 url2 --mobile
201
- pre-post url1 url2 --size 1920x1080
75
+ pre-post https://acme.com http://localhost:3000 --routes /pricing # ad-hoc comparison
76
+ pre-post before.png after.png # diff two images
77
+ pre-post detect # which routes does this branch touch?
78
+ pre-post login https://staging.acme.com # sign in once; the session is reused
79
+ pre-post prune --days 90 # clean up the assets branch
80
+ pre-post doctor # browser, token, dev server, config
202
81
  ```
203
82
 
204
- Capture the entire scrollable page:
83
+ When something needs a human, the CLI exits with code 3 and one sentence saying what to do
84
+ (log in, start the dev server, pass `--before`). Re-running picks up where it left off.
205
85
 
206
- ```bash
207
- pre-post url1 url2 --full
208
- ```
86
+ ## Configuration
209
87
 
210
- Output a markdown table for PR descriptions:
88
+ Optional `.pre-post.json` in the repo root:
211
89
 
212
- ```bash
213
- pre-post url1 url2 --markdown
90
+ ```json
91
+ {
92
+ "before": "https://acme.com",
93
+ "routes": ["/"],
94
+ "samples": { "/blog/[slug]": "/blog/hello-world" },
95
+ "viewports": ["desktop", "mobile"],
96
+ "fullPage": true,
97
+ "maxHeight": 2400,
98
+ "scale": 2,
99
+ "threshold": 0.001,
100
+ "minChangedPixels": 40,
101
+ "maxRoutes": 6,
102
+ "ignore": ["apps/docs"],
103
+ "headers": {},
104
+ "assetsBranch": "pre-post-assets"
105
+ }
214
106
  ```
215
107
 
216
- Save to a custom location:
108
+ Environment:
217
109
 
218
- ```bash
219
- pre-post url1 url2 --output ./screenshots
220
- ```
110
+ | Variable | Purpose |
111
+ |---|---|
112
+ | `GH_TOKEN` / `GITHUB_TOKEN` | GitHub token (default: `gh auth token`) |
113
+ | `VERCEL_AUTOMATION_BYPASS_SECRET` | Bypass Vercel Deployment Protection on the production URL |
114
+ | `PRE_POST_CONCURRENCY` | Parallel pages (default 6) |
115
+ | `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` | Use a specific Chromium binary |
116
+ | `GH_REPO` | `owner/repo` when the remote URL cannot be parsed |
221
117
 
222
- Upload to a custom image storage service:
118
+ ## Library
223
119
 
224
- ```bash
225
- pre-post url1 url2 --markdown --upload-url https://my-s3-bucket.amazonaws.com
120
+ ```ts
121
+ import { runPr, captureScreenshot, diffImages, detectRoutesForRepo } from '@juangadm/pre-post';
226
122
  ```
227
123
 
228
- By default, `--markdown` commits screenshots to the PR branch (under `.pre-post/`) and serves them via GitHub blob URLs pinned to the commit SHA. This works for both public and private repos. Use `--upload-url` to point at your own storage instead. It auto-detects the protocol for 0x0.st, Vercel Blob, and any generic PUT endpoint (like S3). Screenshots auto-append to the PR body, newest on top.
229
-
230
- ## Route Detection
231
-
232
- Pre-post automatically maps `git diff --name-only` to affected UI routes:
233
-
234
- | Changed File | Detected Route | Confidence |
235
- |---|---|---|
236
- | `app/page.tsx` | `/` | high |
237
- | `app/dashboard/page.tsx` | `/dashboard` | high |
238
- | `app/(marketing)/about/page.tsx` | `/about` (strips route groups) | high |
239
- | `app/blog/[slug]/page.tsx` | `/blog/[slug]` | high |
240
- | `app/dashboard/layout.tsx` | `/dashboard` | medium |
241
- | `app/dashboard/components/Chart.tsx` | `/dashboard` | medium |
242
- | `globals.css`, `tailwind.config.ts` | `/` | low |
243
- | `app/api/*`, `middleware.ts` | Skipped (no visual) | -- |
244
-
245
- Supports:
246
- - **Next.js App Router** (route groups, dynamic segments, parallel routes, catch-all)
247
- - **Next.js Pages Router** (`pages/`, `_app.tsx`, `_document.tsx`)
248
- - **Generic fallback** (defaults to `/`)
249
-
250
- ## Add Skill
251
-
252
- Install as an agent skill using the [`skills` CLI](https://github.com/vercel-labs/skills):
124
+ ## Development
253
125
 
254
126
  ```bash
255
- npx skills add juangadm/pre-post # interactive — pick your agent(s)
256
- npx skills add juangadm/pre-post -y # auto-install to all universal agents
257
- npx skills add juangadm/pre-post -y -g # install globally (all projects)
127
+ pnpm install
128
+ pnpm build
129
+ pnpm test:unit
130
+ TEST_BROWSER=true pnpm test # needs a Chromium; npx playwright-core install chromium-headless-shell
258
131
  ```
259
132
 
260
- This copies `skill/SKILL.md` into the appropriate directory for your agent (e.g., `.claude/skills/` for Claude Code, `.agents/skills/` for Amp/Codex/Gemini CLI, etc.).
261
-
262
- The skill uses `gh` to detect the associated PR and Playwright for screenshots.
263
-
264
- > **Note:** The npm package (`@juangadm/pre-post`) is published on [npmjs.com](https://www.npmjs.com/package/@juangadm/pre-post), not GitHub Packages — so the "Packages" section on the GitHub repo page will show none.
265
-
266
- ## Credits
267
-
268
- - Original [before-and-after](https://github.com/vercel-labs/before-and-after) by [James Clements](https://github.com/jamesclement) at [Vercel Labs](https://github.com/vercel-labs)
269
- - Browser automation powered by [Playwright](https://playwright.dev/)
270
-
271
133
  ## License
272
134
 
273
135
  MIT