@pixelmatters/markup 1.21.0 → 1.22.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/README.md +8 -8
- package/dist/widget.js +1683 -1593
- package/dist/widget.js.map +1 -1
- package/package.json +1 -2
- package/skills/install-markup-widget/SKILL.md +22 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixelmatters/markup",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "Embeddable feedback widget for collecting visual bug reports, screenshots, and comments on live web apps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"annotation",
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
"provenance": true
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@medv/finder": "^4.0.2",
|
|
51
50
|
"@playwright/test": "^1.62.1",
|
|
52
51
|
"@preact/preset-vite": "^2.10.6",
|
|
53
52
|
"@tanstack/intent": "0.3.6",
|
|
@@ -7,7 +7,7 @@ sources:
|
|
|
7
7
|
- 'Pixelmatters/markup:packages/widget/src/widget.ts'
|
|
8
8
|
metadata:
|
|
9
9
|
library: pixelmatters-markup
|
|
10
|
-
library_version: '1.
|
|
10
|
+
library_version: '1.22.0'
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
`@pixelmatters/markup` is a Preact widget that runs inside a shadow DOM and talks to a hosted Convex backend at `https://<deployment>.convex.site`. The host page calls `init({ apiUrl, apiKey })` once at the app root and gets back a `destroy()` function. Everything else lives inside the widget bundle: pin anchoring, threads, mentions, identity, screenshots, real-time updates.
|
|
@@ -26,7 +26,7 @@ For a `<script>`-tag drop-in (no bundler / CMS / page-builder), use the inline E
|
|
|
26
26
|
|
|
27
27
|
```html
|
|
28
28
|
<script type="module">
|
|
29
|
-
import { init } from 'https://esm.sh/@pixelmatters/markup@1.
|
|
29
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.22.0'
|
|
30
30
|
init({ apiUrl: '…', apiKey: '…' })
|
|
31
31
|
</script>
|
|
32
32
|
```
|
|
@@ -36,7 +36,7 @@ If the host disallows inline JS, use the auto-init form. `data-markup-widget="tr
|
|
|
36
36
|
```html
|
|
37
37
|
<script
|
|
38
38
|
type="module"
|
|
39
|
-
src="https://esm.sh/@pixelmatters/markup@1.
|
|
39
|
+
src="https://esm.sh/@pixelmatters/markup@1.22.0"
|
|
40
40
|
data-markup-widget="true"
|
|
41
41
|
data-api-url="…"
|
|
42
42
|
data-api-key="…"
|
|
@@ -178,24 +178,24 @@ API key belongs to a different project than the one being watched.
|
|
|
178
178
|
|
|
179
179
|
Walk these in order when the widget is misbehaving:
|
|
180
180
|
|
|
181
|
-
| Symptom | Cause
|
|
182
|
-
| --------------------------------------------------------------------------------------- |
|
|
183
|
-
| Toolbar doesn't appear, console warns `[markup] init() requires both apiUrl and apiKey` | One of the env vars is unset / undefined at the call site
|
|
184
|
-
| Toolbar doesn't appear, console shows `403 Origin not allowed` | Host is not in `allowedDomains`
|
|
185
|
-
| Toolbar renders unstyled, or threads never load | CSP is missing `style-src 'unsafe-inline'` (the stylesheet is a `<style>` element in the shadow root) or the deployment origins under `connect-src`
|
|
186
|
-
| Comments show initials where profile pictures are expected | The host's CSP `img-src` blocks the picture host, or the account has none set
|
|
187
|
-
| `@` types a literal character, no picker | The member fetch failed (a `403`/`429` on `/widget/members` degrades silently by design)
|
|
188
|
-
| `401 Invalid api key` | Key revoked, wrong project, or copy-paste truncation
|
|
189
|
-
| `429` + `Retry-After` header | Rate-limited (per-key pre-auth or per-project bucket)
|
|
190
|
-
| `400 Invalid anchor` / `Invalid viewport` / `Field too long` | Widget POSTed a coord outside `[0..1]`, a non-finite viewport size, or an over-long string (route > 256, url > 2048, userAgent > 500, anchorSelector > 1024, authorEmail > 320) | The bundled widget always stays inside these limits, so this only fires if something between the widget and the API rewrote the payload. Check for a misbehaving service worker or proxy |
|
|
191
|
-
| Pins drift after host layout changes | Selector resolution failed; falling back to viewport fractions
|
|
192
|
-
| Pins disappear after route change in an SPA | `init` was called per-route and remounted state
|
|
193
|
-
| Widget styling looks broken inside an iframe | Shadow DOM doesn't pierce frame boundaries
|
|
194
|
-
| Verified identity doesn't survive reload | Host code clears `localStorage['markup.identity']` on logout
|
|
195
|
-
| Popup sign-in flashes and closes | Popup origin failed `allowedDomains` check, or the stored JWT was expired and dropped
|
|
196
|
-
| HMR leaves duplicate toolbars in dev | Hot reload re-runs `init` without cleanup
|
|
197
|
-
| Screenshot is missing my custom field | Auto-mask matched the input (e.g. `autocomplete="cc-number"`) or your selector
|
|
198
|
-
| Widget invisible behind host UI | Z-index conflict on the shadow host element
|
|
181
|
+
| Symptom | Cause | Fix |
|
|
182
|
+
| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
183
|
+
| Toolbar doesn't appear, console warns `[markup] init() requires both apiUrl and apiKey` | One of the env vars is unset / undefined at the call site | Confirm the framework's env-var prefix (`VITE_…`, `NEXT_PUBLIC_…`, etc.) and that `.env` is being loaded |
|
|
184
|
+
| Toolbar doesn't appear, console shows `403 Origin not allowed` | Host is not in `allowedDomains` | Dashboard → Settings → Domains, add the exact host (`app.example.com`) or a wildcard (`*.example.com` matches any subdomain depth) |
|
|
185
|
+
| Toolbar renders unstyled, or threads never load | CSP is missing `style-src 'unsafe-inline'` (the stylesheet is a `<style>` element in the shadow root) or the deployment origins under `connect-src` | See the CSP bullet under **Don'ts** |
|
|
186
|
+
| Comments show initials where profile pictures are expected | The host's CSP `img-src` blocks the picture host, or the account has none set | Add the picture host to `img-src`. Initials are the intended fallback, not a bug |
|
|
187
|
+
| `@` types a literal character, no picker | The member fetch failed (a `403`/`429` on `/widget/members` degrades silently by design) | Check the network tab for `/widget/members`; the usual cause is the domain allowlist |
|
|
188
|
+
| `401 Invalid api key` | Key revoked, wrong project, or copy-paste truncation | Mint a fresh key and replace the env var |
|
|
189
|
+
| `429` + `Retry-After` header | Rate-limited (per-key pre-auth or per-project bucket) | Stop polling; respect the `Retry-After` seconds. If hit during normal use, ask the user to contact support to raise the project limit |
|
|
190
|
+
| `400 Invalid anchor` / `Invalid viewport` / `Field too long` | Widget POSTed a coord outside `[0..1]`, a non-finite viewport size, or an over-long string (route > 256, url > 2048, userAgent > 500, anchorSelector > 1024, anchorText > 256, authorEmail > 320) | The bundled widget always stays inside these limits, so this only fires if something between the widget and the API rewrote the payload. Check for a misbehaving service worker or proxy |
|
|
191
|
+
| Pins drift after host layout changes | Selector resolution failed; falling back to viewport fractions | Expected. Use stable IDs / data-attributes on anchor targets if precision matters |
|
|
192
|
+
| Pins disappear after route change in an SPA | `init` was called per-route and remounted state | Move `init` to a single root-level mount; the widget handles history itself |
|
|
193
|
+
| Widget styling looks broken inside an iframe | Shadow DOM doesn't pierce frame boundaries | Mount the widget **inside** the iframe document, not the parent |
|
|
194
|
+
| Verified identity doesn't survive reload | Host code clears `localStorage['markup.identity']` on logout | Only clear it on Markup-specific sign-out, not on host logout |
|
|
195
|
+
| Popup sign-in flashes and closes | Popup origin failed `allowedDomains` check, or the stored JWT was expired and dropped | Add the host to the project's allowlist; the popup re-validates. Expired JWTs are dropped on the next load, so sign in again |
|
|
196
|
+
| HMR leaves duplicate toolbars in dev | Hot reload re-runs `init` without cleanup | Return the `destroy` from `useEffect` / `onMounted` so HMR can call it. (The history wrapper itself is module-scoped, so repeated init/destroy cycles no longer leak listeners.) |
|
|
197
|
+
| Screenshot is missing my custom field | Auto-mask matched the input (e.g. `autocomplete="cc-number"`) or your selector | Inspect with the widget devtools panel; add `data-markup-safe` on the wrapper to exempt it from auto-detection |
|
|
198
|
+
| Widget invisible behind host UI | Z-index conflict on the shadow host element | The widget mounts `<div id="markup-widget">` at `document.body`; raise its `z-index` from host CSS if you must |
|
|
199
199
|
|
|
200
200
|
## Don'ts
|
|
201
201
|
|
|
@@ -203,7 +203,7 @@ Walk these in order when the widget is misbehaving:
|
|
|
203
203
|
- **Don't wrap in a provider component.** `init` is the whole public API.
|
|
204
204
|
- **Don't call `init` inside a route component.** Mount at the app root once.
|
|
205
205
|
- **Don't hardcode the API key.** Use env vars so rotations don't require a code change.
|
|
206
|
-
- **Don't ship CDN URLs without a version pin.** `@pixelmatters/markup@1.
|
|
206
|
+
- **Don't ship CDN URLs without a version pin.** `@pixelmatters/markup@1.22.0`, not `@pixelmatters/markup`.
|
|
207
207
|
- **Don't add `https://*.convex.site` to `connect-src` and assume that's the whole CSP story.** The deployment domain (`<your-deployment>.convex.site`) is what the widget hits over HTTP, and it must be listed explicitly. Live thread updates go to `wss://<your-deployment>.convex.cloud`, an origin the widget derives from `apiUrl`, so `connect-src` needs both. `img-src` needs `blob:`, `data:`, and the host serving profile pictures; `style-src` needs `'unsafe-inline'` because the widget appends its stylesheet as a `<style>` element inside its shadow root. Add `https://esm.sh` to `script-src` only if you took the CDN path.
|
|
208
208
|
|
|
209
209
|
## Versioning & releases
|