@pixelmatters/markup 1.20.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 +18 -16
- package/dist/widget.js +1614 -1492
- package/dist/widget.js.map +1 -1
- package/package.json +1 -2
- package/skills/install-markup-widget/SKILL.md +22 -22
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Pin-anchored feedback for live web apps. Drop in a script tag and your stakehold
|
|
|
12
12
|
- **Threads, in real time.** Replies stream in via WebSocket. Per-comment edit, delete (with tombstones), and emoji reactions.
|
|
13
13
|
- **@-mentions.** Typing `@` in the composer opens a project-member picker and inserts a chip; the `@[Name](userId)` wire format never reaches the screen. Mentioned teammates are notified, and signed-in users read those notifications from the toolbar's inbox.
|
|
14
14
|
- **Annotated screenshots.** Opt-in capture with the pin marker drawn on the image and embedded fonts, so the snapshot matches what the user saw.
|
|
15
|
-
- **Drop-in identity.** Anonymous by default, with a popup-based sign-in that survives Safari ITP and Chrome storage partitioning. Signed-in authors show their profile picture; everyone else gets initials.
|
|
15
|
+
- **Drop-in identity.** Anonymous by default, with a popup-based sign-in that survives Safari ITP and Chrome storage partitioning. Signed-in authors show their profile picture; everyone else gets initials. A project can be set to **members only** in the dashboard, in which case visitors are asked to sign in before commenting; everyone still sees the pins.
|
|
16
16
|
- **Agent replies are labelled.** A comment written by an AI agent through Markup's MCP server carries a bot badge. It's posted under a team member's name, so the badge is the only way a visitor can tell a machine answered.
|
|
17
17
|
- **Style-isolated.** Runs inside an open shadow root with `:host { all: initial }`, so host CSS can't bleed in and widget CSS can't bleed out.
|
|
18
18
|
- **SPA-aware.** Patches `history.pushState` / `replaceState` and follows `popstate` to refresh threads on route changes.
|
|
@@ -37,9 +37,9 @@ CDN drop-in, no build step. Paste this just before `</body>`:
|
|
|
37
37
|
```html
|
|
38
38
|
<script type="module">
|
|
39
39
|
// Pin the exact version; esm.sh resolves it from npm
|
|
40
|
-
import { init } from 'https://esm.sh/@pixelmatters/markup@1.
|
|
40
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.22.0'
|
|
41
41
|
// or
|
|
42
|
-
// import { init } from 'https://esm.run/@pixelmatters/markup@1.
|
|
42
|
+
// import { init } from 'https://esm.run/@pixelmatters/markup@1.22.0'
|
|
43
43
|
|
|
44
44
|
init({
|
|
45
45
|
apiUrl: 'https://your-deployment.convex.site',
|
|
@@ -50,14 +50,14 @@ CDN drop-in, no build step. Paste this just before `</body>`:
|
|
|
50
50
|
</script>
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
> **Why pin the version?** CDN URLs without a version (`@pixelmatters/markup`) resolve to whatever's `latest` on npm, so a future major release will break your page with no warning. Always pin (`@pixelmatters/markup@1.
|
|
53
|
+
> **Why pin the version?** CDN URLs without a version (`@pixelmatters/markup`) resolve to whatever's `latest` on npm, so a future major release will break your page with no warning. Always pin (`@pixelmatters/markup@1.22.0`).
|
|
54
54
|
|
|
55
55
|
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:
|
|
56
56
|
|
|
57
57
|
```html
|
|
58
58
|
<script
|
|
59
59
|
type="module"
|
|
60
|
-
src="https://esm.sh/@pixelmatters/markup@1.
|
|
60
|
+
src="https://esm.sh/@pixelmatters/markup@1.22.0"
|
|
61
61
|
data-markup-widget="true"
|
|
62
62
|
data-api-url="https://your-deployment.convex.site"
|
|
63
63
|
data-api-key="markup_..."
|
|
@@ -207,15 +207,17 @@ Unmounts the widget and removes the host element. Safe to call when nothing is m
|
|
|
207
207
|
|
|
208
208
|
The widget mounts a single compact pill in the corner set by `position`:
|
|
209
209
|
|
|
210
|
-
| Control | What it does
|
|
211
|
-
| ------------------- |
|
|
212
|
-
| **Comment** | Arms placement. The next click on the page drops a pin, and it flips to a cancel icon while armed.
|
|
213
|
-
| **Inbox** | Mention notifications for this project, with an unread badge. Signed-in users only; anonymous visitors don't get the button.
|
|
214
|
-
| **Pins** (eye) | Hides or shows every pin without hiding the toolbar.
|
|
215
|
-
| **Identity** | Avatar button. Anonymous: a sign-in prompt plus "Forget me on this site". Signed in: name, email, an **Account →** link when `dashboardUrl` is set, and **Sign out**.
|
|
216
|
-
| **Overflow** (`☰`) | **Appearance** (Light / Dark / Auto), **Position** (left / center / right), an **Auto-capture screenshots** toggle, **Privacy & data**, **Keyboard shortcuts**, **Hide for this session**, and the widget version. |
|
|
210
|
+
| Control | What it does |
|
|
211
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
212
|
+
| **Comment** | Arms placement. The next click on the page drops a pin, and it flips to a cancel icon while armed. |
|
|
213
|
+
| **Inbox** | Mention notifications for this project, with an unread badge. Signed-in users only; anonymous visitors don't get the button. |
|
|
214
|
+
| **Pins** (eye) | Hides or shows every pin without hiding the toolbar. |
|
|
215
|
+
| **Identity** | Avatar button. Anonymous: a sign-in prompt plus "Forget me on this site". Signed in: name, email, an **Account →** link when `dashboardUrl` is set, and **Sign out**. |
|
|
216
|
+
| **Overflow** (`☰`) | **Appearance** (Light / Dark / Auto), **Position** (left / center / right), an **Auto-capture screenshots** toggle, a **Show resolved threads** toggle, **Privacy & data**, **Keyboard shortcuts**, **Hide for this session**, and the widget version. |
|
|
217
217
|
|
|
218
|
-
Appearance persists to the host page's `localStorage` (`markup:widget:theme`) and, once a user has set it, takes precedence over the `theme` option on every later `init()`. Position, pin visibility,
|
|
218
|
+
Appearance persists to the host page's `localStorage` (`markup:widget:theme`) and, once a user has set it, takes precedence over the `theme` option on every later `init()`. Position, pin visibility, the auto-capture toggle and the resolved-threads toggle are per-mount. They reset on reload, and `position` seeds the toolbar again.
|
|
219
|
+
|
|
220
|
+
**Show resolved threads** is off by default. Turned on, the widget also renders the route's most recently resolved threads (up to 100) as muted check-mark pins. Opening one shows the thread read-only: no replies, edits, reactions or resolve button. Reopening still happens from the dashboard.
|
|
219
221
|
|
|
220
222
|
The last two menu rows open panels anchored to the same corner as the toolbar:
|
|
221
223
|
|
|
@@ -279,7 +281,7 @@ Capture degrades instead of failing outright:
|
|
|
279
281
|
- The widget mounts `<div id="markup-widget">` on `document.body` and attaches an open shadow root.
|
|
280
282
|
- All UI lives in that shadow root, with `:host { all: initial }` blocking style inheritance.
|
|
281
283
|
- The host element is `position: fixed; inset: 0; pointer-events: none`, so the widget paints over the entire viewport without blocking the host's clicks; only the toolbar and active popovers opt back in to pointer events.
|
|
282
|
-
- Pins are anchored as `(x, y)` fractions of the document plus a
|
|
284
|
+
- Pins are anchored as `(x, y)` fractions of the document plus a CSS path from the nearest landmark (a stable `id`, `data-testid`, `main`, `form`, `table`, …) and the element's text. The path wins when it still resolves, relaxing from the top if a wrapper changed, and a match whose text differs is rejected; the fraction is the fallback so pins survive layout changes.
|
|
283
285
|
- Live thread updates come over a WebSocket to the deployment's `*.convex.cloud` origin, which the widget derives from `apiUrl`. Everything else, meaning comments, identity, screenshots and error reports, goes to `*.convex.site` over HTTP.
|
|
284
286
|
- Identity lives in **host-page** `localStorage` under `markup.identity`, keyed to the top-level site. On first load the widget mints a server-signed anonymous JWT via `POST /widget/anon-identity` so the backend can verify the `authorClientId` on every anon write. Tampering with the cached `clientId` invalidates the signature. Verified identities upgrade to a `Bearer` JWT via the popup flow described below.
|
|
285
287
|
|
|
@@ -370,7 +372,7 @@ For a `<script>` tag drop-in (no bundler), use the inline ESM form and **pin the
|
|
|
370
372
|
|
|
371
373
|
```html
|
|
372
374
|
<script type="module">
|
|
373
|
-
import { init } from 'https://esm.sh/@pixelmatters/markup@1.
|
|
375
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.22.0'
|
|
374
376
|
|
|
375
377
|
init({
|
|
376
378
|
apiUrl: '...',
|
|
@@ -386,7 +388,7 @@ If inline JS is disallowed (some CMS / page-builder editors), use the auto-init
|
|
|
386
388
|
```html
|
|
387
389
|
<script
|
|
388
390
|
type="module"
|
|
389
|
-
src="https://esm.sh/@pixelmatters/markup@1.
|
|
391
|
+
src="https://esm.sh/@pixelmatters/markup@1.22.0"
|
|
390
392
|
data-markup-widget="true"
|
|
391
393
|
data-api-url="..."
|
|
392
394
|
data-api-key="..."
|