@pixelmatters/markup 1.28.0 → 1.29.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 CHANGED
@@ -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.28.0'
40
+ import { init } from 'https://esm.sh/@pixelmatters/markup@1.29.0'
41
41
  // or
42
- // import { init } from 'https://esm.run/@pixelmatters/markup@1.28.0'
42
+ // import { init } from 'https://esm.run/@pixelmatters/markup@1.29.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.28.0`).
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.29.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.28.0"
60
+ src="https://esm.sh/@pixelmatters/markup@1.29.0"
61
61
  data-markup-widget="true"
62
62
  data-api-url="https://your-deployment.convex.site"
63
63
  data-api-key="markup_..."
@@ -442,13 +442,13 @@ npx @tanstack/intent@latest install
442
442
 
443
443
  Re-run it when you add another Intent-enabled package. A `pnpm update` of this one is enough on its own, because the skill travels with the tarball and refreshes in place.
444
444
 
445
- If you'd rather pull it straight from the repo, or you're deciding whether to adopt the widget at all and haven't installed it yet, the [`skills`](https://www.npmjs.com/package/skills) CLI takes it by path:
445
+ If you haven't installed the widget yet, or you're still deciding whether to adopt it, the [`skills`](https://www.npmjs.com/package/skills) CLI fetches the same skill from the Markup site:
446
446
 
447
447
  ```bash
448
- npx skills add Pixelmatters/markup/packages/widget/skills/install-markup-widget
448
+ npx skills add https://markup.pixelmatters.dev --skill install-markup-widget
449
449
  ```
450
450
 
451
- Pass the full path, not just the repository. That is where this skill lives, and a bare repository reference resolves to a different set of skills.
451
+ Keep `--skill`. The site also publishes a skill for reading feedback over MCP, and without the flag the CLI asks which to install.
452
452
 
453
453
  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.
454
454
 
@@ -495,7 +495,7 @@ For a `<script>` tag drop-in (no bundler), use the inline ESM form and **pin the
495
495
 
496
496
  ```html
497
497
  <script type="module">
498
- import { init } from 'https://esm.sh/@pixelmatters/markup@1.28.0'
498
+ import { init } from 'https://esm.sh/@pixelmatters/markup@1.29.0'
499
499
 
500
500
  init({
501
501
  apiUrl: '...',
@@ -511,7 +511,7 @@ If inline JS is disallowed (some CMS / page-builder editors), use the auto-init
511
511
  ```html
512
512
  <script
513
513
  type="module"
514
- src="https://esm.sh/@pixelmatters/markup@1.28.0"
514
+ src="https://esm.sh/@pixelmatters/markup@1.29.0"
515
515
  data-markup-widget="true"
516
516
  data-api-url="..."
517
517
  data-api-key="..."
package/dist/react.js CHANGED
@@ -1,15 +1,2 @@
1
- "use client";
2
- import { init as e, t } from "./widget.js";
3
- import { t as n } from "./shared-mount-DABK4arh.js";
4
- import { useEffect as r } from "react";
5
- //#region src/react.ts
6
- function i(i) {
7
- let { enabled: a = !0, ...o } = i, s = a ? t(o) : null;
8
- r(() => {
9
- if (s !== null) return n(s, e);
10
- }, [s]);
11
- }
12
- //#endregion
13
- export { i as useMarkup };
14
-
1
+ "use client";import{init as e,t}from"./widget.js";import{t as n}from"./shared-mount-B9ij4vuL.js";import{useEffect as r}from"react";function i(i){let{enabled:a=!0,...o}=i,s=a?t(o):null;r(()=>{if(s!==null)return n(s,e)},[s])}export{i as useMarkup};
15
2
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":[],"sources":["../src/react.ts"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\n\nimport { configKey } from './runtime/config-key'\nimport { acquireMount } from './runtime/shared-mount'\nimport { init, type WidgetConfig } from './widget'\n\nexport type { WidgetConfig } from './widget'\n\nexport type UseMarkupOptions = WidgetConfig & {\n /**\n * `false` unmounts the widget, or never mounts it. Drive it from your build\n * environment to keep the widget off production.\n *\n * @default true\n */\n enabled?: boolean\n}\n\n/**\n * Mounts the widget for as long as the calling component is mounted. Call it\n * once near your app root.\n *\n * An inline options object is fine: the widget remounts only when a value\n * changes, not when the object is recreated. Two components using the same\n * options share one widget, and it stays until both unmount. Server rendering\n * mounts nothing.\n */\nexport function useMarkup(options: UseMarkupOptions): void {\n const { enabled = true, ...config } = options\n const key = enabled ? configKey(config) : null\n\n useEffect(() => {\n if (key === null) return\n return acquireMount(key, init)\n }, [key])\n}\n"],"mappings":";;;;;AA6BA,SAAgB,EAAU,GAAiC;CACzD,IAAM,EAAE,aAAU,IAAM,GAAG,MAAW,GAChC,IAAM,IAAU,EAAU,CAAM,IAAI;CAE1C,QAAgB;EACV,UAAQ,MACZ,OAAO,EAAa,GAAK,CAAI;CAC/B,GAAG,CAAC,CAAG,CAAC;AACV"}
1
+ {"version":3,"file":"react.js","names":[],"sources":["../src/react.ts"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\n\nimport { configKey } from './runtime/config-key'\nimport { acquireMount } from './runtime/shared-mount'\nimport { init, type WidgetConfig } from './widget'\n\nexport type { WidgetConfig } from './widget'\n\nexport type UseMarkupOptions = WidgetConfig & {\n /**\n * `false` unmounts the widget, or never mounts it. Drive it from your build\n * environment to keep the widget off production.\n *\n * @default true\n */\n enabled?: boolean\n}\n\n/**\n * Mounts the widget for as long as the calling component is mounted. Call it\n * once near your app root.\n *\n * An inline options object is fine: the widget remounts only when a value\n * changes, not when the object is recreated. Two components using the same\n * options share one widget, and it stays until both unmount. Server rendering\n * mounts nothing.\n */\nexport function useMarkup(options: UseMarkupOptions): void {\n const { enabled = true, ...config } = options\n const key = enabled ? configKey(config) : null\n\n useEffect(() => {\n if (key === null) return\n return acquireMount(key, init)\n }, [key])\n}\n"],"mappings":"mIA6BA,SAAgB,EAAU,EAAiC,CACzD,GAAM,CAAE,UAAU,GAAM,GAAG,GAAW,EAChC,EAAM,EAAU,EAAU,CAAM,EAAI,KAE1C,MAAgB,CACV,OAAQ,KACZ,OAAO,EAAa,EAAK,CAAI,CAC/B,EAAG,CAAC,CAAG,CAAC,CACV"}
@@ -0,0 +1,2 @@
1
+ var e=/* @__PURE__ */ new Map;function t(t,n){let r=n(JSON.parse(t)),i=(e.get(t)?.count??0)+1;e.delete(t),e.set(t,{count:i,dispose:r});let a=!1;return()=>{if(a)return;a=!0;let r=e.get(t);if(!r||(--r.count,r.count>0))return;e.delete(t),r.dispose();let i=[...e.entries()].at(-1);if(i)try{i[1].dispose=n(JSON.parse(i[0]))}catch(e){i[1].dispose=()=>{},console.warn(`[markup] could not remount the widget`,e)}}}export{t};
2
+ //# sourceMappingURL=shared-mount-B9ij4vuL.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-mount-DABK4arh.js","names":[],"sources":["../src/runtime/shared-mount.ts"],"sourcesContent":["import type { WidgetConfig } from '../widget'\n\ntype Holder = { count: number; dispose: () => void }\n\nconst holders = new Map<string, Holder>()\n\n/**\n * Counts hook holders per config, so the first of two components to unmount\n * doesn't take the widget away from the other. `init` still runs on every\n * acquire: it is a no-op for the live config, and it remounts one that a\n * different config has since replaced.\n *\n * Holders of different configs contend for the one widget, and the latest to\n * acquire wins. When it lets go, the most recent remaining config is mounted\n * again, so no holder is left without a widget while it still wants one.\n */\nexport function acquireMount(key: string, init: (config: WidgetConfig) => () => void): () => void {\n const dispose = init(JSON.parse(key) as WidgetConfig)\n const count = (holders.get(key)?.count ?? 0) + 1\n // Re-inserted so the map's order is recency, which the release path reads.\n holders.delete(key)\n holders.set(key, { count, dispose })\n\n let isReleased = false\n return () => {\n if (isReleased) return\n isReleased = true\n const current = holders.get(key)\n if (!current) return\n current.count -= 1\n if (current.count > 0) return\n holders.delete(key)\n current.dispose()\n const survivor = [...holders.entries()].at(-1)\n if (!survivor) return\n // This runs inside some other component's cleanup; a failure to bring\n // the survivor back must not surface as that component's error.\n try {\n survivor[1].dispose = init(JSON.parse(survivor[0]) as WidgetConfig)\n } catch (error) {\n survivor[1].dispose = () => {}\n console.warn('[markup] could not remount the widget', error)\n }\n }\n}\n"],"mappings":";AAIA,IAAM,oBAAU,IAAI,IAAoB;AAYxC,SAAgB,EAAa,GAAa,GAAwD;CAChG,IAAM,IAAU,EAAK,KAAK,MAAM,CAAG,CAAiB,GAC9C,KAAS,EAAQ,IAAI,CAAG,CAAC,EAAE,SAAS,KAAK;CAG/C,AADA,EAAQ,OAAO,CAAG,GAClB,EAAQ,IAAI,GAAK;EAAE;EAAO;CAAQ,CAAC;CAEnC,IAAI,IAAa;CACjB,aAAa;EACX,IAAI,GAAY;EAChB,IAAa;EACb,IAAM,IAAU,EAAQ,IAAI,CAAG;EAG/B,IAFI,CAAC,MACL,IAAQ,OACJ,EAAQ,QAAQ,IAAG;EAEvB,AADA,EAAQ,OAAO,CAAG,GAClB,EAAQ,QAAQ;EAChB,IAAM,IAAW,CAAC,GAAG,EAAQ,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE;EACxC,OAGL,IAAI;GACF,EAAS,EAAE,CAAC,UAAU,EAAK,KAAK,MAAM,EAAS,EAAE,CAAiB;EACpE,SAAS,GAAO;GAEd,AADA,EAAS,EAAE,CAAC,gBAAgB,CAAC,GAC7B,QAAQ,KAAK,yCAAyC,CAAK;EAC7D;CACF;AACF"}
1
+ {"version":3,"file":"shared-mount-B9ij4vuL.js","names":[],"sources":["../src/runtime/shared-mount.ts"],"sourcesContent":["import type { WidgetConfig } from '../widget'\n\ntype Holder = { count: number; dispose: () => void }\n\nconst holders = new Map<string, Holder>()\n\n/**\n * Counts hook holders per config, so the first of two components to unmount\n * doesn't take the widget away from the other. `init` still runs on every\n * acquire: it is a no-op for the live config, and it remounts one that a\n * different config has since replaced.\n *\n * Holders of different configs contend for the one widget, and the latest to\n * acquire wins. When it lets go, the most recent remaining config is mounted\n * again, so no holder is left without a widget while it still wants one.\n */\nexport function acquireMount(key: string, init: (config: WidgetConfig) => () => void): () => void {\n const dispose = init(JSON.parse(key) as WidgetConfig)\n const count = (holders.get(key)?.count ?? 0) + 1\n // Re-inserted so the map's order is recency, which the release path reads.\n holders.delete(key)\n holders.set(key, { count, dispose })\n\n let isReleased = false\n return () => {\n if (isReleased) return\n isReleased = true\n const current = holders.get(key)\n if (!current) return\n current.count -= 1\n if (current.count > 0) return\n holders.delete(key)\n current.dispose()\n const survivor = [...holders.entries()].at(-1)\n if (!survivor) return\n // This runs inside some other component's cleanup; a failure to bring\n // the survivor back must not surface as that component's error.\n try {\n survivor[1].dispose = init(JSON.parse(survivor[0]) as WidgetConfig)\n } catch (error) {\n survivor[1].dispose = () => {}\n console.warn('[markup] could not remount the widget', error)\n }\n }\n}\n"],"mappings":"AAIA,IAAM,kBAAU,IAAI,IAYpB,SAAgB,EAAa,EAAa,EAAwD,CAChG,IAAM,EAAU,EAAK,KAAK,MAAM,CAAG,CAAiB,EAC9C,GAAS,EAAQ,IAAI,CAAG,CAAC,EAAE,OAAS,GAAK,EAE/C,EAAQ,OAAO,CAAG,EAClB,EAAQ,IAAI,EAAK,CAAE,QAAO,SAAQ,CAAC,EAEnC,IAAI,EAAa,GACjB,UAAa,CACX,GAAI,EAAY,OAChB,EAAa,GACb,IAAM,EAAU,EAAQ,IAAI,CAAG,EAG/B,GAFI,CAAC,IACL,IAAQ,MACJ,EAAQ,MAAQ,GAAG,OACvB,EAAQ,OAAO,CAAG,EAClB,EAAQ,QAAQ,EAChB,IAAM,EAAW,CAAC,GAAG,EAAQ,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,EACxC,KAGL,GAAI,CACF,EAAS,EAAE,CAAC,QAAU,EAAK,KAAK,MAAM,EAAS,EAAE,CAAiB,CACpE,OAAS,EAAO,CACd,EAAS,EAAE,CAAC,YAAgB,CAAC,EAC7B,QAAQ,KAAK,wCAAyC,CAAK,CAC7D,CACF,CACF"}
package/dist/vue.js CHANGED
@@ -1,21 +1,2 @@
1
- import { init as e, t } from "./widget.js";
2
- import { t as n } from "./shared-mount-DABK4arh.js";
3
- import { computed as r, onBeforeUnmount as i, onMounted as a, toValue as o, watch as s } from "vue";
4
- //#region src/vue.ts
5
- function c(c) {
6
- let l = r(() => {
7
- let { enabled: e = !0, ...n } = o(c);
8
- return e ? t(n) : null;
9
- }), u = null, d = (t) => {
10
- u?.(), u = t === null ? null : n(t, e);
11
- }, f = null;
12
- a(() => {
13
- d(l.value), f = s(l, d);
14
- }), i(() => {
15
- f?.(), d(null);
16
- });
17
- }
18
- //#endregion
19
- export { c as useMarkup };
20
-
1
+ import{init as e,t}from"./widget.js";import{t as n}from"./shared-mount-B9ij4vuL.js";import{computed as r,onBeforeUnmount as i,onMounted as a,toValue as o,watch as s}from"vue";function c(c){let l=r(()=>{let{enabled:e=!0,...n}=o(c);return e?t(n):null}),u=null,d=t=>{u?.(),u=t===null?null:n(t,e)},f=null;a(()=>{d(l.value),f=s(l,d)}),i(()=>{f?.(),d(null)})}export{c as useMarkup};
21
2
  //# sourceMappingURL=vue.js.map
package/dist/vue.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vue.js","names":[],"sources":["../src/vue.ts"],"sourcesContent":["import { computed, onBeforeUnmount, onMounted, toValue, watch, type MaybeRefOrGetter } from 'vue'\n\nimport { configKey } from './runtime/config-key'\nimport { acquireMount } from './runtime/shared-mount'\nimport { init, type WidgetConfig } from './widget'\n\nexport type { WidgetConfig } from './widget'\n\nexport type UseMarkupOptions = WidgetConfig & {\n /**\n * `false` unmounts the widget, or never mounts it. Drive it from your build\n * environment to keep the widget off production.\n *\n * @default true\n */\n enabled?: boolean\n}\n\n/**\n * Mounts the widget for as long as the calling component is mounted. Call it\n * once from your root component's `setup`.\n *\n * Pass a plain object, a ref, or a getter. The widget remounts only when a\n * value changes, not when the object is replaced by an equal one. Two\n * components using the same options share one widget, and it stays until\n * both unmount. Nothing mounts during server rendering, since mounting waits\n * for `onMounted`.\n */\nexport function useMarkup(options: MaybeRefOrGetter<UseMarkupOptions>): void {\n const key = computed(() => {\n const { enabled = true, ...config } = toValue(options)\n return enabled ? configKey(config) : null\n })\n\n let release: (() => void) | null = null\n const apply = (next: string | null) => {\n release?.()\n release = next === null ? null : acquireMount(next, init)\n }\n\n let stopWatching: (() => void) | null = null\n onMounted(() => {\n apply(key.value)\n stopWatching = watch(key, apply)\n })\n onBeforeUnmount(() => {\n stopWatching?.()\n apply(null)\n })\n}\n"],"mappings":";;;;AA4BA,SAAgB,EAAU,GAAmD;CAC3E,IAAM,IAAM,QAAe;EACzB,IAAM,EAAE,aAAU,IAAM,GAAG,MAAW,EAAQ,CAAO;EACrD,OAAO,IAAU,EAAU,CAAM,IAAI;CACvC,CAAC,GAEG,IAA+B,MAC7B,KAAS,MAAwB;EAErC,AADA,IAAU,GACV,IAAU,MAAS,OAAO,OAAO,EAAa,GAAM,CAAI;CAC1D,GAEI,IAAoC;CAKxC,AAJA,QAAgB;EAEd,AADA,EAAM,EAAI,KAAK,GACf,IAAe,EAAM,GAAK,CAAK;CACjC,CAAC,GACD,QAAsB;EAEpB,AADA,IAAe,GACf,EAAM,IAAI;CACZ,CAAC;AACH"}
1
+ {"version":3,"file":"vue.js","names":[],"sources":["../src/vue.ts"],"sourcesContent":["import { computed, onBeforeUnmount, onMounted, toValue, watch, type MaybeRefOrGetter } from 'vue'\n\nimport { configKey } from './runtime/config-key'\nimport { acquireMount } from './runtime/shared-mount'\nimport { init, type WidgetConfig } from './widget'\n\nexport type { WidgetConfig } from './widget'\n\nexport type UseMarkupOptions = WidgetConfig & {\n /**\n * `false` unmounts the widget, or never mounts it. Drive it from your build\n * environment to keep the widget off production.\n *\n * @default true\n */\n enabled?: boolean\n}\n\n/**\n * Mounts the widget for as long as the calling component is mounted. Call it\n * once from your root component's `setup`.\n *\n * Pass a plain object, a ref, or a getter. The widget remounts only when a\n * value changes, not when the object is replaced by an equal one. Two\n * components using the same options share one widget, and it stays until\n * both unmount. Nothing mounts during server rendering, since mounting waits\n * for `onMounted`.\n */\nexport function useMarkup(options: MaybeRefOrGetter<UseMarkupOptions>): void {\n const key = computed(() => {\n const { enabled = true, ...config } = toValue(options)\n return enabled ? configKey(config) : null\n })\n\n let release: (() => void) | null = null\n const apply = (next: string | null) => {\n release?.()\n release = next === null ? null : acquireMount(next, init)\n }\n\n let stopWatching: (() => void) | null = null\n onMounted(() => {\n apply(key.value)\n stopWatching = watch(key, apply)\n })\n onBeforeUnmount(() => {\n stopWatching?.()\n apply(null)\n })\n}\n"],"mappings":"+KA4BA,SAAgB,EAAU,EAAmD,CAC3E,IAAM,EAAM,MAAe,CACzB,GAAM,CAAE,UAAU,GAAM,GAAG,GAAW,EAAQ,CAAO,EACrD,OAAO,EAAU,EAAU,CAAM,EAAI,IACvC,CAAC,EAEG,EAA+B,KAC7B,EAAS,GAAwB,CACrC,IAAU,EACV,EAAU,IAAS,KAAO,KAAO,EAAa,EAAM,CAAI,CAC1D,EAEI,EAAoC,KACxC,MAAgB,CACd,EAAM,EAAI,KAAK,EACf,EAAe,EAAM,EAAK,CAAK,CACjC,CAAC,EACD,MAAsB,CACpB,IAAe,EACf,EAAM,IAAI,CACZ,CAAC,CACH"}