@pixelmatters/markup 1.4.1 → 1.6.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 +54 -20
- package/dist/widget.d.ts +11 -1
- package/dist/widget.js +962 -838
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,28 +35,28 @@ CDN drop-in (no build step) — paste this just before `</body>`:
|
|
|
35
35
|
```html
|
|
36
36
|
<script type="module">
|
|
37
37
|
// Pin the exact version — esm.sh resolves it from npm
|
|
38
|
-
import { init } from 'https://esm.sh/@pixelmatters/markup@1.
|
|
38
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.6.0'
|
|
39
39
|
// or
|
|
40
|
-
// import { init } from 'https://esm.run/@pixelmatters/markup@1.
|
|
40
|
+
// import { init } from 'https://esm.run/@pixelmatters/markup@1.6.0'
|
|
41
41
|
|
|
42
42
|
init({
|
|
43
43
|
apiUrl: 'https://your-deployment.convex.site',
|
|
44
44
|
apiKey: 'markup_...',
|
|
45
|
-
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left'
|
|
45
|
+
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
46
46
|
theme: 'auto', // optional: 'auto' | 'light' | 'dark'
|
|
47
47
|
fab: 'default', // optional: 'default' | 'icon-only'
|
|
48
48
|
})
|
|
49
49
|
</script>
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
> **Why pin the version?** CDN URLs without a version (`@pixelmatters/markup`) resolve to whatever's `latest` on npm — a future major release will break your page silently. Always pin (`@pixelmatters/markup@1.
|
|
52
|
+
> **Why pin the version?** CDN URLs without a version (`@pixelmatters/markup`) resolve to whatever's `latest` on npm — a future major release will break your page silently. Always pin (`@pixelmatters/markup@1.6.0`).
|
|
53
53
|
|
|
54
54
|
If your platform doesn't allow inline JS (some CMS / page-builder editors), use the auto-init form instead — point a `<script src=…>` at the bundle and pass config via `data-*` attributes:
|
|
55
55
|
|
|
56
56
|
```html
|
|
57
57
|
<script
|
|
58
58
|
type="module"
|
|
59
|
-
src="https://esm.sh/@pixelmatters/markup@1.
|
|
59
|
+
src="https://esm.sh/@pixelmatters/markup@1.6.0"
|
|
60
60
|
data-markup-widget="true"
|
|
61
61
|
data-api-url="https://your-deployment.convex.site"
|
|
62
62
|
data-api-key="markup_..."
|
|
@@ -78,7 +78,7 @@ import { init, destroy } from '@pixelmatters/markup'
|
|
|
78
78
|
const stop = init({
|
|
79
79
|
apiUrl: 'https://your-deployment.convex.site',
|
|
80
80
|
apiKey: 'markup_...',
|
|
81
|
-
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left'
|
|
81
|
+
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
82
82
|
theme: 'light', // optional: 'auto' | 'light' | 'dark'
|
|
83
83
|
fab: 'default', // optional: 'default' | 'icon-only'
|
|
84
84
|
})
|
|
@@ -98,7 +98,7 @@ export default function App() {
|
|
|
98
98
|
return init({
|
|
99
99
|
apiUrl: import.meta.env.VITE_MARKUP_API_URL,
|
|
100
100
|
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
101
|
-
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left'
|
|
101
|
+
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
102
102
|
theme: 'auto', // optional: 'auto' | 'light' | 'dark'
|
|
103
103
|
fab: 'default', // optional: 'default' | 'icon-only'
|
|
104
104
|
})
|
|
@@ -120,7 +120,7 @@ onMounted(() => {
|
|
|
120
120
|
stop = init({
|
|
121
121
|
apiUrl: import.meta.env.VITE_MARKUP_API_URL,
|
|
122
122
|
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
123
|
-
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left'
|
|
123
|
+
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
124
124
|
theme: 'auto', // optional: 'auto' | 'light' | 'dark'
|
|
125
125
|
fab: 'default', // optional: 'default' | 'icon-only'
|
|
126
126
|
})
|
|
@@ -140,7 +140,7 @@ export default function App() {
|
|
|
140
140
|
const stop = init({
|
|
141
141
|
apiUrl: import.meta.env.VITE_MARKUP_API_URL,
|
|
142
142
|
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
143
|
-
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left'
|
|
143
|
+
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
144
144
|
theme: 'auto', // optional: 'auto' | 'light' | 'dark'
|
|
145
145
|
fab: 'default', // optional: 'default' | 'icon-only'
|
|
146
146
|
})
|
|
@@ -157,13 +157,13 @@ export default function App() {
|
|
|
157
157
|
|
|
158
158
|
Mounts the widget. Always tears down any existing instance before mounting, so calling `init` again (with the same or a different config) is safe. Returns the `destroy` function.
|
|
159
159
|
|
|
160
|
-
| Option | Type
|
|
161
|
-
| ---------- |
|
|
162
|
-
| `apiUrl` | `string`
|
|
163
|
-
| `apiKey` | `string`
|
|
164
|
-
| `position` | `'bottom-right' \| 'bottom-left'` | `'bottom-right'` | Initial
|
|
165
|
-
| `theme` | `'light' \| 'dark' \| 'auto'`
|
|
166
|
-
| `fab` | `'default' \| 'icon-only'`
|
|
160
|
+
| Option | Type | Default | Description |
|
|
161
|
+
| ---------- | ---------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
162
|
+
| `apiUrl` | `string` | required | Convex deployment site URL (`https://*.convex.site`) |
|
|
163
|
+
| `apiKey` | `string` | required | Project API key — mint one in the dashboard |
|
|
164
|
+
| `position` | `'bottom-right' \| 'bottom-left' \| 'bottom-center'` | `'bottom-right'` | Initial placement for the floating action button — users can drag it across the viewport thirds to snap between left / center / right |
|
|
165
|
+
| `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | Visual theme — `'light'` or `'dark'`, or `'auto'` (default) to follow the host's `prefers-color-scheme` |
|
|
166
|
+
| `fab` | `'default' \| 'icon-only'` | `'default'` | Floating button variant — `'icon-only'` drops the "Markup" label for a circular icon button |
|
|
167
167
|
|
|
168
168
|
### `destroy()`
|
|
169
169
|
|
|
@@ -178,6 +178,34 @@ Unmounts the widget and removes the host element. Safe to call when nothing is m
|
|
|
178
178
|
| Drag the FAB | Snap it to whichever bottom corner the pointer ends in |
|
|
179
179
|
| Drag a popover header | Move the open thread / new-thread popover; resets to the pin on reopen |
|
|
180
180
|
|
|
181
|
+
## Screenshots & privacy
|
|
182
|
+
|
|
183
|
+
By default, the widget captures the visible viewport as a JPEG before you submit a thread. Sensitive fields are blacked out **before** the image is produced — the live DOM is mutated only for the duration of the capture and immediately restored. No image content leaves the browser until the user explicitly attaches the screenshot and posts.
|
|
184
|
+
|
|
185
|
+
**Auto-scrubbed (zero config):**
|
|
186
|
+
|
|
187
|
+
- `input[type="password"]`
|
|
188
|
+
- Any `<input>` whose `autocomplete` attribute contains `cc-number`, `cc-csc`, `cc-exp`, `cc-name`, `cc-type`, `current-password`, `new-password`, or `one-time-code`
|
|
189
|
+
|
|
190
|
+
**Attribute API** — add to any element to control capture:
|
|
191
|
+
|
|
192
|
+
| Attribute | Behaviour |
|
|
193
|
+
| --------------------- | ---------------------------------------------------------------------- |
|
|
194
|
+
| `data-markup-private` | Always mask — contents replaced with a solid block. |
|
|
195
|
+
| `data-markup-redact` | Alias for `data-markup-private`. |
|
|
196
|
+
| `data-markup-safe` | Exempts descendants from the default auto-detect rules (escape hatch). |
|
|
197
|
+
| `data-markup-skip` | Removes the element from the screenshot entirely. |
|
|
198
|
+
|
|
199
|
+
**`init()` `screenshots` config:**
|
|
200
|
+
|
|
201
|
+
| Option | Type | Default | Description |
|
|
202
|
+
| ---------------------------- | --------- | ------- | ---------------------------------------------------------- |
|
|
203
|
+
| `screenshots.enabled` | `boolean` | `true` | Set to `false` to disable capture entirely. |
|
|
204
|
+
| `screenshots.strictScrub` | `boolean` | `false` | Also masks all `input`, `select`, and `textarea` elements. |
|
|
205
|
+
| `screenshots.redactSelector` | `string` | — | Custom CSS selector — matched elements are always masked. |
|
|
206
|
+
|
|
207
|
+
When a screenshot is attached in the composer, a chip shows how many fields were redacted. Clicking it expands the list of CSS selectors that were masked.
|
|
208
|
+
|
|
181
209
|
## How it works
|
|
182
210
|
|
|
183
211
|
- The widget mounts `<div id="markup-widget">` on `document.body` and attaches an open shadow root.
|
|
@@ -206,7 +234,13 @@ The popup origin is validated against the project's `allowedDomains` before any
|
|
|
206
234
|
|
|
207
235
|
## AI prompt
|
|
208
236
|
|
|
209
|
-
|
|
237
|
+
If your IDE / agent supports the [`skills`](https://www.npmjs.com/package/skills) CLI (Claude Code, Cursor, etc.), install the bundled skill instead of pasting a prompt — it gives the agent persistent, up-to-date install + troubleshooting guidance:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
npx skills add Pixelmatters/markup --skill pixelmatters-markup
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Otherwise, paste the block below into Claude, ChatGPT, Cursor, or any other LLM and it'll wire the widget into your codebase end-to-end.
|
|
210
244
|
|
|
211
245
|
````markdown
|
|
212
246
|
You are helping me install the **`@pixelmatters/markup`** feedback widget into my web app.
|
|
@@ -229,7 +263,7 @@ import { init, destroy } from '@pixelmatters/markup'
|
|
|
229
263
|
init({
|
|
230
264
|
apiUrl: string, // required
|
|
231
265
|
apiKey: string, // required
|
|
232
|
-
position?: 'bottom-right' | 'bottom-left', // default 'bottom-right'
|
|
266
|
+
position?: 'bottom-right' | 'bottom-left' | 'bottom-center', // default 'bottom-right'
|
|
233
267
|
theme?: 'light' | 'dark' | 'auto', // default 'auto'
|
|
234
268
|
fab?: 'default' | 'icon-only', // default 'default'
|
|
235
269
|
}) // returns a destroy() function — call it on unmount / logout / route teardown
|
|
@@ -244,7 +278,7 @@ For a `<script>` tag drop-in (no bundler), use the inline ESM form and **pin the
|
|
|
244
278
|
|
|
245
279
|
```html
|
|
246
280
|
<script type="module">
|
|
247
|
-
import { init } from 'https://esm.sh/@pixelmatters/markup@1.
|
|
281
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.6.0'
|
|
248
282
|
|
|
249
283
|
init({
|
|
250
284
|
apiUrl: '...',
|
|
@@ -261,7 +295,7 @@ If inline JS is disallowed (some CMS / page-builder editors), use the auto-init
|
|
|
261
295
|
```html
|
|
262
296
|
<script
|
|
263
297
|
type="module"
|
|
264
|
-
src="https://esm.sh/@pixelmatters/markup@1.
|
|
298
|
+
src="https://esm.sh/@pixelmatters/markup@1.6.0"
|
|
265
299
|
data-markup-widget="true"
|
|
266
300
|
data-api-url="..."
|
|
267
301
|
data-api-key="..."
|
package/dist/widget.d.ts
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
export type WidgetTheme = 'light' | 'dark' | 'auto';
|
|
2
2
|
export type WidgetFab = 'default' | 'icon-only';
|
|
3
|
+
export interface ScreenshotsConfig {
|
|
4
|
+
/** Disable screenshot capture entirely. Default: enabled. */
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
/** Also masks all inputs/selects/textareas in addition to the default sensitive set. Default: false. */
|
|
7
|
+
strictScrub?: boolean;
|
|
8
|
+
/** Custom CSS selector — matched elements are always masked. */
|
|
9
|
+
redactSelector?: string;
|
|
10
|
+
}
|
|
3
11
|
export interface WidgetConfig {
|
|
4
12
|
/** Convex deployment site URL, e.g. `https://your-deployment.convex.site` */
|
|
5
13
|
apiUrl: string;
|
|
6
14
|
/** Raw API key minted from a project's settings page */
|
|
7
15
|
apiKey: string;
|
|
8
16
|
/** Where the floating button sits. Defaults to bottom-right. */
|
|
9
|
-
position?: 'bottom-right' | 'bottom-left';
|
|
17
|
+
position?: 'bottom-right' | 'bottom-left' | 'bottom-center';
|
|
10
18
|
/**
|
|
11
19
|
* Visual theme.
|
|
12
20
|
* - `'light'` — force light palette
|
|
@@ -22,6 +30,8 @@ export interface WidgetConfig {
|
|
|
22
30
|
* Defaults to `'default'`.
|
|
23
31
|
*/
|
|
24
32
|
fab?: WidgetFab;
|
|
33
|
+
/** Screenshot capture and PII-scrub options. */
|
|
34
|
+
screenshots?: ScreenshotsConfig;
|
|
25
35
|
}
|
|
26
36
|
/**
|
|
27
37
|
* Mounts the feedback widget on the page. Idempotent — calling init again
|