critique 0.1.12 → 0.1.13

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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 0.1.13
2
+
3
+ - Docs:
4
+ - Enhance web preview section in README
5
+ - Add `/v/` short URL alias documentation
6
+
1
7
  # 0.1.12
2
8
 
3
9
  - Web preview:
package/README.md CHANGED
@@ -86,7 +86,13 @@ Use the interactive UI to select files. Selected files are immediately applied a
86
86
 
87
87
  ### Web Preview
88
88
 
89
- Generate a shareable web preview of your diff that you can send to anyone - no installation required:
89
+ Generate a shareable web preview of your diff that you can send to anyone - no installation required.
90
+
91
+ **Example:** [critique.work/v/b8faf4362c247bfc46f5098a028e00f0](https://critique.work/v/b8faf4362c247bfc46f5098a028e00f0)
92
+
93
+ Great for background agents that can't render terminal UIs, like [kimaki.xyz](https://kimaki.xyz) which runs OpenCode in Discord.
94
+
95
+ ![Web Preview](screenshot-web.png)
90
96
 
91
97
  ```bash
92
98
  # Upload to critique.work and get a shareable URL
@@ -95,29 +101,32 @@ critique web
95
101
  # View staged changes
96
102
  critique web --staged
97
103
 
98
- # View the last commit (works whether pushed or unpushed)
104
+ # View the last commit
99
105
  critique web HEAD
100
106
 
101
107
  # View a specific commit
102
108
  critique web --commit HEAD~1
103
109
 
104
- # View combined changes from last N commits
105
- critique web HEAD~3 HEAD
110
+ # Compare branches (PR-style diff)
111
+ critique web main feature-branch
112
+
113
+ # Filter specific files
114
+ critique web -- src/api.ts src/utils.ts
115
+
116
+ # Custom title for the HTML page
117
+ critique web --title "Fix authentication bug"
106
118
 
107
119
  # Generate local HTML file instead of uploading
108
120
  critique web --local
109
-
110
- # Adjust rendering size (use ~100 cols for mobile-friendly output)
111
- critique web --cols 100 --rows 2000
112
121
  ```
113
122
 
114
- **How it works:**
123
+ **Features:**
115
124
 
116
- 1. Captures the terminal UI output using a PTY (pseudo-terminal)
117
- 2. Converts ANSI escape codes to styled HTML with syntax highlighting
118
- 3. Uploads the HTML to [critique.work](https://critique.work) (Cloudflare Worker + KV storage)
119
- 4. Returns a shareable URL that expires after 7 days
120
- 5. Automatically opens the preview in your browser
125
+ - **Mobile optimized** - Automatically detects mobile devices and serves a unified diff view optimized for smaller screens. Add `?v=mobile` to any URL to force mobile view.
126
+ - **Dark/Light mode** - Automatically adapts to your system's color scheme preference using CSS `prefers-color-scheme`.
127
+ - **Syntax highlighting** - Full syntax highlighting for 18+ languages, same as the terminal UI.
128
+ - **Split view** - Side-by-side diff on desktop, unified view on mobile.
129
+ - **Fast loading** - HTML is streamed for quick initial render, cached for 24 hours.
121
130
 
122
131
  **Options:**
123
132
 
@@ -126,14 +135,24 @@ critique web --cols 100 --rows 2000
126
135
  | `--staged` | Show staged changes | - |
127
136
  | `--commit <ref>` | Show changes from a specific commit | - |
128
137
  | `--cols <n>` | Terminal width for rendering | `240` |
129
- | `--rows <n>` | Terminal height for rendering | `2000` |
138
+ | `--mobile-cols <n>` | Terminal width for mobile version | `100` |
130
139
  | `--local` | Save HTML locally instead of uploading | - |
131
140
  | `--filter <pattern>` | Filter files by glob (can be used multiple times) | - |
141
+ | `--title <text>` | Custom HTML document title | `Critique Diff` |
142
+ | `--theme <name>` | Theme for rendering (disables auto dark/light mode) | - |
143
+
144
+ **How it works:**
145
+
146
+ 1. Captures the terminal UI output using a PTY (pseudo-terminal)
147
+ 2. Converts ANSI escape codes to styled HTML with syntax highlighting
148
+ 3. Generates both desktop (240 cols, split view) and mobile (100 cols, unified view) versions
149
+ 4. Uploads to [critique.work](https://critique.work) (Cloudflare Worker + KV storage)
150
+ 5. Returns a shareable URL that expires after 7 days
132
151
 
133
152
  **Tips:**
134
153
 
135
- - Use `--cols 100` for mobile-friendly output (switches to unified diff view instead of split view)
136
154
  - The URL is based on a SHA-256 hash of the content, so identical diffs produce the same URL (deduplication)
155
+ - Use `?v=desktop` or `?v=mobile` query params to force a specific version
137
156
  - If upload fails, critique automatically saves the HTML locally as a fallback
138
157
 
139
158
  ## Features
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "critique",
3
3
  "module": "src/diff.tsx",
4
4
  "type": "module",
5
- "version": "0.1.12",
5
+ "version": "0.1.13",
6
6
  "private": false,
7
7
  "bin": "./src/cli.tsx",
8
8
  "scripts": {
Binary file
package/src/worker.ts CHANGED
@@ -80,7 +80,7 @@ app.post("/upload", async (c) => {
80
80
  }
81
81
 
82
82
  const url = new URL(c.req.url)
83
- const viewUrl = `${url.origin}/view/${id}`
83
+ const viewUrl = `${url.origin}/v/${id}`
84
84
 
85
85
  return c.json({ id, url: viewUrl })
86
86
  } catch (error) {
@@ -89,10 +89,10 @@ app.post("/upload", async (c) => {
89
89
  })
90
90
 
91
91
  // View HTML content with streaming
92
- // GET /view/:id
92
+ // GET /v/:id (short) or /view/:id (legacy)
93
93
  // Query params: ?v=desktop or ?v=mobile to select version
94
94
  // Server redirects mobile devices to ?v=mobile, client JS also handles redirect
95
- app.get("/view/:id", async (c) => {
95
+ async function handleView(c: any) {
96
96
  const id = c.req.param("id")
97
97
 
98
98
  if (!id || !/^[a-f0-9]{16,32}$/.test(id)) {
@@ -144,7 +144,10 @@ app.get("/view/:id", async (c) => {
144
144
  offset += chunkSize
145
145
  }
146
146
  })
147
- })
147
+ }
148
+
149
+ app.get("/v/:id", handleView)
150
+ app.get("/view/:id", handleView)
148
151
 
149
152
  // Get raw HTML content (for debugging/API access)
150
153
  // GET /raw/:id
@@ -167,8 +170,8 @@ app.get("/raw/:id", async (c) => {
167
170
  })
168
171
 
169
172
  // Check if content exists
170
- // HEAD /view/:id
171
- app.on("HEAD", "/view/:id", async (c) => {
173
+ // HEAD /v/:id or /view/:id
174
+ async function handleHead(c: any) {
172
175
  const id = c.req.param("id")
173
176
 
174
177
  if (!id || !/^[a-f0-9]{16,32}$/.test(id)) {
@@ -183,6 +186,9 @@ app.on("HEAD", "/view/:id", async (c) => {
183
186
 
184
187
  c.header("Content-Length", String(html.length))
185
188
  return c.body(null, 200)
186
- })
189
+ }
190
+
191
+ app.on("HEAD", "/v/:id", handleHead)
192
+ app.on("HEAD", "/view/:id", handleHead)
187
193
 
188
194
  export default app