@craftware/crafty-sdk 0.3.0 → 0.4.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 +13 -2
- package/dist/attrs.d.ts +9 -0
- package/dist/attrs.d.ts.map +1 -1
- package/dist/attrs.js +8 -0
- package/dist/attrs.js.map +1 -1
- package/dist/crafty-visual-editing.global.js +3 -3
- package/dist/crafty-visual-editing.global.js.map +3 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/visual-editing/bridge.d.ts.map +1 -1
- package/dist/visual-editing/bridge.js +90 -29
- package/dist/visual-editing/bridge.js.map +1 -1
- package/dist/visual-editing/markers.js +3 -2
- package/dist/visual-editing/markers.js.map +1 -1
- package/dist/visual-editing/protocol.d.ts +4 -0
- package/dist/visual-editing/protocol.d.ts.map +1 -1
- package/dist/visual-editing/protocol.js +30 -10
- package/dist/visual-editing/protocol.js.map +1 -1
- package/package.json +1 -1
- package/skills/crafty-cms/SKILL.md +2 -1
- package/skills/crafty-cms/references/visual-editor.md +87 -8
package/README.md
CHANGED
|
@@ -242,6 +242,17 @@ Crafty's visual editor loads your site in an iframe and lets editors click a tex
|
|
|
242
242
|
<h2 {...crafty.attrs(entry, `sections[${i}].title`, { label: "Título de la sección" })}>{section.title}</h2>
|
|
243
243
|
```
|
|
244
244
|
|
|
245
|
+
Buttons and links: pass `hrefField` (and optionally `hrefLabel`) so the editor edits the destination together with the text. Clicking anywhere on a link (padding, icon, keyboard activation) selects its marked label instead of following it. Real `<button>`, `<summary>` and `<label>` elements keep their own behavior (menus, accordions) unless the click lands on the marked element itself:
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
<a href={cta.href} className="btn">
|
|
249
|
+
<span {...crafty.attrs(entry, "hero.cta.label", { label: "Texto del botón", hrefField: "hero.cta.href", hrefLabel: "Enlace del botón" })}>{cta.label}</span>
|
|
250
|
+
<ArrowIcon />
|
|
251
|
+
</a>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
A link whose only editable value is its destination (a `url` field) is marked on the `<a>` itself: `<a {...crafty.attrs(entry, "maps_url", { label: "Enlace del mapa" })} href={entry.maps_url}>Ver mapa</a>`. Link destinations are never written live into the page; they show after saving the draft.
|
|
255
|
+
|
|
245
256
|
String templates use `attrsHtml(target, field, options)`, which returns escaped `data-crafty-*="…"` pairs. Attributes are always emitted, so static builds keep them.
|
|
246
257
|
|
|
247
258
|
**2. Carry the preview token.** In the browser nothing is needed. With server rendering, read it per request:
|
|
@@ -285,11 +296,11 @@ if (status === "invalid") notifyPreviewInvalid();
|
|
|
285
296
|
Without a bundler:
|
|
286
297
|
|
|
287
298
|
```html
|
|
288
|
-
<script src="https://cdn.jsdelivr.net/npm/@craftware/crafty-sdk@0.
|
|
299
|
+
<script src="https://cdn.jsdelivr.net/npm/@craftware/crafty-sdk@0.4/dist/crafty-visual-editing.global.js"></script>
|
|
289
300
|
<script>CraftyVisualEditing.enableVisualEditing();</script>
|
|
290
301
|
```
|
|
291
302
|
|
|
292
|
-
For production, pin an exact version (`@0.
|
|
303
|
+
For production, pin an exact version (`@0.4.0`) and add `integrity="sha384-…" crossorigin="anonymous"` with the hash jsDelivr shows for that file.
|
|
293
304
|
|
|
294
305
|
Sites not hosted on Crafty Hosting must allow the admin to frame them: `Content-Security-Policy: frame-ancestors 'self' https://<tenant>.crafty.do`.
|
|
295
306
|
|
package/dist/attrs.d.ts
CHANGED
|
@@ -11,12 +11,21 @@ export type CraftyEditTarget = CraftyBlock | CraftyEntry | {
|
|
|
11
11
|
export type CraftyAttrsOptions = {
|
|
12
12
|
/** Human label shown by the visual editor, e.g. "Título de la sección". */
|
|
13
13
|
label?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Field holding the link destination of this element (a button or link whose
|
|
16
|
+
* text is `field`), e.g. `hero.cta.href`. The editor then edits both together.
|
|
17
|
+
*/
|
|
18
|
+
hrefField?: string;
|
|
19
|
+
/** Human label for `hrefField`. Defaults to "Enlace" in the editor. */
|
|
20
|
+
hrefLabel?: string;
|
|
14
21
|
};
|
|
15
22
|
export type CraftyEditAttributes = {
|
|
16
23
|
"data-crafty-block"?: string;
|
|
17
24
|
"data-crafty-entry"?: string;
|
|
18
25
|
"data-crafty-field"?: string;
|
|
19
26
|
"data-crafty-label"?: string;
|
|
27
|
+
"data-crafty-href-field"?: string;
|
|
28
|
+
"data-crafty-href-label"?: string;
|
|
20
29
|
};
|
|
21
30
|
export declare function resolveEditTarget(target: CraftyEditTarget | null | undefined): {
|
|
22
31
|
type: CraftyEditTargetType;
|
package/dist/attrs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attrs.d.ts","sourceRoot":"","sources":["../src/attrs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,OAAO,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,WAAW,GACX;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"attrs.d.ts","sourceRoot":"","sources":["../src/attrs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,OAAO,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,WAAW,GACX;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,GAC1C;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAuBnD;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CACnB,MAAM,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,EAC3C,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,kBAAuB,GAC/B,oBAAoB,CAgCtB;AAED,6DAA6D;AAC7D,wBAAgB,SAAS,CACvB,MAAM,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,EAC3C,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAIR"}
|
package/dist/attrs.js
CHANGED
|
@@ -34,6 +34,14 @@ export function attrs(target, field, options = {}) {
|
|
|
34
34
|
if (label !== "") {
|
|
35
35
|
attributes["data-crafty-label"] = label;
|
|
36
36
|
}
|
|
37
|
+
const hrefField = typeof options.hrefField === "string" ? options.hrefField.trim() : "";
|
|
38
|
+
if (hrefField !== "") {
|
|
39
|
+
attributes["data-crafty-href-field"] = hrefField;
|
|
40
|
+
const hrefLabel = typeof options.hrefLabel === "string" ? options.hrefLabel.trim() : "";
|
|
41
|
+
if (hrefLabel !== "") {
|
|
42
|
+
attributes["data-crafty-href-label"] = hrefLabel;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
37
45
|
return attributes;
|
|
38
46
|
}
|
|
39
47
|
/** Same as `attrs()`, rendered for HTML string templates. */
|
package/dist/attrs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attrs.js","sourceRoot":"","sources":["../src/attrs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"attrs.js","sourceRoot":"","sources":["../src/attrs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var CraftyVisualEditing=(()=>{var
|
|
2
|
-
`);function
|
|
3
|
-
`)}function
|
|
1
|
+
"use strict";var CraftyVisualEditing=(()=>{var I=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var Ie=Object.getOwnPropertyNames;var Fe=Object.prototype.hasOwnProperty;var He=(e,t)=>{for(var n in t)I(e,n,{get:t[n],enumerable:!0})},We=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Ie(t))!Fe.call(e,i)&&i!==n&&I(e,i,{get:()=>t[i],enumerable:!(r=Ve(t,i))||r.enumerable});return e};var Ke=e=>We(I({},"__esModule",{value:!0}),e);var st={};He(st,{PROTOCOL_VERSION:()=>b,attrs:()=>F,attrsHtml:()=>oe,enableVisualEditing:()=>Re});function $e(e){if(e==null||typeof e!="object")return null;let t=e,n=typeof t.id=="string"?Number(t.id.trim()):t.id;return typeof n!="number"||!Number.isInteger(n)||n<=0?null:t.kind==="block"||t.kind==="entry"?{type:t.kind,id:n}:{type:typeof t.order=="number"&&typeof t.data=="object"&&t.data!==null&&"type"in t?"block":"entry",id:n}}function F(e,t,n={}){let r=$e(e),i=typeof t=="string"?t.trim():"";if(r===null||i==="")return{};let o=r.type==="block"?{"data-crafty-block":String(r.id),"data-crafty-field":i}:{"data-crafty-entry":String(r.id),"data-crafty-field":i},l=typeof n.label=="string"?n.label.trim():"";l!==""&&(o["data-crafty-label"]=l);let s=typeof n.hrefField=="string"?n.hrefField.trim():"";if(s!==""){o["data-crafty-href-field"]=s;let d=typeof n.hrefLabel=="string"?n.hrefLabel.trim():"";d!==""&&(o["data-crafty-href-label"]=d)}return o}function oe(e,t,n={}){return Object.entries(F(e,t,n)).map(([r,i])=>`${r}="${Ue(String(i))}"`).join(" ")}function Ue(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}var $="crafty_preview";var O="crafty:preview-invalid",U="crafty:preview-content",D="crafty:preview-active",W="crafty:preview-token",le="crafty:preview-url-token",De="crafty:preview-invalid-token",Ge="__CRAFTY_PREVIEW_CONTENT__",Ye="__CRAFTY_PREVIEW_STATUS__";function A(){return typeof window=="undefined"?null:window}function H(e){var t,n;try{return(n=(t=A())==null?void 0:t.sessionStorage.getItem(e))!=null?n:null}catch{return null}}function K(e,t){var n;try{(n=A())==null||n.sessionStorage.setItem(e,t)}catch{}}function G(e){return typeof e=="string"&&e.trim()!==""?e.trim():null}function ze(e){try{return G(new URL(e,"http://localhost").searchParams.get($))}catch{return null}}function ae(){var r;let e=A();if(e===null)return null;let t=ze(e.location.href),n;return t!==null&&t!==H(le)?(K(le,t),K(W,t),n=t):n=(r=G(H(W)))!=null?r:t,n!==null&&n===H(De)?null:n}function se(e){let t=G(e);t!==null&&K(W,t)}function de(){let e=A(),t=e==null?void 0:e[Ge];return t?{page:t.page,entries:[...t.entries]}:{page:null,entries:[]}}function ce(){let e=A(),t=e==null?void 0:e[Ye];return t==="active"||t==="invalid"?t:null}var ue="0.4.0";var b=1;var Be=/^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+|\[\d+\])*$/,Xe=/^[\x21-\x7E]+$/;function S(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function je(e){return typeof e=="number"&&Number.isInteger(e)&&e>0}function ye(e){if(typeof e!="string")return null;let t=e.trim();return t===""||t.length>255||!Be.test(t)?null:t}function fe(e){return typeof e=="string"?e.trim().slice(0,120).trim():""}function P(e){if(!S(e))return null;let{type:t,id:n}=e,r=ye(e.field);return t!=="block"&&t!=="entry"||!je(n)||r===null?null:{type:t,id:n,field:r}}function pe(e){let t=P(e);if(t===null||!S(e))return null;let n={...t},r=fe(e.label),i=ye(e.hrefField);if(r!==""&&(n.label=r),i!==null){n.hrefField=i;let o=fe(e.hrefLabel);o!==""&&(n.hrefLabel=o)}return n}function qe(e){if(!S(e)||e.v!==1||typeof e.type!="string")return null;let t=e.payload===void 0?{}:e.payload;return S(t)?{type:e.type,payload:t}:null}function ge(e){let t=qe(e);if(t===null)return null;let{payload:n}=t;switch(t.type){case"crafty:token":{let r=typeof n.token=="string"?n.token.trim():"";return r!==""&&r.length<=4096&&Xe.test(r)?{v:1,type:"crafty:token",payload:{token:r}}:null}case"crafty:refresh":return{v:1,type:"crafty:refresh",payload:{}};case"crafty:highlight":{let r=P(n);return r?{v:1,type:"crafty:highlight",payload:r}:null}case"crafty:preview-field":{let r=P(n),i=n.value;return r&&typeof i=="string"&&i.length<=1e5?{v:1,type:"crafty:preview-field",payload:{...r,value:i}}:null}case"crafty:preview-reset":{let r=P(n);return r?{v:1,type:"crafty:preview-reset",payload:r}:null}default:return null}}var R="[data-crafty-field]";function L(e){var i;let t=e.getAttribute("data-crafty-block"),n=e.getAttribute("data-crafty-entry"),r=t!=null?t:n;return r===null?null:pe({type:t!==null?"block":"entry",id:r.trim()===""?Number.NaN:Number(r),field:(i=e.getAttribute("data-crafty-field"))!=null?i:"",label:e.getAttribute("data-crafty-label"),hrefField:e.getAttribute("data-crafty-href-field"),hrefLabel:e.getAttribute("data-crafty-href-label")})}function E(e){return`${e.type}:${e.id}:${e.field}`}function _(e){let t=[];return e.querySelectorAll(R).forEach(n=>{let r=L(n);r!==null&&t.push({element:n,field:r})}),t}function Y(e){let t=new Set,n=[];for(let{field:r}of e){let i=E(r);t.has(i)||(t.add(i),n.push(r))}return n}function Ee(e){let t=new Map,n=new Map,r=l=>Array.from(e.querySelectorAll(R)).filter(s=>{let d=L(s);return d!==null&&E(d)===l}),i=(l,s)=>{var d;n.has(l)||n.set(l,(d=l.textContent)!=null?d:""),l.textContent!==s&&(l.textContent=s)},o=l=>{for(let[s,d]of n){let y=L(s);(l===null||y!==null&&E(y)===l)&&(s.textContent!==d&&(s.textContent=d),n.delete(s))}};return{set(l,s){let d=E(l);t.set(d,s),r(d).forEach(y=>i(y,s))},reset(l){let s=E(l);t.delete(s),o(s)},reapply(){for(let l of[...n.keys()])l.isConnected||n.delete(l);for(let[l,s]of t)r(l).forEach(d=>i(d,s))},resetAll(){t.clear(),o(null)},get size(){return t.size}}}var ve=[/^https:\/\/([a-z0-9-]+\.)*crafty\.do$/];function he(e){try{return new URL(e).origin}catch{return null}}function me(e,t){return e===""||e==="null"?!1:t.some(n=>typeof n=="string"?he(n)===e:(n.lastIndex=0,n.test(e)))}function be(e){let t=e.location.ancestorOrigins,n=t&&t.length>0?t[0]:void 0;if(typeof n=="string"&&n!=="")return n;let r=e.document.referrer;return r?he(r):null}var Qe="crafty-visual-editing-style",z="#4f46e5",B="crafty-ve-flash",Ze=["[data-crafty-field]{cursor:pointer}",`.crafty-ve-box{position:fixed;top:0;left:0;pointer-events:none;z-index:2147483647;box-sizing:border-box;border:2px solid ${z};border-radius:4px;background:rgba(79,70,229,.06)}`,".crafty-ve-box[hidden]{display:none}",`.crafty-ve-label{position:absolute;left:-2px;bottom:100%;margin-bottom:4px;padding:2px 8px;max-width:320px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:4px;background:${z};color:#fff;font:500 12px/1.5 system-ui,-apple-system,sans-serif}`,`.${B}{outline:2px dashed ${z} !important;outline-offset:2px !important}`].join(`
|
|
2
|
+
`);function ke(e){let t=e.defaultView,n=e.createElement("style");n.id=Qe,n.textContent=Ze;let r=e.createElement("div");r.setAttribute("data-crafty-overlay",""),r.className="crafty-ve-box",r.hidden=!0;let i=e.createElement("span");i.className="crafty-ve-label",r.appendChild(i);let o=null,l=[],s,d=t==null?void 0:t.ResizeObserver,y=()=>{if(o===null)return;let c=o.getBoundingClientRect();r.style.top=`${c.top}px`,r.style.left=`${c.left}px`,r.style.width=`${c.width}px`,r.style.height=`${c.height}px`},f=typeof d=="function"?new d(()=>y()):null,v=c=>{o!==c&&(o!==null&&(f==null||f.unobserve(o)),o=c,o!==null&&(f==null||f.observe(o)))},g=()=>{l.forEach(c=>c.classList.remove(B)),l=[],s!==void 0&&(t==null||t.clearTimeout(s),s=void 0)},m=()=>{var c,h;n.isConnected||((c=e.head)!=null?c:e.documentElement).appendChild(n),r.isConnected||((h=e.body)!=null?h:e.documentElement).appendChild(r)};return m(),t==null||t.addEventListener("scroll",y,{capture:!0,passive:!0}),t==null||t.addEventListener("resize",y,{passive:!0}),{show(c,h){m(),v(c),i.textContent!==h&&(i.textContent=h),r.hidden=!1,y()},hide(){v(null),r.hidden=!0},reposition(){y()},flash(c,h){g(),l=[...c],l.forEach(w=>w.classList.add(B)),s=t==null?void 0:t.setTimeout(g,h)},ensureAttached:m,contains(c){return c!==null&&(r===c||r.contains(c)||n===c||n.contains(c))},destroy(){g(),t==null||t.removeEventListener("scroll",y,{capture:!0}),t==null||t.removeEventListener("resize",y),f==null||f.disconnect(),r.remove(),n.remove(),o=null}}}var j="crafty:scroll-y",Je=50,et=1500,tt=["data-crafty-field","data-crafty-block","data-crafty-entry","data-crafty-label","data-crafty-href-field","data-crafty-href-label"],M={active:!1,disable:()=>{}},k=null;function Re(e={}){var i;if(typeof window=="undefined"||typeof document=="undefined")return M;if(k!==null)return k;let t=window;if(t.parent===null||t.parent===t||ae()===null)return M;let n=be(t);if(n===null||!me(n,(i=e.adminOrigins)!=null?i:ve))return M;let r=ce();return r==="invalid"?(Le(t,n),M):(k=r==="active"?we(t,n,e):nt(t,n,e),k)}function Le(e,t){let n={v:1,type:"crafty:preview-invalid",payload:{}};e.parent.postMessage(n,t)}function nt(e,t,n){var f;let r=null,i=!1,o=()=>{i=!0,e.removeEventListener(D,s),e.removeEventListener(O,d)},l=()=>{k===y&&(k=null)},s=()=>{i||(o(),r=we(e,t,n,l))},d=()=>{i||(o(),l(),Le(e,t))},y={get active(){var v;return(v=r==null?void 0:r.active)!=null?v:!1},disable(){o(),r==null||r.disable(),l()}};return e.addEventListener(D,s),e.addEventListener(O,d),(f=n.client)==null||f.pages.list({per_page:1}).catch(()=>{}),y}function we(e,t,n,r){let i=e.document,o=ke(i),l=Ee(i),s=lt(e),d=[],y=null,f,v=!1,g=!0,m=a=>{e.parent.postMessage(a,t)},c=()=>{var p,C,T;let a=Y(d),u=de();y=Ce(a),m({v:1,type:"crafty:ready",payload:{sdkVersion:ue,path:Ae(e),fields:a,page:(C=(p=u.page)!=null?p:n.page)!=null?C:null,entries:rt(u.entries,(T=n.entries)!=null?T:[])}})},h=()=>{f=void 0,g&&(o.ensureAttached(),d=_(i),l.reapply(),(v||Ce(Y(d))!==y)&&(v=!1,c()))},w=()=>{g&&f===void 0&&(f=e.setTimeout(h,Je))},q=new MutationObserver(a=>{a.some(u=>!o.contains(u.target))&&w()}),N=a=>{var u;return(u=a.label)!=null?u:a.field},Q=a=>{if(a.pointerType==="touch")return;let u=X(a.target);u!==null?o.show(u.element,N(u.field)):o.hide()},x=a=>{a.preventDefault(),a.stopPropagation()},Z=a=>{let u=X(a.target);if(u!==null){x(a),o.show(u.element,N(u.field)),m({v:1,type:"crafty:select",payload:u.field});return}let p=it(a,e);p.kind!=="allow"&&(x(a),p.kind==="navigate"&&m({v:1,type:"crafty:navigate",payload:{path:p.path}}))},J=a=>{(X(a.target)!==null||xe(a.target)!==null)&&x(a)},ee=a=>{x(a)},Pe=a=>{var T;let u=E(a),p=_(i).find(Ne=>E(Ne.field)===u);if(p===void 0)return;let C=p.element;(T=C.scrollIntoView)==null||T.call(C,{block:"center",behavior:"smooth"}),o.show(p.element,N(p.field))},Se=async()=>{if(n.onRefresh){try{await n.onRefresh()}finally{w()}return}try{e.sessionStorage.setItem(j,String(e.scrollY))}catch{}e.location.reload()},Me=a=>{switch(a.type){case"crafty:token":se(a.payload.token);return;case"crafty:refresh":Se().catch(u=>console.error("[crafty] onRefresh failed",u));return;case"crafty:highlight":Pe(a.payload);return;case"crafty:preview-field":l.set(a.payload,a.payload.value),o.reposition();return;case"crafty:preview-reset":l.reset(a.payload),o.reposition();return}},te=a=>{if(a.source!==e.parent||a.origin!==t)return;let u=ge(a.data);u!==null&&Me(u)},ne=()=>{m({v:1,type:"crafty:preview-invalid",payload:{}})},re=()=>{v=!0,w()},V=()=>{var a;g&&(d=_(i),c(),ot(e)&&o.flash(d.map(u=>u.element),(a=n.touchHighlightMs)!=null?a:et),at(e,s))};e.addEventListener("message",te),e.addEventListener("click",Z,!0),e.addEventListener("auxclick",J,!0),e.addEventListener("submit",ee,!0),i.addEventListener("pointerover",Q,!0),e.addEventListener(O,ne),e.addEventListener(U,re),q.observe(i.documentElement,{childList:!0,subtree:!0,attributes:!0,attributeFilter:tt}),i.readyState==="loading"?i.addEventListener("DOMContentLoaded",V,{once:!0}):V();let ie={get active(){return g},disable(){g&&(g=!1,e.removeEventListener("message",te),e.removeEventListener("click",Z,!0),e.removeEventListener("auxclick",J,!0),e.removeEventListener("submit",ee,!0),i.removeEventListener("pointerover",Q,!0),i.removeEventListener("DOMContentLoaded",V),e.removeEventListener(O,ne),e.removeEventListener(U,re),q.disconnect(),f!==void 0&&(e.clearTimeout(f),f=void 0),l.resetAll(),o.destroy(),k===ie&&(k=null),r==null||r())}};return ie}function Te(e){return e!==null&&typeof e.closest=="function"?e:null}function Ce(e){return e.map(t=>{var n,r,i;return`${E(t)}|${(n=t.label)!=null?n:""}|${(r=t.hrefField)!=null?r:""}|${(i=t.hrefLabel)!=null?i:""}`}).join(`
|
|
3
|
+
`)}function rt(e,t){let n=new Set;return[...e,...t].filter(r=>{let i=`${r.collection}:${r.id}`;return n.has(i)?!1:(n.add(i),!0)})}function Oe(e){return e.searchParams.delete($),`${e.pathname}${e.search}`}function Ae(e){return Oe(new URL(e.location.href))}var _e="a[href], area[href]";function X(e){var r,i,o;let t=Te(e);if(t===null)return null;for(let l=t.closest(R);l!==null;l=(i=(r=l.parentElement)==null?void 0:r.closest(R))!=null?i:null){let s=L(l);if(s!==null)return{element:l,field:s}}let n=t.closest(_e);return n!==null&&(o=_(n)[0])!=null?o:null}function xe(e){var t,n;return(n=(t=Te(e))==null?void 0:t.closest(_e))!=null?n:null}function it(e,t){var s;let n=xe(e.target);if(n===null)return{kind:"allow"};if(e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||n.hasAttribute("download"))return{kind:"block"};let r=n.getAttribute("target");if(r!==null&&r!==""&&r!=="_self")return{kind:"block"};let i=(s=n.getAttribute("href"))!=null?s:"",o;try{o=new URL(i,t.location.href)}catch{return{kind:"block"}}if(o.origin!==t.location.origin||o.protocol!=="http:"&&o.protocol!=="https:")return{kind:"block"};let l=Oe(o);return(o.hash!==""||i.startsWith("#"))&&l===Ae(t)?{kind:"allow"}:{kind:"navigate",path:l}}function ot(e){return typeof e.matchMedia=="function"&&e.matchMedia("(hover: none)").matches}function lt(e){try{let t=e.sessionStorage.getItem(j);e.sessionStorage.removeItem(j);let n=t===null?Number.NaN:Number(t);return Number.isFinite(n)?n:null}catch{return null}}function at(e,t){if(t===null)return;let n=()=>e.scrollTo(0,t);e.document.readyState==="complete"?n():e.addEventListener("load",n,{once:!0})}return Ke(st);})();
|
|
4
4
|
//# sourceMappingURL=crafty-visual-editing.global.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/cdn.ts", "../src/attrs.ts", "../src/preview.ts", "../src/version.ts", "../src/visual-editing/protocol.ts", "../src/visual-editing/markers.ts", "../src/visual-editing/live-preview.ts", "../src/visual-editing/origin.ts", "../src/visual-editing/overlay.ts", "../src/visual-editing/bridge.ts"],
|
|
4
|
-
"sourcesContent": ["/** Entry for the `<script>` build: exposed as `window.CraftyVisualEditing`. */\nexport { attrs, attrsHtml } from \"./attrs.js\";\nexport { enableVisualEditing } from \"./visual-editing/bridge.js\";\nexport { PROTOCOL_VERSION } from \"./visual-editing/protocol.js\";\n", "import type { CraftyBlock, CraftyEntry } from \"./types/public.js\";\n\nexport type CraftyEditTargetType = \"block\" | \"entry\";\n\n/**\n * A block or entry as returned by the API, or an explicit reference for\n * ambiguous shapes (e.g. an entry with fields named `order`, `data` and `type`).\n */\nexport type CraftyEditTarget =\n | CraftyBlock\n | CraftyEntry\n | { kind: CraftyEditTargetType; id: number | string };\n\nexport type CraftyAttrsOptions = {\n /** Human label shown by the visual editor, e.g. \"T\u00EDtulo de la secci\u00F3n\". */\n label?: string;\n};\n\nexport type CraftyEditAttributes = {\n \"data-crafty-block\"?: string;\n \"data-crafty-entry\"?: string;\n \"data-crafty-field\"?: string;\n \"data-crafty-label\"?: string;\n};\n\nexport function resolveEditTarget(\n target: CraftyEditTarget | null | undefined\n): { type: CraftyEditTargetType; id: number } | null {\n if (target === null || target === undefined || typeof target !== \"object\") {\n return null;\n }\n\n const record = target as Record<string, unknown>;\n const id = typeof record.id === \"string\" ? Number(record.id.trim()) : record.id;\n\n if (typeof id !== \"number\" || !Number.isInteger(id) || id <= 0) {\n return null;\n }\n\n if (record.kind === \"block\" || record.kind === \"entry\") {\n return { type: record.kind, id };\n }\n\n const looksLikeBlock =\n typeof record.order === \"number\" &&\n typeof record.data === \"object\" &&\n record.data !== null &&\n \"type\" in record;\n\n return { type: looksLikeBlock ? \"block\" : \"entry\", id };\n}\n\n/**\n * DOM attributes that let the visual editor map an element to a field.\n * Always emitted (static sites render them at build time without a token).\n * `field` is a top-level field key or a JSON path such as `sections[3].title`.\n */\nexport function attrs(\n target: CraftyEditTarget | null | undefined,\n field: string,\n options: CraftyAttrsOptions = {}\n): CraftyEditAttributes {\n const resolved = resolveEditTarget(target);\n const normalizedField = typeof field === \"string\" ? field.trim() : \"\";\n\n if (resolved === null || normalizedField === \"\") {\n return {};\n }\n\n const attributes: CraftyEditAttributes =\n resolved.type === \"block\"\n ? { \"data-crafty-block\": String(resolved.id), \"data-crafty-field\": normalizedField }\n : { \"data-crafty-entry\": String(resolved.id), \"data-crafty-field\": normalizedField };\n\n const label = typeof options.label === \"string\" ? options.label.trim() : \"\";\n\n if (label !== \"\") {\n attributes[\"data-crafty-label\"] = label;\n }\n\n return attributes;\n}\n\n/** Same as `attrs()`, rendered for HTML string templates. */\nexport function attrsHtml(\n target: CraftyEditTarget | null | undefined,\n field: string,\n options: CraftyAttrsOptions = {}\n): string {\n return Object.entries(attrs(target, field, options))\n .map(([name, value]) => `${name}=\"${escapeAttribute(String(value))}\"`)\n .join(\" \");\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n", "export const PREVIEW_QUERY_PARAM = \"crafty_preview\";\nexport const PREVIEW_HEADER = \"X-Crafty-Preview\";\nexport const PREVIEW_STATUS_HEADER = \"X-Crafty-Preview-Status\";\nexport const PREVIEW_INVALID_EVENT = \"crafty:preview-invalid\";\nexport const PREVIEW_CONTENT_EVENT = \"crafty:preview-content\";\nexport const PREVIEW_ACTIVE_EVENT = \"crafty:preview-active\";\n\nconst TOKEN_STORAGE_KEY = \"crafty:preview-token\";\nconst URL_TOKEN_STORAGE_KEY = \"crafty:preview-url-token\";\nconst INVALID_TOKEN_STORAGE_KEY = \"crafty:preview-invalid-token\";\nconst CONTENT_GLOBAL_KEY = \"__CRAFTY_PREVIEW_CONTENT__\";\nconst STATUS_GLOBAL_KEY = \"__CRAFTY_PREVIEW_STATUS__\";\n\nexport type PreviewPage = { id: number; slug: string };\nexport type PreviewEntry = { id: number; collection: string };\nexport type PreviewContent = { page: PreviewPage | null; entries: PreviewEntry[] };\n/** Last `X-Crafty-Preview-Status` the API answered in this window, or null before any preview request. */\nexport type PreviewStatus = \"active\" | \"invalid\";\n\n/** A URL, a Web `Request`, a Node `IncomingMessage` or an Express-style request. */\nexport type PreviewRequestLike =\n | string\n | URL\n | { url?: string | undefined; query?: Record<string, unknown> | undefined };\n\ntype ContentHost = Record<string, PreviewContent | undefined>;\n\nfunction browserWindow(): Window | null {\n return typeof window === \"undefined\" ? null : window;\n}\n\nfunction storageGet(key: string): string | null {\n try {\n return browserWindow()?.sessionStorage.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction storageSet(key: string, value: string): void {\n try {\n browserWindow()?.sessionStorage.setItem(key, value);\n } catch {\n // Storage can be blocked (private mode, sandboxed frames); the URL token still works.\n }\n}\n\nfunction storageRemove(key: string): void {\n try {\n browserWindow()?.sessionStorage.removeItem(key);\n } catch {\n // Ignore blocked storage.\n }\n}\n\nfunction normalizeToken(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() !== \"\" ? value.trim() : null;\n}\n\nfunction tokenFromUrl(url: string): string | null {\n try {\n return normalizeToken(new URL(url, \"http://localhost\").searchParams.get(PREVIEW_QUERY_PARAM));\n } catch {\n return null;\n }\n}\n\n/**\n * Preview token for browser requests. A token the URL brings for the first time\n * wins; afterwards the stored token wins, so a renewal received over\n * `postMessage` is not overwritten by the stale token still in the URL.\n */\nexport function readPreviewToken(): string | null {\n const win = browserWindow();\n\n if (win === null) {\n return null;\n }\n\n const urlToken = tokenFromUrl(win.location.href);\n let token: string | null;\n\n if (urlToken !== null && urlToken !== storageGet(URL_TOKEN_STORAGE_KEY)) {\n storageSet(URL_TOKEN_STORAGE_KEY, urlToken);\n storageSet(TOKEN_STORAGE_KEY, urlToken);\n token = urlToken;\n } else {\n token = normalizeToken(storageGet(TOKEN_STORAGE_KEY)) ?? urlToken;\n }\n\n return token !== null && token === storageGet(INVALID_TOKEN_STORAGE_KEY) ? null : token;\n}\n\n/**\n * Forgets a browser token the API reported invalid, so later requests stop\n * sending it (the stale copy in the URL included) until a new token arrives\n * over `postMessage` or a new URL. Explicit server-side tokens are untouched.\n */\nexport function discardPreviewToken(token: string): void {\n const win = browserWindow();\n const normalized = normalizeToken(token);\n\n if (win === null || normalized === null) {\n return;\n }\n\n const isStored = normalizeToken(storageGet(TOKEN_STORAGE_KEY)) === normalized;\n\n if (!isStored && tokenFromUrl(win.location.href) !== normalized) {\n return;\n }\n\n if (isStored) {\n storageRemove(TOKEN_STORAGE_KEY);\n }\n\n storageSet(INVALID_TOKEN_STORAGE_KEY, normalized);\n}\n\nexport function storePreviewToken(token: string): void {\n const normalized = normalizeToken(token);\n\n if (normalized !== null) {\n storageSet(TOKEN_STORAGE_KEY, normalized);\n }\n}\n\nexport function clearPreviewToken(): void {\n storageRemove(TOKEN_STORAGE_KEY);\n storageRemove(URL_TOKEN_STORAGE_KEY);\n storageRemove(INVALID_TOKEN_STORAGE_KEY);\n setPreviewStatus(null);\n}\n\n/** Server-side helper: the preview token of an incoming request, or null. */\nexport function previewFromRequest(request: PreviewRequestLike | null | undefined): string | null {\n if (request === null || request === undefined) {\n return null;\n }\n\n if (typeof request === \"string\" || request instanceof URL) {\n return tokenFromUrl(String(request));\n }\n\n const queryValue = request.query?.[PREVIEW_QUERY_PARAM];\n const fromQuery = normalizeToken(Array.isArray(queryValue) ? queryValue[0] : queryValue);\n\n if (fromQuery !== null) {\n return fromQuery;\n }\n\n return typeof request.url === \"string\" ? tokenFromUrl(request.url) : null;\n}\n\nexport function getPreviewContent(): PreviewContent {\n const win = browserWindow() as (Window & ContentHost) | null;\n const content = win?.[CONTENT_GLOBAL_KEY];\n\n return content ? { page: content.page, entries: [...content.entries] } : { page: null, entries: [] };\n}\n\nexport function recordPreviewContent(\n item: ({ type: \"page\" } & PreviewPage) | ({ type: \"entry\" } & PreviewEntry)\n): void {\n const win = browserWindow() as (Window & ContentHost) | null;\n\n if (win === null) {\n return;\n }\n\n const content = win[CONTENT_GLOBAL_KEY] ?? { page: null, entries: [] };\n win[CONTENT_GLOBAL_KEY] = content;\n\n if (item.type === \"page\") {\n content.page = { id: item.id, slug: item.slug };\n } else if (!content.entries.some((entry) => entry.id === item.id && entry.collection === item.collection)) {\n content.entries.push({ id: item.id, collection: item.collection });\n }\n\n dispatch(PREVIEW_CONTENT_EVENT);\n}\n\nexport function resetPreviewContent(): void {\n const win = browserWindow() as (Window & ContentHost) | null;\n\n if (win !== null) {\n win[CONTENT_GLOBAL_KEY] = undefined;\n }\n}\n\n/**\n * Kept on `window` (like the shown content) so a separately bundled bridge, such\n * as the `<script>` build, sees what the site's own SDK copy recorded.\n */\nexport function getPreviewStatus(): PreviewStatus | null {\n const win = browserWindow() as (Window & Record<string, unknown>) | null;\n const status = win?.[STATUS_GLOBAL_KEY];\n\n return status === \"active\" || status === \"invalid\" ? status : null;\n}\n\nfunction setPreviewStatus(status: PreviewStatus | null): void {\n const win = browserWindow() as (Window & Record<string, unknown>) | null;\n\n if (win !== null) {\n win[STATUS_GLOBAL_KEY] = status ?? undefined;\n }\n}\n\nexport function notifyPreviewActive(): void {\n setPreviewStatus(\"active\");\n dispatch(PREVIEW_ACTIVE_EVENT);\n}\n\nexport function notifyPreviewInvalid(): void {\n setPreviewStatus(\"invalid\");\n dispatch(PREVIEW_INVALID_EVENT);\n}\n\nfunction dispatch(name: string): void {\n const win = browserWindow();\n\n if (win !== null && typeof win.dispatchEvent === \"function\") {\n win.dispatchEvent(new Event(name));\n }\n}\n", "// Generated by scripts/write-version.mjs from package.json. Do not edit.\nexport const SDK_VERSION = \"0.3.0\";\n", "export const PROTOCOL_VERSION = 1;\n\nexport type CraftyTargetType = \"block\" | \"entry\";\nexport type CraftyFieldRef = { type: CraftyTargetType; id: number; field: string };\nexport type CraftyMarkedField = CraftyFieldRef & { label?: string };\nexport type CraftyShownPage = { id: number; slug: string };\nexport type CraftyShownEntry = { id: number; collection: string };\n\nexport type ReadyPayload = {\n sdkVersion: string;\n path: string;\n fields: CraftyMarkedField[];\n page: CraftyShownPage | null;\n entries: CraftyShownEntry[];\n};\n\ntype Version = typeof PROTOCOL_VERSION;\ntype EmptyPayload = Record<string, never>;\n\n/** iframe -> admin. `crafty:ready` is a snapshot that may be re-sent; the last one wins. */\nexport type OutboundMessage =\n | { v: Version; type: \"crafty:ready\"; payload: ReadyPayload }\n | { v: Version; type: \"crafty:select\"; payload: CraftyMarkedField }\n | { v: Version; type: \"crafty:navigate\"; payload: { path: string } }\n | { v: Version; type: \"crafty:preview-invalid\"; payload: EmptyPayload };\n\n/** admin -> iframe. */\nexport type InboundMessage =\n | { v: Version; type: \"crafty:token\"; payload: { token: string } }\n | { v: Version; type: \"crafty:refresh\"; payload: EmptyPayload }\n | { v: Version; type: \"crafty:highlight\"; payload: CraftyFieldRef }\n | { v: Version; type: \"crafty:preview-field\"; payload: CraftyFieldRef & { value: string } }\n | { v: Version; type: \"crafty:preview-reset\"; payload: CraftyFieldRef };\n\n/** Same limits as the Crafty admin and backend (content_drafts.field / label). */\nconst MAX_FIELD_LENGTH = 255;\nconst MAX_LABEL_LENGTH = 120;\nconst MAX_TOKEN_LENGTH = 4096;\nconst MAX_VALUE_LENGTH = 100_000;\nconst MAX_PATH_LENGTH = 2048;\nconst FIELD_PATTERN = /^[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+|\\[\\d+\\])*$/;\nconst TOKEN_PATTERN = /^[\\x21-\\x7E]+$/;\nconst CONTROL_CHARACTERS = /[\\u0000-\\u001F\\u007F]/;\nconst PATH_BASE = \"https://crafty.invalid\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPositiveInteger(value: unknown): value is number {\n return typeof value === \"number\" && Number.isInteger(value) && value > 0;\n}\n\nexport function parseFieldRef(value: unknown): CraftyFieldRef | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const { type, id, field } = value;\n\n if ((type !== \"block\" && type !== \"entry\") || !isPositiveInteger(id) || typeof field !== \"string\") {\n return null;\n }\n\n const trimmed = field.trim();\n\n return trimmed === \"\" || trimmed.length > MAX_FIELD_LENGTH || !FIELD_PATTERN.test(trimmed)\n ? null\n : { type, id, field: trimmed };\n}\n\nexport function parseMarkedField(value: unknown): CraftyMarkedField | null {\n const ref = parseFieldRef(value);\n\n if (ref === null) {\n return null;\n }\n\n const rawLabel = isRecord(value) ? value.label : undefined;\n const label = typeof rawLabel === \"string\" ? rawLabel.trim().slice(0, MAX_LABEL_LENGTH).trim() : \"\";\n\n return label === \"\" ? ref : { ...ref, label };\n}\n\nfunction isSameOriginPath(value: string): boolean {\n if (!value.startsWith(\"/\") || value.startsWith(\"//\") || value.startsWith(\"/\\\\\")) {\n return false;\n }\n\n try {\n const url = new URL(value, PATH_BASE);\n\n // Dot segments can still resolve to a protocol-relative path (\"/.//evil.example\").\n return url.origin === PATH_BASE && !url.pathname.startsWith(\"//\") && !url.pathname.startsWith(\"/\\\\\");\n } catch {\n return false;\n }\n}\n\nfunction parsePath(value: unknown): string | null {\n if (typeof value !== \"string\" || value.length > MAX_PATH_LENGTH || CONTROL_CHARACTERS.test(value)) {\n return null;\n }\n\n return isSameOriginPath(value) ? value : null;\n}\n\nfunction parseShownEntry(value: unknown): CraftyShownEntry | null {\n return isRecord(value) && isPositiveInteger(value.id) && typeof value.collection === \"string\"\n ? { id: value.id, collection: value.collection }\n : null;\n}\n\nfunction readEnvelope(data: unknown): { type: string; payload: Record<string, unknown> } | null {\n if (!isRecord(data) || data.v !== PROTOCOL_VERSION || typeof data.type !== \"string\") {\n return null;\n }\n\n const payload = data.payload === undefined ? {} : data.payload;\n\n return isRecord(payload) ? { type: data.type, payload } : null;\n}\n\nexport function parseInboundMessage(data: unknown): InboundMessage | null {\n const message = readEnvelope(data);\n\n if (message === null) {\n return null;\n }\n\n const { payload } = message;\n\n switch (message.type) {\n case \"crafty:token\": {\n const token = typeof payload.token === \"string\" ? payload.token.trim() : \"\";\n\n return token !== \"\" && token.length <= MAX_TOKEN_LENGTH && TOKEN_PATTERN.test(token)\n ? { v: PROTOCOL_VERSION, type: \"crafty:token\", payload: { token } }\n : null;\n }\n case \"crafty:refresh\":\n return { v: PROTOCOL_VERSION, type: \"crafty:refresh\", payload: {} };\n case \"crafty:highlight\": {\n const ref = parseFieldRef(payload);\n\n return ref ? { v: PROTOCOL_VERSION, type: \"crafty:highlight\", payload: ref } : null;\n }\n case \"crafty:preview-field\": {\n const ref = parseFieldRef(payload);\n const value = payload.value;\n\n return ref && typeof value === \"string\" && value.length <= MAX_VALUE_LENGTH\n ? { v: PROTOCOL_VERSION, type: \"crafty:preview-field\", payload: { ...ref, value } }\n : null;\n }\n case \"crafty:preview-reset\": {\n const ref = parseFieldRef(payload);\n\n return ref ? { v: PROTOCOL_VERSION, type: \"crafty:preview-reset\", payload: ref } : null;\n }\n default:\n return null;\n }\n}\n\nexport function parseOutboundMessage(data: unknown): OutboundMessage | null {\n const message = readEnvelope(data);\n\n if (message === null) {\n return null;\n }\n\n const { payload } = message;\n\n switch (message.type) {\n case \"crafty:ready\": {\n const path = parsePath(payload.path);\n const rawPage = payload.page;\n\n if (typeof payload.sdkVersion !== \"string\" || path === null || !Array.isArray(payload.fields) || !Array.isArray(payload.entries)) {\n return null;\n }\n\n return {\n v: PROTOCOL_VERSION,\n type: \"crafty:ready\",\n payload: {\n sdkVersion: payload.sdkVersion,\n path,\n fields: payload.fields\n .map((field: unknown) => parseMarkedField(field))\n .filter((field): field is CraftyMarkedField => field !== null),\n page:\n isRecord(rawPage) && isPositiveInteger(rawPage.id) && typeof rawPage.slug === \"string\"\n ? { id: rawPage.id, slug: rawPage.slug }\n : null,\n entries: payload.entries\n .map((entry: unknown) => parseShownEntry(entry))\n .filter((entry): entry is CraftyShownEntry => entry !== null)\n }\n };\n }\n case \"crafty:select\": {\n const field = parseMarkedField(payload);\n\n return field ? { v: PROTOCOL_VERSION, type: \"crafty:select\", payload: field } : null;\n }\n case \"crafty:navigate\": {\n const path = parsePath(payload.path);\n\n return path ? { v: PROTOCOL_VERSION, type: \"crafty:navigate\", payload: { path } } : null;\n }\n case \"crafty:preview-invalid\":\n return { v: PROTOCOL_VERSION, type: \"crafty:preview-invalid\", payload: {} };\n default:\n return null;\n }\n}\n", "import { parseMarkedField, type CraftyFieldRef, type CraftyMarkedField } from \"./protocol.js\";\n\nexport const MARKED_SELECTOR = \"[data-crafty-field]\";\n\nexport type MarkedElement = { element: Element; field: CraftyMarkedField };\n\nexport function readMarkedField(element: Element): CraftyMarkedField | null {\n const blockId = element.getAttribute(\"data-crafty-block\");\n const entryId = element.getAttribute(\"data-crafty-entry\");\n const rawId = blockId ?? entryId;\n\n if (rawId === null) {\n return null;\n }\n\n const label = element.getAttribute(\"data-crafty-label\");\n\n return parseMarkedField({\n type: blockId !== null ? \"block\" : \"entry\",\n id: rawId.trim() === \"\" ? Number.NaN : Number(rawId),\n field: element.getAttribute(\"data-crafty-field\") ?? \"\",\n ...(label !== null ? { label } : {})\n });\n}\n\nexport function refKey(ref: CraftyFieldRef): string {\n return `${ref.type}:${ref.id}:${ref.field}`;\n}\n\nexport function scanMarked(root: ParentNode): MarkedElement[] {\n const marked: MarkedElement[] = [];\n\n root.querySelectorAll(MARKED_SELECTOR).forEach((element) => {\n const field = readMarkedField(element);\n\n if (field !== null) {\n marked.push({ element, field });\n }\n });\n\n return marked;\n}\n\nexport function uniqueFields(marked: MarkedElement[]): CraftyMarkedField[] {\n const seen = new Set<string>();\n const fields: CraftyMarkedField[] = [];\n\n for (const { field } of marked) {\n const key = refKey(field);\n\n if (!seen.has(key)) {\n seen.add(key);\n fields.push(field);\n }\n }\n\n return fields;\n}\n", "import { MARKED_SELECTOR, readMarkedField, refKey } from \"./markers.js\";\nimport type { CraftyFieldRef } from \"./protocol.js\";\n\nexport type LivePreview = {\n set(ref: CraftyFieldRef, value: string): void;\n reset(ref: CraftyFieldRef): void;\n reapply(): void;\n resetAll(): void;\n readonly size: number;\n};\n\n/**\n * Plain-text live preview. Values are written with `textContent` (never HTML),\n * and each element's own original text is kept so a reset restores exactly what\n * the site rendered, even for elements rendered after the value was set.\n */\nexport function createLivePreview(root: ParentNode): LivePreview {\n const values = new Map<string, string>();\n const originals = new Map<Element, string>();\n\n const matching = (key: string): Element[] =>\n Array.from(root.querySelectorAll(MARKED_SELECTOR)).filter((element) => {\n const field = readMarkedField(element);\n\n return field !== null && refKey(field) === key;\n });\n\n const write = (element: Element, value: string): void => {\n if (!originals.has(element)) {\n originals.set(element, element.textContent ?? \"\");\n }\n\n if (element.textContent !== value) {\n element.textContent = value;\n }\n };\n\n const restore = (key: string | null): void => {\n for (const [element, original] of originals) {\n const field = readMarkedField(element);\n\n if (key === null || (field !== null && refKey(field) === key)) {\n if (element.textContent !== original) {\n element.textContent = original;\n }\n\n originals.delete(element);\n }\n }\n };\n\n return {\n set(ref, value) {\n const key = refKey(ref);\n values.set(key, value);\n matching(key).forEach((element) => write(element, value));\n },\n reset(ref) {\n const key = refKey(ref);\n values.delete(key);\n restore(key);\n },\n reapply() {\n for (const element of [...originals.keys()]) {\n if (!element.isConnected) {\n originals.delete(element);\n }\n }\n\n for (const [key, value] of values) {\n matching(key).forEach((element) => write(element, value));\n }\n },\n resetAll() {\n values.clear();\n restore(null);\n },\n get size() {\n return values.size;\n }\n };\n}\n", "/** Crafty admin panels: https://crafty.do and https://<tenant>.crafty.do. */\nexport const DEFAULT_ADMIN_ORIGINS: ReadonlyArray<string | RegExp> = [/^https:\\/\\/([a-z0-9-]+\\.)*crafty\\.do$/];\n\nfunction originOf(value: string): string | null {\n try {\n return new URL(value).origin;\n } catch {\n return null;\n }\n}\n\nexport function isAllowedAdminOrigin(origin: string, allowlist: ReadonlyArray<string | RegExp>): boolean {\n if (origin === \"\" || origin === \"null\") {\n return false;\n }\n\n return allowlist.some((allowed) => {\n if (typeof allowed === \"string\") {\n return originOf(allowed) === origin;\n }\n\n allowed.lastIndex = 0;\n\n return allowed.test(origin);\n });\n}\n\n/**\n * Origin of the embedding admin. `ancestorOrigins` (Chromium, WebKit) cannot be\n * spoofed by the framed page; Firefox falls back to the referrer the admin sent\n * when it set the iframe `src`.\n */\nexport function resolveParentOrigin(win: Window): string | null {\n const ancestors = win.location.ancestorOrigins as ArrayLike<string> | undefined;\n const first = ancestors && ancestors.length > 0 ? ancestors[0] : undefined;\n\n if (typeof first === \"string\" && first !== \"\") {\n return first;\n }\n\n const referrer = win.document.referrer;\n\n return referrer ? originOf(referrer) : null;\n}\n", "const STYLE_ELEMENT_ID = \"crafty-visual-editing-style\";\nconst ACCENT = \"#4f46e5\";\n\nexport const FLASH_CLASS = \"crafty-ve-flash\";\n\nconst STYLES = [\n \"[data-crafty-field]{cursor:pointer}\",\n `.crafty-ve-box{position:fixed;top:0;left:0;pointer-events:none;z-index:2147483647;box-sizing:border-box;border:2px solid ${ACCENT};border-radius:4px;background:rgba(79,70,229,.06)}`,\n \".crafty-ve-box[hidden]{display:none}\",\n `.crafty-ve-label{position:absolute;left:-2px;bottom:100%;margin-bottom:4px;padding:2px 8px;max-width:320px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:4px;background:${ACCENT};color:#fff;font:500 12px/1.5 system-ui,-apple-system,sans-serif}`,\n `.${FLASH_CLASS}{outline:2px dashed ${ACCENT} !important;outline-offset:2px !important}`\n].join(\"\\n\");\n\nexport type Overlay = {\n show(element: Element, label: string): void;\n hide(): void;\n /** Re-measures the highlighted element, e.g. after its content changed. */\n reposition(): void;\n flash(elements: Element[], durationMs: number): void;\n ensureAttached(): void;\n contains(node: Node | null): boolean;\n destroy(): void;\n};\n\nexport function createOverlay(doc: Document): Overlay {\n const win = doc.defaultView;\n const style = doc.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = STYLES;\n\n const box = doc.createElement(\"div\");\n box.setAttribute(\"data-crafty-overlay\", \"\");\n box.className = \"crafty-ve-box\";\n box.hidden = true;\n\n const label = doc.createElement(\"span\");\n label.className = \"crafty-ve-label\";\n box.appendChild(label);\n\n let target: Element | null = null;\n let flashed: Element[] = [];\n let flashTimer: number | undefined;\n const Observer = (win as (Window & { ResizeObserver?: typeof ResizeObserver }) | null)?.ResizeObserver;\n\n const place = (): void => {\n if (target === null) {\n return;\n }\n\n const rect = target.getBoundingClientRect();\n box.style.top = `${rect.top}px`;\n box.style.left = `${rect.left}px`;\n box.style.width = `${rect.width}px`;\n box.style.height = `${rect.height}px`;\n };\n\n const resizeObserver = typeof Observer === \"function\" ? new Observer(() => place()) : null;\n\n const track = (element: Element | null): void => {\n if (target === element) {\n return;\n }\n\n if (target !== null) {\n resizeObserver?.unobserve(target);\n }\n\n target = element;\n\n if (target !== null) {\n resizeObserver?.observe(target);\n }\n };\n\n const clearFlash = (): void => {\n flashed.forEach((element) => element.classList.remove(FLASH_CLASS));\n flashed = [];\n\n if (flashTimer !== undefined) {\n win?.clearTimeout(flashTimer);\n flashTimer = undefined;\n }\n };\n\n const ensureAttached = (): void => {\n if (!style.isConnected) {\n (doc.head ?? doc.documentElement).appendChild(style);\n }\n\n if (!box.isConnected) {\n (doc.body ?? doc.documentElement).appendChild(box);\n }\n };\n\n ensureAttached();\n win?.addEventListener(\"scroll\", place, { capture: true, passive: true });\n win?.addEventListener(\"resize\", place, { passive: true });\n\n return {\n show(element, text) {\n ensureAttached();\n track(element);\n\n if (label.textContent !== text) {\n label.textContent = text;\n }\n\n box.hidden = false;\n place();\n },\n hide() {\n track(null);\n box.hidden = true;\n },\n reposition() {\n place();\n },\n flash(elements, durationMs) {\n clearFlash();\n flashed = [...elements];\n flashed.forEach((element) => element.classList.add(FLASH_CLASS));\n flashTimer = win?.setTimeout(clearFlash, durationMs);\n },\n ensureAttached,\n contains(node) {\n return node !== null && (box === node || box.contains(node) || style === node || style.contains(node));\n },\n destroy() {\n clearFlash();\n win?.removeEventListener(\"scroll\", place, { capture: true });\n win?.removeEventListener(\"resize\", place);\n resizeObserver?.disconnect();\n box.remove();\n style.remove();\n target = null;\n }\n };\n}\n", "import type { CraftyClient } from \"../client.js\";\nimport {\n PREVIEW_ACTIVE_EVENT,\n PREVIEW_CONTENT_EVENT,\n PREVIEW_INVALID_EVENT,\n PREVIEW_QUERY_PARAM,\n getPreviewContent,\n getPreviewStatus,\n readPreviewToken,\n storePreviewToken\n} from \"../preview.js\";\nimport { SDK_VERSION } from \"../version.js\";\nimport { createLivePreview } from \"./live-preview.js\";\nimport { MARKED_SELECTOR, readMarkedField, refKey, scanMarked, uniqueFields, type MarkedElement } from \"./markers.js\";\nimport { DEFAULT_ADMIN_ORIGINS, isAllowedAdminOrigin, resolveParentOrigin } from \"./origin.js\";\nimport { createOverlay } from \"./overlay.js\";\nimport {\n PROTOCOL_VERSION,\n parseInboundMessage,\n type CraftyFieldRef,\n type CraftyMarkedField,\n type CraftyShownEntry,\n type CraftyShownPage,\n type InboundMessage,\n type OutboundMessage\n} from \"./protocol.js\";\n\nexport type VisualEditingOptions = {\n /** Allowed admin origins. Replaces the default (`https://*.crafty.do`). */\n adminOrigins?: ReadonlyArray<string | RegExp>;\n /** Re-fetch and re-render instead of a full reload when the admin asks for a refresh. */\n onRefresh?: () => void | Promise<void>;\n /** Page rendered by the server (SSR sites, where the browser did not fetch it). */\n page?: CraftyShownPage | null;\n /** Entries rendered by the server (SSR sites). */\n entries?: CraftyShownEntry[];\n /** How long touch devices highlight every editable after load. Default 1500 ms. */\n touchHighlightMs?: number;\n /**\n * Client used to confirm the preview token when no preview request has been\n * answered yet (one `pages.list({ per_page: 1 })` call). Without it the bridge\n * waits for the site's own first Crafty request to confirm the token.\n */\n client?: Pick<CraftyClient, \"pages\">;\n};\n\nexport type VisualEditingHandle = {\n readonly active: boolean;\n disable(): void;\n};\n\nconst SCROLL_STORAGE_KEY = \"crafty:scroll-y\";\nconst RESCAN_DELAY_MS = 50;\nconst DEFAULT_TOUCH_HIGHLIGHT_MS = 1500;\nconst WATCHED_ATTRIBUTES = [\"data-crafty-field\", \"data-crafty-block\", \"data-crafty-entry\", \"data-crafty-label\"];\n\nconst inactiveHandle: VisualEditingHandle = { active: false, disable: () => undefined };\nlet activeHandle: VisualEditingHandle | null = null;\n\n/**\n * Connects the page to the Crafty visual editor. No-op unless the page runs in\n * an iframe, carries a preview token, and its parent is an allowed admin origin.\n *\n * The default allowlist (`*.crafty.do`) also covers sites hosted by Crafty, so\n * the bridge stays inert (no overlay, no listeners, no messages) until the API\n * answers a preview request with `X-Crafty-Preview-Status: active`. On `invalid`\n * it only tells the admin `crafty:preview-invalid` and stays inert.\n */\nexport function enableVisualEditing(options: VisualEditingOptions = {}): VisualEditingHandle {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return inactiveHandle;\n }\n\n if (activeHandle !== null) {\n return activeHandle;\n }\n\n const win = window;\n\n if (win.parent === null || win.parent === win || readPreviewToken() === null) {\n return inactiveHandle;\n }\n\n const parentOrigin = resolveParentOrigin(win);\n\n if (parentOrigin === null || !isAllowedAdminOrigin(parentOrigin, options.adminOrigins ?? DEFAULT_ADMIN_ORIGINS)) {\n return inactiveHandle;\n }\n\n const status = getPreviewStatus();\n\n if (status === \"invalid\") {\n postPreviewInvalid(win, parentOrigin);\n\n return inactiveHandle;\n }\n\n activeHandle = status === \"active\" ? startBridge(win, parentOrigin, options) : awaitConfirmation(win, parentOrigin, options);\n\n return activeHandle;\n}\n\nfunction postPreviewInvalid(win: Window, parentOrigin: string): void {\n const message: OutboundMessage = { v: PROTOCOL_VERSION, type: \"crafty:preview-invalid\", payload: {} };\n win.parent.postMessage(message, parentOrigin);\n}\n\n/**\n * Pending handle: waits for the API to confirm the token before starting the\n * bridge, verifying it through `options.client` when one is given.\n */\nfunction awaitConfirmation(win: Window, parentOrigin: string, options: VisualEditingOptions): VisualEditingHandle {\n let bridge: VisualEditingHandle | null = null;\n let settled = false;\n\n const stopWaiting = (): void => {\n settled = true;\n win.removeEventListener(PREVIEW_ACTIVE_EVENT, onActive);\n win.removeEventListener(PREVIEW_INVALID_EVENT, onInvalid);\n };\n\n const release = (): void => {\n if (activeHandle === handle) {\n activeHandle = null;\n }\n };\n\n const onActive = (): void => {\n if (settled) {\n return;\n }\n\n stopWaiting();\n bridge = startBridge(win, parentOrigin, options, release);\n };\n\n const onInvalid = (): void => {\n if (settled) {\n return;\n }\n\n stopWaiting();\n release();\n postPreviewInvalid(win, parentOrigin);\n };\n\n const handle: VisualEditingHandle = {\n get active() {\n return bridge?.active ?? false;\n },\n disable() {\n stopWaiting();\n bridge?.disable();\n release();\n }\n };\n\n win.addEventListener(PREVIEW_ACTIVE_EVENT, onActive);\n win.addEventListener(PREVIEW_INVALID_EVENT, onInvalid);\n\n // The status handlers above settle the outcome; request errors leave the bridge waiting.\n options.client?.pages.list({ per_page: 1 }).catch(() => undefined);\n\n return handle;\n}\n\nfunction startBridge(\n win: Window,\n parentOrigin: string,\n options: VisualEditingOptions,\n onDisable?: () => void\n): VisualEditingHandle {\n const doc = win.document;\n const overlay = createOverlay(doc);\n const livePreview = createLivePreview(doc);\n const pendingScrollY = takeStoredScroll(win);\n\n let marked: MarkedElement[] = [];\n let sentSignature: string | null = null;\n let rescanTimer: number | undefined;\n let forceReady = false;\n let active = true;\n\n const post = (message: OutboundMessage): void => {\n win.parent.postMessage(message, parentOrigin);\n };\n\n const sendReady = (): void => {\n const fields = uniqueFields(marked);\n const content = getPreviewContent();\n sentSignature = signatureOf(fields);\n\n post({\n v: PROTOCOL_VERSION,\n type: \"crafty:ready\",\n payload: {\n sdkVersion: SDK_VERSION,\n path: currentPath(win),\n fields,\n page: content.page ?? options.page ?? null,\n entries: mergeEntries(content.entries, options.entries ?? [])\n }\n });\n };\n\n const rescan = (): void => {\n rescanTimer = undefined;\n\n if (!active) {\n return;\n }\n\n overlay.ensureAttached();\n marked = scanMarked(doc);\n livePreview.reapply();\n\n if (forceReady || signatureOf(uniqueFields(marked)) !== sentSignature) {\n forceReady = false;\n sendReady();\n }\n };\n\n const scheduleRescan = (): void => {\n if (active && rescanTimer === undefined) {\n rescanTimer = win.setTimeout(rescan, RESCAN_DELAY_MS);\n }\n };\n\n const observer = new MutationObserver((records) => {\n if (records.some((record) => !overlay.contains(record.target))) {\n scheduleRescan();\n }\n });\n\n const hitFrom = (target: EventTarget | null): MarkedElement | null => {\n const element = asElement(target)?.closest(MARKED_SELECTOR) ?? null;\n const field = element !== null ? readMarkedField(element) : null;\n\n return element !== null && field !== null ? { element, field } : null;\n };\n\n const labelOf = (field: CraftyMarkedField): string => field.label ?? field.field;\n\n const onPointerOver = (event: PointerEvent): void => {\n if (event.pointerType === \"touch\") {\n return;\n }\n\n const hit = hitFrom(event.target);\n\n if (hit !== null) {\n overlay.show(hit.element, labelOf(hit.field));\n } else {\n overlay.hide();\n }\n };\n\n const onClick = (event: MouseEvent): void => {\n const hit = hitFrom(event.target);\n\n if (hit !== null) {\n event.preventDefault();\n event.stopPropagation();\n overlay.show(hit.element, labelOf(hit.field));\n post({ v: PROTOCOL_VERSION, type: \"crafty:select\", payload: hit.field });\n\n return;\n }\n\n const path = internalLinkPath(event, win);\n\n if (path !== null) {\n event.preventDefault();\n event.stopPropagation();\n post({ v: PROTOCOL_VERSION, type: \"crafty:navigate\", payload: { path } });\n }\n };\n\n const highlight = (ref: CraftyFieldRef): void => {\n const key = refKey(ref);\n const match = scanMarked(doc).find((item) => refKey(item.field) === key);\n\n if (match === undefined) {\n return;\n }\n\n const element = match.element as Element & { scrollIntoView?: (options?: ScrollIntoViewOptions) => void };\n element.scrollIntoView?.({ block: \"center\", behavior: \"smooth\" });\n overlay.show(match.element, labelOf(match.field));\n };\n\n const refresh = async (): Promise<void> => {\n if (options.onRefresh) {\n try {\n await options.onRefresh();\n } finally {\n scheduleRescan();\n }\n\n return;\n }\n\n try {\n win.sessionStorage.setItem(SCROLL_STORAGE_KEY, String(win.scrollY));\n } catch {\n // Storage blocked: reload without restoring the scroll position.\n }\n\n win.location.reload();\n };\n\n const handleInbound = (message: InboundMessage): void => {\n switch (message.type) {\n case \"crafty:token\":\n storePreviewToken(message.payload.token);\n return;\n case \"crafty:refresh\":\n refresh().catch((error: unknown) => console.error(\"[crafty] onRefresh failed\", error));\n return;\n case \"crafty:highlight\":\n highlight(message.payload);\n return;\n case \"crafty:preview-field\":\n livePreview.set(message.payload, message.payload.value);\n overlay.reposition();\n return;\n case \"crafty:preview-reset\":\n livePreview.reset(message.payload);\n overlay.reposition();\n return;\n }\n };\n\n const onMessage = (event: MessageEvent): void => {\n if (event.source !== win.parent || event.origin !== parentOrigin) {\n return;\n }\n\n const message = parseInboundMessage(event.data);\n\n if (message !== null) {\n handleInbound(message);\n }\n };\n\n const onPreviewInvalid = (): void => {\n post({ v: PROTOCOL_VERSION, type: \"crafty:preview-invalid\", payload: {} });\n };\n\n const onPreviewContent = (): void => {\n forceReady = true;\n scheduleRescan();\n };\n\n const start = (): void => {\n if (!active) {\n return;\n }\n\n marked = scanMarked(doc);\n sendReady();\n\n if (isTouchDevice(win)) {\n overlay.flash(\n marked.map((item) => item.element),\n options.touchHighlightMs ?? DEFAULT_TOUCH_HIGHLIGHT_MS\n );\n }\n\n restoreScroll(win, pendingScrollY);\n };\n\n win.addEventListener(\"message\", onMessage);\n doc.addEventListener(\"click\", onClick, true);\n doc.addEventListener(\"pointerover\", onPointerOver, true);\n win.addEventListener(PREVIEW_INVALID_EVENT, onPreviewInvalid);\n win.addEventListener(PREVIEW_CONTENT_EVENT, onPreviewContent);\n observer.observe(doc.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: WATCHED_ATTRIBUTES\n });\n\n if (doc.readyState === \"loading\") {\n doc.addEventListener(\"DOMContentLoaded\", start, { once: true });\n } else {\n start();\n }\n\n const handle: VisualEditingHandle = {\n get active() {\n return active;\n },\n disable() {\n if (!active) {\n return;\n }\n\n active = false;\n win.removeEventListener(\"message\", onMessage);\n doc.removeEventListener(\"click\", onClick, true);\n doc.removeEventListener(\"pointerover\", onPointerOver, true);\n doc.removeEventListener(\"DOMContentLoaded\", start);\n win.removeEventListener(PREVIEW_INVALID_EVENT, onPreviewInvalid);\n win.removeEventListener(PREVIEW_CONTENT_EVENT, onPreviewContent);\n observer.disconnect();\n\n if (rescanTimer !== undefined) {\n win.clearTimeout(rescanTimer);\n rescanTimer = undefined;\n }\n\n livePreview.resetAll();\n overlay.destroy();\n\n if (activeHandle === handle) {\n activeHandle = null;\n }\n\n onDisable?.();\n }\n };\n\n return handle;\n}\n\nfunction asElement(target: EventTarget | null): Element | null {\n return target !== null && typeof (target as Element).closest === \"function\" ? (target as Element) : null;\n}\n\nfunction signatureOf(fields: CraftyMarkedField[]): string {\n return fields.map((field) => `${refKey(field)}|${field.label ?? \"\"}`).join(\"\\n\");\n}\n\nfunction mergeEntries(fetched: CraftyShownEntry[], declared: CraftyShownEntry[]): CraftyShownEntry[] {\n const seen = new Set<string>();\n\n return [...fetched, ...declared].filter((entry) => {\n const key = `${entry.collection}:${entry.id}`;\n\n if (seen.has(key)) {\n return false;\n }\n\n seen.add(key);\n\n return true;\n });\n}\n\nfunction stripPreviewParam(url: URL): string {\n url.searchParams.delete(PREVIEW_QUERY_PARAM);\n\n return `${url.pathname}${url.search}`;\n}\n\nfunction currentPath(win: Window): string {\n return stripPreviewParam(new URL(win.location.href));\n}\n\nfunction internalLinkPath(event: MouseEvent, win: Window): string | null {\n if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return null;\n }\n\n const anchor = asElement(event.target)?.closest(\"a[href]\") ?? null;\n\n if (anchor === null || anchor.hasAttribute(\"download\")) {\n return null;\n }\n\n const target = anchor.getAttribute(\"target\");\n\n if (target !== null && target !== \"\" && target !== \"_self\") {\n return null;\n }\n\n let url: URL;\n\n try {\n url = new URL(anchor.getAttribute(\"href\") ?? \"\", win.location.href);\n } catch {\n return null;\n }\n\n if (url.origin !== win.location.origin) {\n return null;\n }\n\n const path = stripPreviewParam(url);\n\n if (url.hash !== \"\" && path === currentPath(win)) {\n return null;\n }\n\n return path;\n}\n\nfunction isTouchDevice(win: Window): boolean {\n return typeof win.matchMedia === \"function\" && win.matchMedia(\"(hover: none)\").matches;\n}\n\nfunction takeStoredScroll(win: Window): number | null {\n try {\n const raw = win.sessionStorage.getItem(SCROLL_STORAGE_KEY);\n win.sessionStorage.removeItem(SCROLL_STORAGE_KEY);\n const scrollY = raw === null ? Number.NaN : Number(raw);\n\n return Number.isFinite(scrollY) ? scrollY : null;\n } catch {\n return null;\n }\n}\n\nfunction restoreScroll(win: Window, scrollY: number | null): void {\n if (scrollY === null) {\n return;\n }\n\n const apply = (): void => win.scrollTo(0, scrollY);\n\n if (win.document.readyState === \"complete\") {\n apply();\n } else {\n win.addEventListener(\"load\", apply, { once: true });\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["cdn_exports", "__export", "PROTOCOL_VERSION", "attrs", "attrsHtml", "enableVisualEditing", "resolveEditTarget", "target", "record", "id", "attrs", "field", "options", "resolved", "normalizedField", "attributes", "label", "attrsHtml", "name", "value", "escapeAttribute", "PREVIEW_QUERY_PARAM", "PREVIEW_INVALID_EVENT", "PREVIEW_CONTENT_EVENT", "PREVIEW_ACTIVE_EVENT", "TOKEN_STORAGE_KEY", "URL_TOKEN_STORAGE_KEY", "INVALID_TOKEN_STORAGE_KEY", "CONTENT_GLOBAL_KEY", "STATUS_GLOBAL_KEY", "browserWindow", "storageGet", "key", "_a", "_b", "storageSet", "value", "normalizeToken", "value", "tokenFromUrl", "url", "PREVIEW_QUERY_PARAM", "readPreviewToken", "_a", "win", "browserWindow", "urlToken", "token", "storageGet", "URL_TOKEN_STORAGE_KEY", "storageSet", "TOKEN_STORAGE_KEY", "INVALID_TOKEN_STORAGE_KEY", "storePreviewToken", "token", "normalized", "normalizeToken", "storageSet", "TOKEN_STORAGE_KEY", "getPreviewContent", "win", "browserWindow", "content", "CONTENT_GLOBAL_KEY", "getPreviewStatus", "win", "browserWindow", "status", "STATUS_GLOBAL_KEY", "SDK_VERSION", "PROTOCOL_VERSION", "FIELD_PATTERN", "TOKEN_PATTERN", "isRecord", "value", "isPositiveInteger", "parseFieldRef", "type", "id", "field", "
|
|
4
|
+
"sourcesContent": ["/** Entry for the `<script>` build: exposed as `window.CraftyVisualEditing`. */\nexport { attrs, attrsHtml } from \"./attrs.js\";\nexport { enableVisualEditing } from \"./visual-editing/bridge.js\";\nexport { PROTOCOL_VERSION } from \"./visual-editing/protocol.js\";\n", "import type { CraftyBlock, CraftyEntry } from \"./types/public.js\";\n\nexport type CraftyEditTargetType = \"block\" | \"entry\";\n\n/**\n * A block or entry as returned by the API, or an explicit reference for\n * ambiguous shapes (e.g. an entry with fields named `order`, `data` and `type`).\n */\nexport type CraftyEditTarget =\n | CraftyBlock\n | CraftyEntry\n | { kind: CraftyEditTargetType; id: number | string };\n\nexport type CraftyAttrsOptions = {\n /** Human label shown by the visual editor, e.g. \"T\u00EDtulo de la secci\u00F3n\". */\n label?: string;\n /**\n * Field holding the link destination of this element (a button or link whose\n * text is `field`), e.g. `hero.cta.href`. The editor then edits both together.\n */\n hrefField?: string;\n /** Human label for `hrefField`. Defaults to \"Enlace\" in the editor. */\n hrefLabel?: string;\n};\n\nexport type CraftyEditAttributes = {\n \"data-crafty-block\"?: string;\n \"data-crafty-entry\"?: string;\n \"data-crafty-field\"?: string;\n \"data-crafty-label\"?: string;\n \"data-crafty-href-field\"?: string;\n \"data-crafty-href-label\"?: string;\n};\n\nexport function resolveEditTarget(\n target: CraftyEditTarget | null | undefined\n): { type: CraftyEditTargetType; id: number } | null {\n if (target === null || target === undefined || typeof target !== \"object\") {\n return null;\n }\n\n const record = target as Record<string, unknown>;\n const id = typeof record.id === \"string\" ? Number(record.id.trim()) : record.id;\n\n if (typeof id !== \"number\" || !Number.isInteger(id) || id <= 0) {\n return null;\n }\n\n if (record.kind === \"block\" || record.kind === \"entry\") {\n return { type: record.kind, id };\n }\n\n const looksLikeBlock =\n typeof record.order === \"number\" &&\n typeof record.data === \"object\" &&\n record.data !== null &&\n \"type\" in record;\n\n return { type: looksLikeBlock ? \"block\" : \"entry\", id };\n}\n\n/**\n * DOM attributes that let the visual editor map an element to a field.\n * Always emitted (static sites render them at build time without a token).\n * `field` is a top-level field key or a JSON path such as `sections[3].title`.\n */\nexport function attrs(\n target: CraftyEditTarget | null | undefined,\n field: string,\n options: CraftyAttrsOptions = {}\n): CraftyEditAttributes {\n const resolved = resolveEditTarget(target);\n const normalizedField = typeof field === \"string\" ? field.trim() : \"\";\n\n if (resolved === null || normalizedField === \"\") {\n return {};\n }\n\n const attributes: CraftyEditAttributes =\n resolved.type === \"block\"\n ? { \"data-crafty-block\": String(resolved.id), \"data-crafty-field\": normalizedField }\n : { \"data-crafty-entry\": String(resolved.id), \"data-crafty-field\": normalizedField };\n\n const label = typeof options.label === \"string\" ? options.label.trim() : \"\";\n\n if (label !== \"\") {\n attributes[\"data-crafty-label\"] = label;\n }\n\n const hrefField = typeof options.hrefField === \"string\" ? options.hrefField.trim() : \"\";\n\n if (hrefField !== \"\") {\n attributes[\"data-crafty-href-field\"] = hrefField;\n\n const hrefLabel = typeof options.hrefLabel === \"string\" ? options.hrefLabel.trim() : \"\";\n\n if (hrefLabel !== \"\") {\n attributes[\"data-crafty-href-label\"] = hrefLabel;\n }\n }\n\n return attributes;\n}\n\n/** Same as `attrs()`, rendered for HTML string templates. */\nexport function attrsHtml(\n target: CraftyEditTarget | null | undefined,\n field: string,\n options: CraftyAttrsOptions = {}\n): string {\n return Object.entries(attrs(target, field, options))\n .map(([name, value]) => `${name}=\"${escapeAttribute(String(value))}\"`)\n .join(\" \");\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n", "export const PREVIEW_QUERY_PARAM = \"crafty_preview\";\nexport const PREVIEW_HEADER = \"X-Crafty-Preview\";\nexport const PREVIEW_STATUS_HEADER = \"X-Crafty-Preview-Status\";\nexport const PREVIEW_INVALID_EVENT = \"crafty:preview-invalid\";\nexport const PREVIEW_CONTENT_EVENT = \"crafty:preview-content\";\nexport const PREVIEW_ACTIVE_EVENT = \"crafty:preview-active\";\n\nconst TOKEN_STORAGE_KEY = \"crafty:preview-token\";\nconst URL_TOKEN_STORAGE_KEY = \"crafty:preview-url-token\";\nconst INVALID_TOKEN_STORAGE_KEY = \"crafty:preview-invalid-token\";\nconst CONTENT_GLOBAL_KEY = \"__CRAFTY_PREVIEW_CONTENT__\";\nconst STATUS_GLOBAL_KEY = \"__CRAFTY_PREVIEW_STATUS__\";\n\nexport type PreviewPage = { id: number; slug: string };\nexport type PreviewEntry = { id: number; collection: string };\nexport type PreviewContent = { page: PreviewPage | null; entries: PreviewEntry[] };\n/** Last `X-Crafty-Preview-Status` the API answered in this window, or null before any preview request. */\nexport type PreviewStatus = \"active\" | \"invalid\";\n\n/** A URL, a Web `Request`, a Node `IncomingMessage` or an Express-style request. */\nexport type PreviewRequestLike =\n | string\n | URL\n | { url?: string | undefined; query?: Record<string, unknown> | undefined };\n\ntype ContentHost = Record<string, PreviewContent | undefined>;\n\nfunction browserWindow(): Window | null {\n return typeof window === \"undefined\" ? null : window;\n}\n\nfunction storageGet(key: string): string | null {\n try {\n return browserWindow()?.sessionStorage.getItem(key) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction storageSet(key: string, value: string): void {\n try {\n browserWindow()?.sessionStorage.setItem(key, value);\n } catch {\n // Storage can be blocked (private mode, sandboxed frames); the URL token still works.\n }\n}\n\nfunction storageRemove(key: string): void {\n try {\n browserWindow()?.sessionStorage.removeItem(key);\n } catch {\n // Ignore blocked storage.\n }\n}\n\nfunction normalizeToken(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() !== \"\" ? value.trim() : null;\n}\n\nfunction tokenFromUrl(url: string): string | null {\n try {\n return normalizeToken(new URL(url, \"http://localhost\").searchParams.get(PREVIEW_QUERY_PARAM));\n } catch {\n return null;\n }\n}\n\n/**\n * Preview token for browser requests. A token the URL brings for the first time\n * wins; afterwards the stored token wins, so a renewal received over\n * `postMessage` is not overwritten by the stale token still in the URL.\n */\nexport function readPreviewToken(): string | null {\n const win = browserWindow();\n\n if (win === null) {\n return null;\n }\n\n const urlToken = tokenFromUrl(win.location.href);\n let token: string | null;\n\n if (urlToken !== null && urlToken !== storageGet(URL_TOKEN_STORAGE_KEY)) {\n storageSet(URL_TOKEN_STORAGE_KEY, urlToken);\n storageSet(TOKEN_STORAGE_KEY, urlToken);\n token = urlToken;\n } else {\n token = normalizeToken(storageGet(TOKEN_STORAGE_KEY)) ?? urlToken;\n }\n\n return token !== null && token === storageGet(INVALID_TOKEN_STORAGE_KEY) ? null : token;\n}\n\n/**\n * Forgets a browser token the API reported invalid, so later requests stop\n * sending it (the stale copy in the URL included) until a new token arrives\n * over `postMessage` or a new URL. Explicit server-side tokens are untouched.\n */\nexport function discardPreviewToken(token: string): void {\n const win = browserWindow();\n const normalized = normalizeToken(token);\n\n if (win === null || normalized === null) {\n return;\n }\n\n const isStored = normalizeToken(storageGet(TOKEN_STORAGE_KEY)) === normalized;\n\n if (!isStored && tokenFromUrl(win.location.href) !== normalized) {\n return;\n }\n\n if (isStored) {\n storageRemove(TOKEN_STORAGE_KEY);\n }\n\n storageSet(INVALID_TOKEN_STORAGE_KEY, normalized);\n}\n\nexport function storePreviewToken(token: string): void {\n const normalized = normalizeToken(token);\n\n if (normalized !== null) {\n storageSet(TOKEN_STORAGE_KEY, normalized);\n }\n}\n\nexport function clearPreviewToken(): void {\n storageRemove(TOKEN_STORAGE_KEY);\n storageRemove(URL_TOKEN_STORAGE_KEY);\n storageRemove(INVALID_TOKEN_STORAGE_KEY);\n setPreviewStatus(null);\n}\n\n/** Server-side helper: the preview token of an incoming request, or null. */\nexport function previewFromRequest(request: PreviewRequestLike | null | undefined): string | null {\n if (request === null || request === undefined) {\n return null;\n }\n\n if (typeof request === \"string\" || request instanceof URL) {\n return tokenFromUrl(String(request));\n }\n\n const queryValue = request.query?.[PREVIEW_QUERY_PARAM];\n const fromQuery = normalizeToken(Array.isArray(queryValue) ? queryValue[0] : queryValue);\n\n if (fromQuery !== null) {\n return fromQuery;\n }\n\n return typeof request.url === \"string\" ? tokenFromUrl(request.url) : null;\n}\n\nexport function getPreviewContent(): PreviewContent {\n const win = browserWindow() as (Window & ContentHost) | null;\n const content = win?.[CONTENT_GLOBAL_KEY];\n\n return content ? { page: content.page, entries: [...content.entries] } : { page: null, entries: [] };\n}\n\nexport function recordPreviewContent(\n item: ({ type: \"page\" } & PreviewPage) | ({ type: \"entry\" } & PreviewEntry)\n): void {\n const win = browserWindow() as (Window & ContentHost) | null;\n\n if (win === null) {\n return;\n }\n\n const content = win[CONTENT_GLOBAL_KEY] ?? { page: null, entries: [] };\n win[CONTENT_GLOBAL_KEY] = content;\n\n if (item.type === \"page\") {\n content.page = { id: item.id, slug: item.slug };\n } else if (!content.entries.some((entry) => entry.id === item.id && entry.collection === item.collection)) {\n content.entries.push({ id: item.id, collection: item.collection });\n }\n\n dispatch(PREVIEW_CONTENT_EVENT);\n}\n\nexport function resetPreviewContent(): void {\n const win = browserWindow() as (Window & ContentHost) | null;\n\n if (win !== null) {\n win[CONTENT_GLOBAL_KEY] = undefined;\n }\n}\n\n/**\n * Kept on `window` (like the shown content) so a separately bundled bridge, such\n * as the `<script>` build, sees what the site's own SDK copy recorded.\n */\nexport function getPreviewStatus(): PreviewStatus | null {\n const win = browserWindow() as (Window & Record<string, unknown>) | null;\n const status = win?.[STATUS_GLOBAL_KEY];\n\n return status === \"active\" || status === \"invalid\" ? status : null;\n}\n\nfunction setPreviewStatus(status: PreviewStatus | null): void {\n const win = browserWindow() as (Window & Record<string, unknown>) | null;\n\n if (win !== null) {\n win[STATUS_GLOBAL_KEY] = status ?? undefined;\n }\n}\n\nexport function notifyPreviewActive(): void {\n setPreviewStatus(\"active\");\n dispatch(PREVIEW_ACTIVE_EVENT);\n}\n\nexport function notifyPreviewInvalid(): void {\n setPreviewStatus(\"invalid\");\n dispatch(PREVIEW_INVALID_EVENT);\n}\n\nfunction dispatch(name: string): void {\n const win = browserWindow();\n\n if (win !== null && typeof win.dispatchEvent === \"function\") {\n win.dispatchEvent(new Event(name));\n }\n}\n", "// Generated by scripts/write-version.mjs from package.json. Do not edit.\nexport const SDK_VERSION = \"0.4.0\";\n", "export const PROTOCOL_VERSION = 1;\n\nexport type CraftyTargetType = \"block\" | \"entry\";\nexport type CraftyFieldRef = { type: CraftyTargetType; id: number; field: string };\n/** `hrefField` is the field with the link destination of the same element (same target). */\nexport type CraftyMarkedField = CraftyFieldRef & { label?: string; hrefField?: string; hrefLabel?: string };\nexport type CraftyShownPage = { id: number; slug: string };\nexport type CraftyShownEntry = { id: number; collection: string };\n\nexport type ReadyPayload = {\n sdkVersion: string;\n path: string;\n fields: CraftyMarkedField[];\n page: CraftyShownPage | null;\n entries: CraftyShownEntry[];\n};\n\ntype Version = typeof PROTOCOL_VERSION;\ntype EmptyPayload = Record<string, never>;\n\n/** iframe -> admin. `crafty:ready` is a snapshot that may be re-sent; the last one wins. */\nexport type OutboundMessage =\n | { v: Version; type: \"crafty:ready\"; payload: ReadyPayload }\n | { v: Version; type: \"crafty:select\"; payload: CraftyMarkedField }\n | { v: Version; type: \"crafty:navigate\"; payload: { path: string } }\n | { v: Version; type: \"crafty:preview-invalid\"; payload: EmptyPayload };\n\n/** admin -> iframe. */\nexport type InboundMessage =\n | { v: Version; type: \"crafty:token\"; payload: { token: string } }\n | { v: Version; type: \"crafty:refresh\"; payload: EmptyPayload }\n | { v: Version; type: \"crafty:highlight\"; payload: CraftyFieldRef }\n | { v: Version; type: \"crafty:preview-field\"; payload: CraftyFieldRef & { value: string } }\n | { v: Version; type: \"crafty:preview-reset\"; payload: CraftyFieldRef };\n\n/** Same limits as the Crafty admin and backend (content_drafts.field / label). */\nconst MAX_FIELD_LENGTH = 255;\nconst MAX_LABEL_LENGTH = 120;\nconst MAX_TOKEN_LENGTH = 4096;\nconst MAX_VALUE_LENGTH = 100_000;\nconst MAX_PATH_LENGTH = 2048;\nconst FIELD_PATTERN = /^[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+|\\[\\d+\\])*$/;\nconst TOKEN_PATTERN = /^[\\x21-\\x7E]+$/;\nconst CONTROL_CHARACTERS = /[\\u0000-\\u001F\\u007F]/;\nconst PATH_BASE = \"https://crafty.invalid\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPositiveInteger(value: unknown): value is number {\n return typeof value === \"number\" && Number.isInteger(value) && value > 0;\n}\n\nfunction parseFieldPath(value: unknown): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n\n const trimmed = value.trim();\n\n return trimmed === \"\" || trimmed.length > MAX_FIELD_LENGTH || !FIELD_PATTERN.test(trimmed) ? null : trimmed;\n}\n\nfunction parseLabel(value: unknown): string {\n return typeof value === \"string\" ? value.trim().slice(0, MAX_LABEL_LENGTH).trim() : \"\";\n}\n\nexport function parseFieldRef(value: unknown): CraftyFieldRef | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const { type, id } = value;\n const field = parseFieldPath(value.field);\n\n if ((type !== \"block\" && type !== \"entry\") || !isPositiveInteger(id) || field === null) {\n return null;\n }\n\n return { type, id, field };\n}\n\n/** An invalid `hrefField` is dropped; the text field stays selectable. */\nexport function parseMarkedField(value: unknown): CraftyMarkedField | null {\n const ref = parseFieldRef(value);\n\n if (ref === null || !isRecord(value)) {\n return null;\n }\n\n const marked: CraftyMarkedField = { ...ref };\n const label = parseLabel(value.label);\n const hrefField = parseFieldPath(value.hrefField);\n\n if (label !== \"\") {\n marked.label = label;\n }\n\n if (hrefField !== null) {\n marked.hrefField = hrefField;\n\n const hrefLabel = parseLabel(value.hrefLabel);\n\n if (hrefLabel !== \"\") {\n marked.hrefLabel = hrefLabel;\n }\n }\n\n return marked;\n}\n\nfunction isSameOriginPath(value: string): boolean {\n if (!value.startsWith(\"/\") || value.startsWith(\"//\") || value.startsWith(\"/\\\\\")) {\n return false;\n }\n\n try {\n const url = new URL(value, PATH_BASE);\n\n // Dot segments can still resolve to a protocol-relative path (\"/.//evil.example\").\n return url.origin === PATH_BASE && !url.pathname.startsWith(\"//\") && !url.pathname.startsWith(\"/\\\\\");\n } catch {\n return false;\n }\n}\n\nfunction parsePath(value: unknown): string | null {\n if (typeof value !== \"string\" || value.length > MAX_PATH_LENGTH || CONTROL_CHARACTERS.test(value)) {\n return null;\n }\n\n return isSameOriginPath(value) ? value : null;\n}\n\nfunction parseShownEntry(value: unknown): CraftyShownEntry | null {\n return isRecord(value) && isPositiveInteger(value.id) && typeof value.collection === \"string\"\n ? { id: value.id, collection: value.collection }\n : null;\n}\n\nfunction readEnvelope(data: unknown): { type: string; payload: Record<string, unknown> } | null {\n if (!isRecord(data) || data.v !== PROTOCOL_VERSION || typeof data.type !== \"string\") {\n return null;\n }\n\n const payload = data.payload === undefined ? {} : data.payload;\n\n return isRecord(payload) ? { type: data.type, payload } : null;\n}\n\nexport function parseInboundMessage(data: unknown): InboundMessage | null {\n const message = readEnvelope(data);\n\n if (message === null) {\n return null;\n }\n\n const { payload } = message;\n\n switch (message.type) {\n case \"crafty:token\": {\n const token = typeof payload.token === \"string\" ? payload.token.trim() : \"\";\n\n return token !== \"\" && token.length <= MAX_TOKEN_LENGTH && TOKEN_PATTERN.test(token)\n ? { v: PROTOCOL_VERSION, type: \"crafty:token\", payload: { token } }\n : null;\n }\n case \"crafty:refresh\":\n return { v: PROTOCOL_VERSION, type: \"crafty:refresh\", payload: {} };\n case \"crafty:highlight\": {\n const ref = parseFieldRef(payload);\n\n return ref ? { v: PROTOCOL_VERSION, type: \"crafty:highlight\", payload: ref } : null;\n }\n case \"crafty:preview-field\": {\n const ref = parseFieldRef(payload);\n const value = payload.value;\n\n return ref && typeof value === \"string\" && value.length <= MAX_VALUE_LENGTH\n ? { v: PROTOCOL_VERSION, type: \"crafty:preview-field\", payload: { ...ref, value } }\n : null;\n }\n case \"crafty:preview-reset\": {\n const ref = parseFieldRef(payload);\n\n return ref ? { v: PROTOCOL_VERSION, type: \"crafty:preview-reset\", payload: ref } : null;\n }\n default:\n return null;\n }\n}\n\nexport function parseOutboundMessage(data: unknown): OutboundMessage | null {\n const message = readEnvelope(data);\n\n if (message === null) {\n return null;\n }\n\n const { payload } = message;\n\n switch (message.type) {\n case \"crafty:ready\": {\n const path = parsePath(payload.path);\n const rawPage = payload.page;\n\n if (typeof payload.sdkVersion !== \"string\" || path === null || !Array.isArray(payload.fields) || !Array.isArray(payload.entries)) {\n return null;\n }\n\n return {\n v: PROTOCOL_VERSION,\n type: \"crafty:ready\",\n payload: {\n sdkVersion: payload.sdkVersion,\n path,\n fields: payload.fields\n .map((field: unknown) => parseMarkedField(field))\n .filter((field): field is CraftyMarkedField => field !== null),\n page:\n isRecord(rawPage) && isPositiveInteger(rawPage.id) && typeof rawPage.slug === \"string\"\n ? { id: rawPage.id, slug: rawPage.slug }\n : null,\n entries: payload.entries\n .map((entry: unknown) => parseShownEntry(entry))\n .filter((entry): entry is CraftyShownEntry => entry !== null)\n }\n };\n }\n case \"crafty:select\": {\n const field = parseMarkedField(payload);\n\n return field ? { v: PROTOCOL_VERSION, type: \"crafty:select\", payload: field } : null;\n }\n case \"crafty:navigate\": {\n const path = parsePath(payload.path);\n\n return path ? { v: PROTOCOL_VERSION, type: \"crafty:navigate\", payload: { path } } : null;\n }\n case \"crafty:preview-invalid\":\n return { v: PROTOCOL_VERSION, type: \"crafty:preview-invalid\", payload: {} };\n default:\n return null;\n }\n}\n", "import { parseMarkedField, type CraftyFieldRef, type CraftyMarkedField } from \"./protocol.js\";\n\nexport const MARKED_SELECTOR = \"[data-crafty-field]\";\n\nexport type MarkedElement = { element: Element; field: CraftyMarkedField };\n\nexport function readMarkedField(element: Element): CraftyMarkedField | null {\n const blockId = element.getAttribute(\"data-crafty-block\");\n const entryId = element.getAttribute(\"data-crafty-entry\");\n const rawId = blockId ?? entryId;\n\n if (rawId === null) {\n return null;\n }\n\n return parseMarkedField({\n type: blockId !== null ? \"block\" : \"entry\",\n id: rawId.trim() === \"\" ? Number.NaN : Number(rawId),\n field: element.getAttribute(\"data-crafty-field\") ?? \"\",\n label: element.getAttribute(\"data-crafty-label\"),\n hrefField: element.getAttribute(\"data-crafty-href-field\"),\n hrefLabel: element.getAttribute(\"data-crafty-href-label\")\n });\n}\n\nexport function refKey(ref: CraftyFieldRef): string {\n return `${ref.type}:${ref.id}:${ref.field}`;\n}\n\nexport function scanMarked(root: ParentNode): MarkedElement[] {\n const marked: MarkedElement[] = [];\n\n root.querySelectorAll(MARKED_SELECTOR).forEach((element) => {\n const field = readMarkedField(element);\n\n if (field !== null) {\n marked.push({ element, field });\n }\n });\n\n return marked;\n}\n\nexport function uniqueFields(marked: MarkedElement[]): CraftyMarkedField[] {\n const seen = new Set<string>();\n const fields: CraftyMarkedField[] = [];\n\n for (const { field } of marked) {\n const key = refKey(field);\n\n if (!seen.has(key)) {\n seen.add(key);\n fields.push(field);\n }\n }\n\n return fields;\n}\n", "import { MARKED_SELECTOR, readMarkedField, refKey } from \"./markers.js\";\nimport type { CraftyFieldRef } from \"./protocol.js\";\n\nexport type LivePreview = {\n set(ref: CraftyFieldRef, value: string): void;\n reset(ref: CraftyFieldRef): void;\n reapply(): void;\n resetAll(): void;\n readonly size: number;\n};\n\n/**\n * Plain-text live preview. Values are written with `textContent` (never HTML),\n * and each element's own original text is kept so a reset restores exactly what\n * the site rendered, even for elements rendered after the value was set.\n */\nexport function createLivePreview(root: ParentNode): LivePreview {\n const values = new Map<string, string>();\n const originals = new Map<Element, string>();\n\n const matching = (key: string): Element[] =>\n Array.from(root.querySelectorAll(MARKED_SELECTOR)).filter((element) => {\n const field = readMarkedField(element);\n\n return field !== null && refKey(field) === key;\n });\n\n const write = (element: Element, value: string): void => {\n if (!originals.has(element)) {\n originals.set(element, element.textContent ?? \"\");\n }\n\n if (element.textContent !== value) {\n element.textContent = value;\n }\n };\n\n const restore = (key: string | null): void => {\n for (const [element, original] of originals) {\n const field = readMarkedField(element);\n\n if (key === null || (field !== null && refKey(field) === key)) {\n if (element.textContent !== original) {\n element.textContent = original;\n }\n\n originals.delete(element);\n }\n }\n };\n\n return {\n set(ref, value) {\n const key = refKey(ref);\n values.set(key, value);\n matching(key).forEach((element) => write(element, value));\n },\n reset(ref) {\n const key = refKey(ref);\n values.delete(key);\n restore(key);\n },\n reapply() {\n for (const element of [...originals.keys()]) {\n if (!element.isConnected) {\n originals.delete(element);\n }\n }\n\n for (const [key, value] of values) {\n matching(key).forEach((element) => write(element, value));\n }\n },\n resetAll() {\n values.clear();\n restore(null);\n },\n get size() {\n return values.size;\n }\n };\n}\n", "/** Crafty admin panels: https://crafty.do and https://<tenant>.crafty.do. */\nexport const DEFAULT_ADMIN_ORIGINS: ReadonlyArray<string | RegExp> = [/^https:\\/\\/([a-z0-9-]+\\.)*crafty\\.do$/];\n\nfunction originOf(value: string): string | null {\n try {\n return new URL(value).origin;\n } catch {\n return null;\n }\n}\n\nexport function isAllowedAdminOrigin(origin: string, allowlist: ReadonlyArray<string | RegExp>): boolean {\n if (origin === \"\" || origin === \"null\") {\n return false;\n }\n\n return allowlist.some((allowed) => {\n if (typeof allowed === \"string\") {\n return originOf(allowed) === origin;\n }\n\n allowed.lastIndex = 0;\n\n return allowed.test(origin);\n });\n}\n\n/**\n * Origin of the embedding admin. `ancestorOrigins` (Chromium, WebKit) cannot be\n * spoofed by the framed page; Firefox falls back to the referrer the admin sent\n * when it set the iframe `src`.\n */\nexport function resolveParentOrigin(win: Window): string | null {\n const ancestors = win.location.ancestorOrigins as ArrayLike<string> | undefined;\n const first = ancestors && ancestors.length > 0 ? ancestors[0] : undefined;\n\n if (typeof first === \"string\" && first !== \"\") {\n return first;\n }\n\n const referrer = win.document.referrer;\n\n return referrer ? originOf(referrer) : null;\n}\n", "const STYLE_ELEMENT_ID = \"crafty-visual-editing-style\";\nconst ACCENT = \"#4f46e5\";\n\nexport const FLASH_CLASS = \"crafty-ve-flash\";\n\nconst STYLES = [\n \"[data-crafty-field]{cursor:pointer}\",\n `.crafty-ve-box{position:fixed;top:0;left:0;pointer-events:none;z-index:2147483647;box-sizing:border-box;border:2px solid ${ACCENT};border-radius:4px;background:rgba(79,70,229,.06)}`,\n \".crafty-ve-box[hidden]{display:none}\",\n `.crafty-ve-label{position:absolute;left:-2px;bottom:100%;margin-bottom:4px;padding:2px 8px;max-width:320px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:4px;background:${ACCENT};color:#fff;font:500 12px/1.5 system-ui,-apple-system,sans-serif}`,\n `.${FLASH_CLASS}{outline:2px dashed ${ACCENT} !important;outline-offset:2px !important}`\n].join(\"\\n\");\n\nexport type Overlay = {\n show(element: Element, label: string): void;\n hide(): void;\n /** Re-measures the highlighted element, e.g. after its content changed. */\n reposition(): void;\n flash(elements: Element[], durationMs: number): void;\n ensureAttached(): void;\n contains(node: Node | null): boolean;\n destroy(): void;\n};\n\nexport function createOverlay(doc: Document): Overlay {\n const win = doc.defaultView;\n const style = doc.createElement(\"style\");\n style.id = STYLE_ELEMENT_ID;\n style.textContent = STYLES;\n\n const box = doc.createElement(\"div\");\n box.setAttribute(\"data-crafty-overlay\", \"\");\n box.className = \"crafty-ve-box\";\n box.hidden = true;\n\n const label = doc.createElement(\"span\");\n label.className = \"crafty-ve-label\";\n box.appendChild(label);\n\n let target: Element | null = null;\n let flashed: Element[] = [];\n let flashTimer: number | undefined;\n const Observer = (win as (Window & { ResizeObserver?: typeof ResizeObserver }) | null)?.ResizeObserver;\n\n const place = (): void => {\n if (target === null) {\n return;\n }\n\n const rect = target.getBoundingClientRect();\n box.style.top = `${rect.top}px`;\n box.style.left = `${rect.left}px`;\n box.style.width = `${rect.width}px`;\n box.style.height = `${rect.height}px`;\n };\n\n const resizeObserver = typeof Observer === \"function\" ? new Observer(() => place()) : null;\n\n const track = (element: Element | null): void => {\n if (target === element) {\n return;\n }\n\n if (target !== null) {\n resizeObserver?.unobserve(target);\n }\n\n target = element;\n\n if (target !== null) {\n resizeObserver?.observe(target);\n }\n };\n\n const clearFlash = (): void => {\n flashed.forEach((element) => element.classList.remove(FLASH_CLASS));\n flashed = [];\n\n if (flashTimer !== undefined) {\n win?.clearTimeout(flashTimer);\n flashTimer = undefined;\n }\n };\n\n const ensureAttached = (): void => {\n if (!style.isConnected) {\n (doc.head ?? doc.documentElement).appendChild(style);\n }\n\n if (!box.isConnected) {\n (doc.body ?? doc.documentElement).appendChild(box);\n }\n };\n\n ensureAttached();\n win?.addEventListener(\"scroll\", place, { capture: true, passive: true });\n win?.addEventListener(\"resize\", place, { passive: true });\n\n return {\n show(element, text) {\n ensureAttached();\n track(element);\n\n if (label.textContent !== text) {\n label.textContent = text;\n }\n\n box.hidden = false;\n place();\n },\n hide() {\n track(null);\n box.hidden = true;\n },\n reposition() {\n place();\n },\n flash(elements, durationMs) {\n clearFlash();\n flashed = [...elements];\n flashed.forEach((element) => element.classList.add(FLASH_CLASS));\n flashTimer = win?.setTimeout(clearFlash, durationMs);\n },\n ensureAttached,\n contains(node) {\n return node !== null && (box === node || box.contains(node) || style === node || style.contains(node));\n },\n destroy() {\n clearFlash();\n win?.removeEventListener(\"scroll\", place, { capture: true });\n win?.removeEventListener(\"resize\", place);\n resizeObserver?.disconnect();\n box.remove();\n style.remove();\n target = null;\n }\n };\n}\n", "import type { CraftyClient } from \"../client.js\";\nimport {\n PREVIEW_ACTIVE_EVENT,\n PREVIEW_CONTENT_EVENT,\n PREVIEW_INVALID_EVENT,\n PREVIEW_QUERY_PARAM,\n getPreviewContent,\n getPreviewStatus,\n readPreviewToken,\n storePreviewToken\n} from \"../preview.js\";\nimport { SDK_VERSION } from \"../version.js\";\nimport { createLivePreview } from \"./live-preview.js\";\nimport { MARKED_SELECTOR, readMarkedField, refKey, scanMarked, uniqueFields, type MarkedElement } from \"./markers.js\";\nimport { DEFAULT_ADMIN_ORIGINS, isAllowedAdminOrigin, resolveParentOrigin } from \"./origin.js\";\nimport { createOverlay } from \"./overlay.js\";\nimport {\n PROTOCOL_VERSION,\n parseInboundMessage,\n type CraftyFieldRef,\n type CraftyMarkedField,\n type CraftyShownEntry,\n type CraftyShownPage,\n type InboundMessage,\n type OutboundMessage\n} from \"./protocol.js\";\n\nexport type VisualEditingOptions = {\n /** Allowed admin origins. Replaces the default (`https://*.crafty.do`). */\n adminOrigins?: ReadonlyArray<string | RegExp>;\n /** Re-fetch and re-render instead of a full reload when the admin asks for a refresh. */\n onRefresh?: () => void | Promise<void>;\n /** Page rendered by the server (SSR sites, where the browser did not fetch it). */\n page?: CraftyShownPage | null;\n /** Entries rendered by the server (SSR sites). */\n entries?: CraftyShownEntry[];\n /** How long touch devices highlight every editable after load. Default 1500 ms. */\n touchHighlightMs?: number;\n /**\n * Client used to confirm the preview token when no preview request has been\n * answered yet (one `pages.list({ per_page: 1 })` call). Without it the bridge\n * waits for the site's own first Crafty request to confirm the token.\n */\n client?: Pick<CraftyClient, \"pages\">;\n};\n\nexport type VisualEditingHandle = {\n readonly active: boolean;\n disable(): void;\n};\n\nconst SCROLL_STORAGE_KEY = \"crafty:scroll-y\";\nconst RESCAN_DELAY_MS = 50;\nconst DEFAULT_TOUCH_HIGHLIGHT_MS = 1500;\nconst WATCHED_ATTRIBUTES = [\n \"data-crafty-field\",\n \"data-crafty-block\",\n \"data-crafty-entry\",\n \"data-crafty-label\",\n \"data-crafty-href-field\",\n \"data-crafty-href-label\"\n];\n\nconst inactiveHandle: VisualEditingHandle = { active: false, disable: () => undefined };\nlet activeHandle: VisualEditingHandle | null = null;\n\n/**\n * Connects the page to the Crafty visual editor. No-op unless the page runs in\n * an iframe, carries a preview token, and its parent is an allowed admin origin.\n *\n * The default allowlist (`*.crafty.do`) also covers sites hosted by Crafty, so\n * the bridge stays inert (no overlay, no listeners, no messages) until the API\n * answers a preview request with `X-Crafty-Preview-Status: active`. On `invalid`\n * it only tells the admin `crafty:preview-invalid` and stays inert.\n */\nexport function enableVisualEditing(options: VisualEditingOptions = {}): VisualEditingHandle {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return inactiveHandle;\n }\n\n if (activeHandle !== null) {\n return activeHandle;\n }\n\n const win = window;\n\n if (win.parent === null || win.parent === win || readPreviewToken() === null) {\n return inactiveHandle;\n }\n\n const parentOrigin = resolveParentOrigin(win);\n\n if (parentOrigin === null || !isAllowedAdminOrigin(parentOrigin, options.adminOrigins ?? DEFAULT_ADMIN_ORIGINS)) {\n return inactiveHandle;\n }\n\n const status = getPreviewStatus();\n\n if (status === \"invalid\") {\n postPreviewInvalid(win, parentOrigin);\n\n return inactiveHandle;\n }\n\n activeHandle = status === \"active\" ? startBridge(win, parentOrigin, options) : awaitConfirmation(win, parentOrigin, options);\n\n return activeHandle;\n}\n\nfunction postPreviewInvalid(win: Window, parentOrigin: string): void {\n const message: OutboundMessage = { v: PROTOCOL_VERSION, type: \"crafty:preview-invalid\", payload: {} };\n win.parent.postMessage(message, parentOrigin);\n}\n\n/**\n * Pending handle: waits for the API to confirm the token before starting the\n * bridge, verifying it through `options.client` when one is given.\n */\nfunction awaitConfirmation(win: Window, parentOrigin: string, options: VisualEditingOptions): VisualEditingHandle {\n let bridge: VisualEditingHandle | null = null;\n let settled = false;\n\n const stopWaiting = (): void => {\n settled = true;\n win.removeEventListener(PREVIEW_ACTIVE_EVENT, onActive);\n win.removeEventListener(PREVIEW_INVALID_EVENT, onInvalid);\n };\n\n const release = (): void => {\n if (activeHandle === handle) {\n activeHandle = null;\n }\n };\n\n const onActive = (): void => {\n if (settled) {\n return;\n }\n\n stopWaiting();\n bridge = startBridge(win, parentOrigin, options, release);\n };\n\n const onInvalid = (): void => {\n if (settled) {\n return;\n }\n\n stopWaiting();\n release();\n postPreviewInvalid(win, parentOrigin);\n };\n\n const handle: VisualEditingHandle = {\n get active() {\n return bridge?.active ?? false;\n },\n disable() {\n stopWaiting();\n bridge?.disable();\n release();\n }\n };\n\n win.addEventListener(PREVIEW_ACTIVE_EVENT, onActive);\n win.addEventListener(PREVIEW_INVALID_EVENT, onInvalid);\n\n // The status handlers above settle the outcome; request errors leave the bridge waiting.\n options.client?.pages.list({ per_page: 1 }).catch(() => undefined);\n\n return handle;\n}\n\nfunction startBridge(\n win: Window,\n parentOrigin: string,\n options: VisualEditingOptions,\n onDisable?: () => void\n): VisualEditingHandle {\n const doc = win.document;\n const overlay = createOverlay(doc);\n const livePreview = createLivePreview(doc);\n const pendingScrollY = takeStoredScroll(win);\n\n let marked: MarkedElement[] = [];\n let sentSignature: string | null = null;\n let rescanTimer: number | undefined;\n let forceReady = false;\n let active = true;\n\n const post = (message: OutboundMessage): void => {\n win.parent.postMessage(message, parentOrigin);\n };\n\n const sendReady = (): void => {\n const fields = uniqueFields(marked);\n const content = getPreviewContent();\n sentSignature = signatureOf(fields);\n\n post({\n v: PROTOCOL_VERSION,\n type: \"crafty:ready\",\n payload: {\n sdkVersion: SDK_VERSION,\n path: currentPath(win),\n fields,\n page: content.page ?? options.page ?? null,\n entries: mergeEntries(content.entries, options.entries ?? [])\n }\n });\n };\n\n const rescan = (): void => {\n rescanTimer = undefined;\n\n if (!active) {\n return;\n }\n\n overlay.ensureAttached();\n marked = scanMarked(doc);\n livePreview.reapply();\n\n if (forceReady || signatureOf(uniqueFields(marked)) !== sentSignature) {\n forceReady = false;\n sendReady();\n }\n };\n\n const scheduleRescan = (): void => {\n if (active && rescanTimer === undefined) {\n rescanTimer = win.setTimeout(rescan, RESCAN_DELAY_MS);\n }\n };\n\n const observer = new MutationObserver((records) => {\n if (records.some((record) => !overlay.contains(record.target))) {\n scheduleRescan();\n }\n });\n\n const labelOf = (field: CraftyMarkedField): string => field.label ?? field.field;\n\n const onPointerOver = (event: PointerEvent): void => {\n if (event.pointerType === \"touch\") {\n return;\n }\n\n const hit = hitFrom(event.target);\n\n if (hit !== null) {\n overlay.show(hit.element, labelOf(hit.field));\n } else {\n overlay.hide();\n }\n };\n\n const block = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n };\n\n /**\n * Runs in the capture phase on `window`, before any site listener, so a marked\n * element always selects even when it is (or sits inside) a link or button,\n * and nothing the site renders can take the iframe out of the editor.\n */\n const onClick = (event: MouseEvent): void => {\n const hit = hitFrom(event.target);\n\n if (hit !== null) {\n block(event);\n overlay.show(hit.element, labelOf(hit.field));\n post({ v: PROTOCOL_VERSION, type: \"crafty:select\", payload: hit.field });\n\n return;\n }\n\n const action = linkAction(event, win);\n\n if (action.kind === \"allow\") {\n return;\n }\n\n block(event);\n\n if (action.kind === \"navigate\") {\n post({ v: PROTOCOL_VERSION, type: \"crafty:navigate\", payload: { path: action.path } });\n }\n };\n\n /** Middle clicks open links in a new tab: never let them leave the editor. */\n const onAuxClick = (event: MouseEvent): void => {\n if (hitFrom(event.target) !== null || closestLink(event.target) !== null) {\n block(event);\n }\n };\n\n const onSubmit = (event: Event): void => {\n block(event);\n };\n\n const highlight = (ref: CraftyFieldRef): void => {\n const key = refKey(ref);\n const match = scanMarked(doc).find((item) => refKey(item.field) === key);\n\n if (match === undefined) {\n return;\n }\n\n const element = match.element as Element & { scrollIntoView?: (options?: ScrollIntoViewOptions) => void };\n element.scrollIntoView?.({ block: \"center\", behavior: \"smooth\" });\n overlay.show(match.element, labelOf(match.field));\n };\n\n const refresh = async (): Promise<void> => {\n if (options.onRefresh) {\n try {\n await options.onRefresh();\n } finally {\n scheduleRescan();\n }\n\n return;\n }\n\n try {\n win.sessionStorage.setItem(SCROLL_STORAGE_KEY, String(win.scrollY));\n } catch {\n // Storage blocked: reload without restoring the scroll position.\n }\n\n win.location.reload();\n };\n\n const handleInbound = (message: InboundMessage): void => {\n switch (message.type) {\n case \"crafty:token\":\n storePreviewToken(message.payload.token);\n return;\n case \"crafty:refresh\":\n refresh().catch((error: unknown) => console.error(\"[crafty] onRefresh failed\", error));\n return;\n case \"crafty:highlight\":\n highlight(message.payload);\n return;\n case \"crafty:preview-field\":\n livePreview.set(message.payload, message.payload.value);\n overlay.reposition();\n return;\n case \"crafty:preview-reset\":\n livePreview.reset(message.payload);\n overlay.reposition();\n return;\n }\n };\n\n const onMessage = (event: MessageEvent): void => {\n if (event.source !== win.parent || event.origin !== parentOrigin) {\n return;\n }\n\n const message = parseInboundMessage(event.data);\n\n if (message !== null) {\n handleInbound(message);\n }\n };\n\n const onPreviewInvalid = (): void => {\n post({ v: PROTOCOL_VERSION, type: \"crafty:preview-invalid\", payload: {} });\n };\n\n const onPreviewContent = (): void => {\n forceReady = true;\n scheduleRescan();\n };\n\n const start = (): void => {\n if (!active) {\n return;\n }\n\n marked = scanMarked(doc);\n sendReady();\n\n if (isTouchDevice(win)) {\n overlay.flash(\n marked.map((item) => item.element),\n options.touchHighlightMs ?? DEFAULT_TOUCH_HIGHLIGHT_MS\n );\n }\n\n restoreScroll(win, pendingScrollY);\n };\n\n win.addEventListener(\"message\", onMessage);\n win.addEventListener(\"click\", onClick, true);\n win.addEventListener(\"auxclick\", onAuxClick, true);\n win.addEventListener(\"submit\", onSubmit, true);\n doc.addEventListener(\"pointerover\", onPointerOver, true);\n win.addEventListener(PREVIEW_INVALID_EVENT, onPreviewInvalid);\n win.addEventListener(PREVIEW_CONTENT_EVENT, onPreviewContent);\n observer.observe(doc.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: WATCHED_ATTRIBUTES\n });\n\n if (doc.readyState === \"loading\") {\n doc.addEventListener(\"DOMContentLoaded\", start, { once: true });\n } else {\n start();\n }\n\n const handle: VisualEditingHandle = {\n get active() {\n return active;\n },\n disable() {\n if (!active) {\n return;\n }\n\n active = false;\n win.removeEventListener(\"message\", onMessage);\n win.removeEventListener(\"click\", onClick, true);\n win.removeEventListener(\"auxclick\", onAuxClick, true);\n win.removeEventListener(\"submit\", onSubmit, true);\n doc.removeEventListener(\"pointerover\", onPointerOver, true);\n doc.removeEventListener(\"DOMContentLoaded\", start);\n win.removeEventListener(PREVIEW_INVALID_EVENT, onPreviewInvalid);\n win.removeEventListener(PREVIEW_CONTENT_EVENT, onPreviewContent);\n observer.disconnect();\n\n if (rescanTimer !== undefined) {\n win.clearTimeout(rescanTimer);\n rescanTimer = undefined;\n }\n\n livePreview.resetAll();\n overlay.destroy();\n\n if (activeHandle === handle) {\n activeHandle = null;\n }\n\n onDisable?.();\n }\n };\n\n return handle;\n}\n\nfunction asElement(target: EventTarget | null): Element | null {\n return target !== null && typeof (target as Element).closest === \"function\" ? (target as Element) : null;\n}\n\nfunction signatureOf(fields: CraftyMarkedField[]): string {\n return fields.map((field) => `${refKey(field)}|${field.label ?? \"\"}|${field.hrefField ?? \"\"}|${field.hrefLabel ?? \"\"}`).join(\"\\n\");\n}\n\nfunction mergeEntries(fetched: CraftyShownEntry[], declared: CraftyShownEntry[]): CraftyShownEntry[] {\n const seen = new Set<string>();\n\n return [...fetched, ...declared].filter((entry) => {\n const key = `${entry.collection}:${entry.id}`;\n\n if (seen.has(key)) {\n return false;\n }\n\n seen.add(key);\n\n return true;\n });\n}\n\nfunction stripPreviewParam(url: URL): string {\n url.searchParams.delete(PREVIEW_QUERY_PARAM);\n\n return `${url.pathname}${url.search}`;\n}\n\nfunction currentPath(win: Window): string {\n return stripPreviewParam(new URL(win.location.href));\n}\n\ntype LinkAction = { kind: \"allow\" } | { kind: \"block\" } | { kind: \"navigate\"; path: string };\n\n/**\n * Only links fall back to their marked descendant: following them would leave\n * the editor. Buttons, `<summary>` and labels keep their own behavior (menus,\n * accordions, tabs) when the click misses the marked element.\n */\nconst LINK_SELECTOR = \"a[href], area[href]\";\n\n/**\n * The marked element a pointer or click target maps to: the innermost valid\n * marked ancestor (or the target itself), else the first marked element inside\n * the link that was clicked, so clicking a link button's padding or icon\n * selects its label.\n */\nfunction hitFrom(target: EventTarget | null): MarkedElement | null {\n const element = asElement(target);\n\n if (element === null) {\n return null;\n }\n\n for (let node = element.closest(MARKED_SELECTOR); node !== null; node = node.parentElement?.closest(MARKED_SELECTOR) ?? null) {\n const field = readMarkedField(node);\n\n if (field !== null) {\n return { element: node, field };\n }\n }\n\n const link = element.closest(LINK_SELECTOR);\n\n return link !== null ? (scanMarked(link)[0] ?? null) : null;\n}\n\nfunction closestLink(target: EventTarget | null): Element | null {\n return asElement(target)?.closest(LINK_SELECTOR) ?? null;\n}\n\n/**\n * What to do with a click that hit no marked element. Only same-page anchors\n * run as usual; same-origin links become `crafty:navigate`; anything that\n * would leave the editor (other origins, `mailto:`/`tel:`, new tabs,\n * downloads, modified clicks) is blocked.\n */\nfunction linkAction(event: MouseEvent, win: Window): LinkAction {\n const anchor = closestLink(event.target);\n\n if (anchor === null) {\n return { kind: \"allow\" };\n }\n\n if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || anchor.hasAttribute(\"download\")) {\n return { kind: \"block\" };\n }\n\n const target = anchor.getAttribute(\"target\");\n\n if (target !== null && target !== \"\" && target !== \"_self\") {\n return { kind: \"block\" };\n }\n\n const href = anchor.getAttribute(\"href\") ?? \"\";\n let url: URL;\n\n try {\n url = new URL(href, win.location.href);\n } catch {\n return { kind: \"block\" };\n }\n\n if (url.origin !== win.location.origin || (url.protocol !== \"http:\" && url.protocol !== \"https:\")) {\n return { kind: \"block\" };\n }\n\n const path = stripPreviewParam(url);\n\n if ((url.hash !== \"\" || href.startsWith(\"#\")) && path === currentPath(win)) {\n return { kind: \"allow\" };\n }\n\n return { kind: \"navigate\", path };\n}\n\nfunction isTouchDevice(win: Window): boolean {\n return typeof win.matchMedia === \"function\" && win.matchMedia(\"(hover: none)\").matches;\n}\n\nfunction takeStoredScroll(win: Window): number | null {\n try {\n const raw = win.sessionStorage.getItem(SCROLL_STORAGE_KEY);\n win.sessionStorage.removeItem(SCROLL_STORAGE_KEY);\n const scrollY = raw === null ? Number.NaN : Number(raw);\n\n return Number.isFinite(scrollY) ? scrollY : null;\n } catch {\n return null;\n }\n}\n\nfunction restoreScroll(win: Window, scrollY: number | null): void {\n if (scrollY === null) {\n return;\n }\n\n const apply = (): void => win.scrollTo(0, scrollY);\n\n if (win.document.readyState === \"complete\") {\n apply();\n } else {\n win.addEventListener(\"load\", apply, { once: true });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["cdn_exports", "__export", "PROTOCOL_VERSION", "attrs", "attrsHtml", "enableVisualEditing", "resolveEditTarget", "target", "record", "id", "attrs", "field", "options", "resolved", "normalizedField", "attributes", "label", "hrefField", "hrefLabel", "attrsHtml", "name", "value", "escapeAttribute", "PREVIEW_QUERY_PARAM", "PREVIEW_INVALID_EVENT", "PREVIEW_CONTENT_EVENT", "PREVIEW_ACTIVE_EVENT", "TOKEN_STORAGE_KEY", "URL_TOKEN_STORAGE_KEY", "INVALID_TOKEN_STORAGE_KEY", "CONTENT_GLOBAL_KEY", "STATUS_GLOBAL_KEY", "browserWindow", "storageGet", "key", "_a", "_b", "storageSet", "value", "normalizeToken", "value", "tokenFromUrl", "url", "PREVIEW_QUERY_PARAM", "readPreviewToken", "_a", "win", "browserWindow", "urlToken", "token", "storageGet", "URL_TOKEN_STORAGE_KEY", "storageSet", "TOKEN_STORAGE_KEY", "INVALID_TOKEN_STORAGE_KEY", "storePreviewToken", "token", "normalized", "normalizeToken", "storageSet", "TOKEN_STORAGE_KEY", "getPreviewContent", "win", "browserWindow", "content", "CONTENT_GLOBAL_KEY", "getPreviewStatus", "win", "browserWindow", "status", "STATUS_GLOBAL_KEY", "SDK_VERSION", "PROTOCOL_VERSION", "FIELD_PATTERN", "TOKEN_PATTERN", "isRecord", "value", "isPositiveInteger", "parseFieldPath", "trimmed", "FIELD_PATTERN", "parseLabel", "parseFieldRef", "type", "id", "field", "parseMarkedField", "ref", "marked", "label", "hrefField", "hrefLabel", "readEnvelope", "data", "isRecord", "payload", "parseInboundMessage", "message", "token", "TOKEN_PATTERN", "ref", "parseFieldRef", "value", "MARKED_SELECTOR", "readMarkedField", "element", "_a", "blockId", "entryId", "rawId", "parseMarkedField", "refKey", "ref", "scanMarked", "root", "marked", "field", "uniqueFields", "seen", "fields", "key", "createLivePreview", "root", "values", "originals", "matching", "key", "MARKED_SELECTOR", "element", "field", "readMarkedField", "refKey", "write", "value", "_a", "restore", "original", "ref", "DEFAULT_ADMIN_ORIGINS", "originOf", "value", "isAllowedAdminOrigin", "origin", "allowlist", "allowed", "resolveParentOrigin", "win", "ancestors", "first", "referrer", "STYLE_ELEMENT_ID", "ACCENT", "FLASH_CLASS", "STYLES", "createOverlay", "doc", "win", "style", "box", "label", "target", "flashed", "flashTimer", "Observer", "place", "rect", "resizeObserver", "track", "element", "clearFlash", "ensureAttached", "_a", "_b", "text", "elements", "durationMs", "node", "SCROLL_STORAGE_KEY", "RESCAN_DELAY_MS", "DEFAULT_TOUCH_HIGHLIGHT_MS", "WATCHED_ATTRIBUTES", "inactiveHandle", "activeHandle", "enableVisualEditing", "options", "_a", "win", "readPreviewToken", "parentOrigin", "resolveParentOrigin", "isAllowedAdminOrigin", "DEFAULT_ADMIN_ORIGINS", "status", "getPreviewStatus", "postPreviewInvalid", "startBridge", "awaitConfirmation", "message", "bridge", "settled", "stopWaiting", "PREVIEW_ACTIVE_EVENT", "onActive", "PREVIEW_INVALID_EVENT", "onInvalid", "release", "handle", "onDisable", "doc", "overlay", "createOverlay", "livePreview", "createLivePreview", "pendingScrollY", "takeStoredScroll", "marked", "sentSignature", "rescanTimer", "forceReady", "active", "post", "sendReady", "_b", "_c", "fields", "uniqueFields", "content", "getPreviewContent", "signatureOf", "SDK_VERSION", "currentPath", "mergeEntries", "rescan", "scanMarked", "scheduleRescan", "observer", "records", "record", "labelOf", "field", "onPointerOver", "event", "hit", "hitFrom", "block", "onClick", "action", "linkAction", "onAuxClick", "closestLink", "onSubmit", "highlight", "ref", "key", "refKey", "match", "item", "element", "refresh", "handleInbound", "storePreviewToken", "error", "onMessage", "parseInboundMessage", "onPreviewInvalid", "onPreviewContent", "start", "isTouchDevice", "restoreScroll", "PREVIEW_CONTENT_EVENT", "asElement", "target", "fetched", "declared", "seen", "entry", "stripPreviewParam", "url", "PREVIEW_QUERY_PARAM", "LINK_SELECTOR", "node", "MARKED_SELECTOR", "readMarkedField", "link", "anchor", "href", "path", "raw", "scrollY", "apply"]
|
|
7
7
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.
|
|
1
|
+
export declare const SDK_VERSION = "0.4.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/visual-editing/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAgBjD,OAAO,EAKL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAGrB,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,oBAAoB,GAAG;IACjC,2EAA2E;IAC3E,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC9C,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,mFAAmF;IACnF,IAAI,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,kDAAkD;IAClD,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/visual-editing/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAgBjD,OAAO,EAKL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAGrB,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,oBAAoB,GAAG;IACjC,2EAA2E;IAC3E,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC9C,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,mFAAmF;IACnF,IAAI,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,kDAAkD;IAClD,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAiBF;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CAgC3F"}
|
|
@@ -8,7 +8,14 @@ import { PROTOCOL_VERSION, parseInboundMessage } from "./protocol.js";
|
|
|
8
8
|
const SCROLL_STORAGE_KEY = "crafty:scroll-y";
|
|
9
9
|
const RESCAN_DELAY_MS = 50;
|
|
10
10
|
const DEFAULT_TOUCH_HIGHLIGHT_MS = 1500;
|
|
11
|
-
const WATCHED_ATTRIBUTES = [
|
|
11
|
+
const WATCHED_ATTRIBUTES = [
|
|
12
|
+
"data-crafty-field",
|
|
13
|
+
"data-crafty-block",
|
|
14
|
+
"data-crafty-entry",
|
|
15
|
+
"data-crafty-label",
|
|
16
|
+
"data-crafty-href-field",
|
|
17
|
+
"data-crafty-href-label"
|
|
18
|
+
];
|
|
12
19
|
const inactiveHandle = { active: false, disable: () => undefined };
|
|
13
20
|
let activeHandle = null;
|
|
14
21
|
/**
|
|
@@ -147,11 +154,6 @@ function startBridge(win, parentOrigin, options, onDisable) {
|
|
|
147
154
|
scheduleRescan();
|
|
148
155
|
}
|
|
149
156
|
});
|
|
150
|
-
const hitFrom = (target) => {
|
|
151
|
-
const element = asElement(target)?.closest(MARKED_SELECTOR) ?? null;
|
|
152
|
-
const field = element !== null ? readMarkedField(element) : null;
|
|
153
|
-
return element !== null && field !== null ? { element, field } : null;
|
|
154
|
-
};
|
|
155
157
|
const labelOf = (field) => field.label ?? field.field;
|
|
156
158
|
const onPointerOver = (event) => {
|
|
157
159
|
if (event.pointerType === "touch") {
|
|
@@ -165,22 +167,41 @@ function startBridge(win, parentOrigin, options, onDisable) {
|
|
|
165
167
|
overlay.hide();
|
|
166
168
|
}
|
|
167
169
|
};
|
|
170
|
+
const block = (event) => {
|
|
171
|
+
event.preventDefault();
|
|
172
|
+
event.stopPropagation();
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Runs in the capture phase on `window`, before any site listener, so a marked
|
|
176
|
+
* element always selects even when it is (or sits inside) a link or button,
|
|
177
|
+
* and nothing the site renders can take the iframe out of the editor.
|
|
178
|
+
*/
|
|
168
179
|
const onClick = (event) => {
|
|
169
180
|
const hit = hitFrom(event.target);
|
|
170
181
|
if (hit !== null) {
|
|
171
|
-
event
|
|
172
|
-
event.stopPropagation();
|
|
182
|
+
block(event);
|
|
173
183
|
overlay.show(hit.element, labelOf(hit.field));
|
|
174
184
|
post({ v: PROTOCOL_VERSION, type: "crafty:select", payload: hit.field });
|
|
175
185
|
return;
|
|
176
186
|
}
|
|
177
|
-
const
|
|
178
|
-
if (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
187
|
+
const action = linkAction(event, win);
|
|
188
|
+
if (action.kind === "allow") {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
block(event);
|
|
192
|
+
if (action.kind === "navigate") {
|
|
193
|
+
post({ v: PROTOCOL_VERSION, type: "crafty:navigate", payload: { path: action.path } });
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
/** Middle clicks open links in a new tab: never let them leave the editor. */
|
|
197
|
+
const onAuxClick = (event) => {
|
|
198
|
+
if (hitFrom(event.target) !== null || closestLink(event.target) !== null) {
|
|
199
|
+
block(event);
|
|
182
200
|
}
|
|
183
201
|
};
|
|
202
|
+
const onSubmit = (event) => {
|
|
203
|
+
block(event);
|
|
204
|
+
};
|
|
184
205
|
const highlight = (ref) => {
|
|
185
206
|
const key = refKey(ref);
|
|
186
207
|
const match = scanMarked(doc).find((item) => refKey(item.field) === key);
|
|
@@ -258,7 +279,9 @@ function startBridge(win, parentOrigin, options, onDisable) {
|
|
|
258
279
|
restoreScroll(win, pendingScrollY);
|
|
259
280
|
};
|
|
260
281
|
win.addEventListener("message", onMessage);
|
|
261
|
-
|
|
282
|
+
win.addEventListener("click", onClick, true);
|
|
283
|
+
win.addEventListener("auxclick", onAuxClick, true);
|
|
284
|
+
win.addEventListener("submit", onSubmit, true);
|
|
262
285
|
doc.addEventListener("pointerover", onPointerOver, true);
|
|
263
286
|
win.addEventListener(PREVIEW_INVALID_EVENT, onPreviewInvalid);
|
|
264
287
|
win.addEventListener(PREVIEW_CONTENT_EVENT, onPreviewContent);
|
|
@@ -284,7 +307,9 @@ function startBridge(win, parentOrigin, options, onDisable) {
|
|
|
284
307
|
}
|
|
285
308
|
active = false;
|
|
286
309
|
win.removeEventListener("message", onMessage);
|
|
287
|
-
|
|
310
|
+
win.removeEventListener("click", onClick, true);
|
|
311
|
+
win.removeEventListener("auxclick", onAuxClick, true);
|
|
312
|
+
win.removeEventListener("submit", onSubmit, true);
|
|
288
313
|
doc.removeEventListener("pointerover", onPointerOver, true);
|
|
289
314
|
doc.removeEventListener("DOMContentLoaded", start);
|
|
290
315
|
win.removeEventListener(PREVIEW_INVALID_EVENT, onPreviewInvalid);
|
|
@@ -308,7 +333,7 @@ function asElement(target) {
|
|
|
308
333
|
return target !== null && typeof target.closest === "function" ? target : null;
|
|
309
334
|
}
|
|
310
335
|
function signatureOf(fields) {
|
|
311
|
-
return fields.map((field) => `${refKey(field)}|${field.label ?? ""}`).join("\n");
|
|
336
|
+
return fields.map((field) => `${refKey(field)}|${field.label ?? ""}|${field.hrefField ?? ""}|${field.hrefLabel ?? ""}`).join("\n");
|
|
312
337
|
}
|
|
313
338
|
function mergeEntries(fetched, declared) {
|
|
314
339
|
const seen = new Set();
|
|
@@ -328,33 +353,69 @@ function stripPreviewParam(url) {
|
|
|
328
353
|
function currentPath(win) {
|
|
329
354
|
return stripPreviewParam(new URL(win.location.href));
|
|
330
355
|
}
|
|
331
|
-
|
|
332
|
-
|
|
356
|
+
/**
|
|
357
|
+
* Only links fall back to their marked descendant: following them would leave
|
|
358
|
+
* the editor. Buttons, `<summary>` and labels keep their own behavior (menus,
|
|
359
|
+
* accordions, tabs) when the click misses the marked element.
|
|
360
|
+
*/
|
|
361
|
+
const LINK_SELECTOR = "a[href], area[href]";
|
|
362
|
+
/**
|
|
363
|
+
* The marked element a pointer or click target maps to: the innermost valid
|
|
364
|
+
* marked ancestor (or the target itself), else the first marked element inside
|
|
365
|
+
* the link that was clicked, so clicking a link button's padding or icon
|
|
366
|
+
* selects its label.
|
|
367
|
+
*/
|
|
368
|
+
function hitFrom(target) {
|
|
369
|
+
const element = asElement(target);
|
|
370
|
+
if (element === null) {
|
|
333
371
|
return null;
|
|
334
372
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
373
|
+
for (let node = element.closest(MARKED_SELECTOR); node !== null; node = node.parentElement?.closest(MARKED_SELECTOR) ?? null) {
|
|
374
|
+
const field = readMarkedField(node);
|
|
375
|
+
if (field !== null) {
|
|
376
|
+
return { element: node, field };
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
const link = element.closest(LINK_SELECTOR);
|
|
380
|
+
return link !== null ? (scanMarked(link)[0] ?? null) : null;
|
|
381
|
+
}
|
|
382
|
+
function closestLink(target) {
|
|
383
|
+
return asElement(target)?.closest(LINK_SELECTOR) ?? null;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* What to do with a click that hit no marked element. Only same-page anchors
|
|
387
|
+
* run as usual; same-origin links become `crafty:navigate`; anything that
|
|
388
|
+
* would leave the editor (other origins, `mailto:`/`tel:`, new tabs,
|
|
389
|
+
* downloads, modified clicks) is blocked.
|
|
390
|
+
*/
|
|
391
|
+
function linkAction(event, win) {
|
|
392
|
+
const anchor = closestLink(event.target);
|
|
393
|
+
if (anchor === null) {
|
|
394
|
+
return { kind: "allow" };
|
|
395
|
+
}
|
|
396
|
+
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || anchor.hasAttribute("download")) {
|
|
397
|
+
return { kind: "block" };
|
|
338
398
|
}
|
|
339
399
|
const target = anchor.getAttribute("target");
|
|
340
400
|
if (target !== null && target !== "" && target !== "_self") {
|
|
341
|
-
return
|
|
401
|
+
return { kind: "block" };
|
|
342
402
|
}
|
|
403
|
+
const href = anchor.getAttribute("href") ?? "";
|
|
343
404
|
let url;
|
|
344
405
|
try {
|
|
345
|
-
url = new URL(
|
|
406
|
+
url = new URL(href, win.location.href);
|
|
346
407
|
}
|
|
347
408
|
catch {
|
|
348
|
-
return
|
|
409
|
+
return { kind: "block" };
|
|
349
410
|
}
|
|
350
|
-
if (url.origin !== win.location.origin) {
|
|
351
|
-
return
|
|
411
|
+
if (url.origin !== win.location.origin || (url.protocol !== "http:" && url.protocol !== "https:")) {
|
|
412
|
+
return { kind: "block" };
|
|
352
413
|
}
|
|
353
414
|
const path = stripPreviewParam(url);
|
|
354
|
-
if (url.hash !== "" && path === currentPath(win)) {
|
|
355
|
-
return
|
|
415
|
+
if ((url.hash !== "" || href.startsWith("#")) && path === currentPath(win)) {
|
|
416
|
+
return { kind: "allow" };
|
|
356
417
|
}
|
|
357
|
-
return path;
|
|
418
|
+
return { kind: "navigate", path };
|
|
358
419
|
}
|
|
359
420
|
function isTouchDevice(win) {
|
|
360
421
|
return typeof win.matchMedia === "function" && win.matchMedia("(hover: none)").matches;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/visual-editing/bridge.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/visual-editing/bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,12 +7,13 @@ export function readMarkedField(element) {
|
|
|
7
7
|
if (rawId === null) {
|
|
8
8
|
return null;
|
|
9
9
|
}
|
|
10
|
-
const label = element.getAttribute("data-crafty-label");
|
|
11
10
|
return parseMarkedField({
|
|
12
11
|
type: blockId !== null ? "block" : "entry",
|
|
13
12
|
id: rawId.trim() === "" ? Number.NaN : Number(rawId),
|
|
14
13
|
field: element.getAttribute("data-crafty-field") ?? "",
|
|
15
|
-
|
|
14
|
+
label: element.getAttribute("data-crafty-label"),
|
|
15
|
+
hrefField: element.getAttribute("data-crafty-href-field"),
|
|
16
|
+
hrefLabel: element.getAttribute("data-crafty-href-label")
|
|
16
17
|
});
|
|
17
18
|
}
|
|
18
19
|
export function refKey(ref) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markers.js","sourceRoot":"","sources":["../../src/visual-editing/markers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA+C,MAAM,eAAe,CAAC;AAE9F,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAIrD,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,OAAO,IAAI,OAAO,CAAC;IAEjC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"markers.js","sourceRoot":"","sources":["../../src/visual-editing/markers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA+C,MAAM,eAAe,CAAC;AAE9F,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAIrD,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,OAAO,IAAI,OAAO,CAAC;IAEjC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QAC1C,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;QACpD,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,IAAI,EAAE;QACtD,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC;QAChD,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,wBAAwB,CAAC;QACzD,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,wBAAwB,CAAC;KAC1D,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAmB;IACxC,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAgB;IACzC,MAAM,MAAM,GAAoB,EAAE,CAAC;IAEnC,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACzD,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAEvC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,MAAM,GAAwB,EAAE,CAAC;IAEvC,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,MAAM,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAE1B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -5,8 +5,11 @@ export type CraftyFieldRef = {
|
|
|
5
5
|
id: number;
|
|
6
6
|
field: string;
|
|
7
7
|
};
|
|
8
|
+
/** `hrefField` is the field with the link destination of the same element (same target). */
|
|
8
9
|
export type CraftyMarkedField = CraftyFieldRef & {
|
|
9
10
|
label?: string;
|
|
11
|
+
hrefField?: string;
|
|
12
|
+
hrefLabel?: string;
|
|
10
13
|
};
|
|
11
14
|
export type CraftyShownPage = {
|
|
12
15
|
id: number;
|
|
@@ -72,6 +75,7 @@ export type InboundMessage = {
|
|
|
72
75
|
payload: CraftyFieldRef;
|
|
73
76
|
};
|
|
74
77
|
export declare function parseFieldRef(value: unknown): CraftyFieldRef | null;
|
|
78
|
+
/** An invalid `hrefField` is dropped; the text field stays selectable. */
|
|
75
79
|
export declare function parseMarkedField(value: unknown): CraftyMarkedField | null;
|
|
76
80
|
export declare function parseInboundMessage(data: unknown): InboundMessage | null;
|
|
77
81
|
export declare function parseOutboundMessage(data: unknown): OutboundMessage | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/visual-editing/protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,CAAC;AACjD,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACnF,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/visual-editing/protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,27 +15,47 @@ function isRecord(value) {
|
|
|
15
15
|
function isPositiveInteger(value) {
|
|
16
16
|
return typeof value === "number" && Number.isInteger(value) && value > 0;
|
|
17
17
|
}
|
|
18
|
+
function parseFieldPath(value) {
|
|
19
|
+
if (typeof value !== "string") {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const trimmed = value.trim();
|
|
23
|
+
return trimmed === "" || trimmed.length > MAX_FIELD_LENGTH || !FIELD_PATTERN.test(trimmed) ? null : trimmed;
|
|
24
|
+
}
|
|
25
|
+
function parseLabel(value) {
|
|
26
|
+
return typeof value === "string" ? value.trim().slice(0, MAX_LABEL_LENGTH).trim() : "";
|
|
27
|
+
}
|
|
18
28
|
export function parseFieldRef(value) {
|
|
19
29
|
if (!isRecord(value)) {
|
|
20
30
|
return null;
|
|
21
31
|
}
|
|
22
|
-
const { type, id
|
|
23
|
-
|
|
32
|
+
const { type, id } = value;
|
|
33
|
+
const field = parseFieldPath(value.field);
|
|
34
|
+
if ((type !== "block" && type !== "entry") || !isPositiveInteger(id) || field === null) {
|
|
24
35
|
return null;
|
|
25
36
|
}
|
|
26
|
-
|
|
27
|
-
return trimmed === "" || trimmed.length > MAX_FIELD_LENGTH || !FIELD_PATTERN.test(trimmed)
|
|
28
|
-
? null
|
|
29
|
-
: { type, id, field: trimmed };
|
|
37
|
+
return { type, id, field };
|
|
30
38
|
}
|
|
39
|
+
/** An invalid `hrefField` is dropped; the text field stays selectable. */
|
|
31
40
|
export function parseMarkedField(value) {
|
|
32
41
|
const ref = parseFieldRef(value);
|
|
33
|
-
if (ref === null) {
|
|
42
|
+
if (ref === null || !isRecord(value)) {
|
|
34
43
|
return null;
|
|
35
44
|
}
|
|
36
|
-
const
|
|
37
|
-
const label =
|
|
38
|
-
|
|
45
|
+
const marked = { ...ref };
|
|
46
|
+
const label = parseLabel(value.label);
|
|
47
|
+
const hrefField = parseFieldPath(value.hrefField);
|
|
48
|
+
if (label !== "") {
|
|
49
|
+
marked.label = label;
|
|
50
|
+
}
|
|
51
|
+
if (hrefField !== null) {
|
|
52
|
+
marked.hrefField = hrefField;
|
|
53
|
+
const hrefLabel = parseLabel(value.hrefLabel);
|
|
54
|
+
if (hrefLabel !== "") {
|
|
55
|
+
marked.hrefLabel = hrefLabel;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return marked;
|
|
39
59
|
}
|
|
40
60
|
function isSameOriginPath(value) {
|
|
41
61
|
if (!value.startsWith("/") || value.startsWith("//") || value.startsWith("/\\")) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/visual-editing/protocol.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/visual-editing/protocol.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -124,7 +124,7 @@ Whenever you integrate Crafty into a frontend, ask the user exactly once:
|
|
|
124
124
|
|
|
125
125
|
> **¿Quieres dejar el sitio preparado para el editor visual de Crafty?**
|
|
126
126
|
|
|
127
|
-
- **Yes** → follow `references/visual-editor.md` completely: mark content with `crafty.attrs()
|
|
127
|
+
- **Yes** → follow `references/visual-editor.md` completely: mark content with `crafty.attrs()` (buttons and links with `hrefField`; JSON paths with the stored index), deliver the preview token for the site's render mode, call `enableVisualEditing()` (pass `client` for `ssr` sites; React/Vue sites re-fetch and remount in `onRefresh`, hybrid sites cache the latest fetch), allow framing (`frame-ancestors`), check images are public, confirm which host really serves the domain before setting `frontend_url`, run `configure_visual_editor`, and verify (including hydration errors).
|
|
128
128
|
- **No** → add nothing and tell the user it can be enabled later by asking «habilita el editor visual de Crafty».
|
|
129
129
|
|
|
130
130
|
A later request like «habilita el editor visual de Crafty» on an existing site runs the Yes flow without asking again.
|
|
@@ -145,6 +145,7 @@ These are two different credentials — do not mix them:
|
|
|
145
145
|
- **`update_entry` / `update_page` wipe fields you don't send** → both MCP tools do a **full replace**, not a merge. If you send only the new fields, all existing fields are deleted in that revision. Always fetch the current entry first (`get_entry`), merge your changes into the full field map, then call `update_entry` with the complete merged object.
|
|
146
146
|
- **Content not visible via the SDK** → it isn't published. Pages/forms must be published (`publish_page` / `publish_form`).
|
|
147
147
|
- **Confusing the two tokens** → the SDK `apiKey` (X-API-Key) is not an MCP Bearer token.
|
|
148
|
+
- **Stale skill copy** → a project copy of this skill (e.g. `.claude/skills/crafty-cms`) does not update with the SDK. After upgrading `@craftware/crafty-sdk`, copy `node_modules/@craftware/crafty-sdk/skills/crafty-cms` over it.
|
|
148
149
|
|
|
149
150
|
## References
|
|
150
151
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Preparing a site for the Crafty visual editor
|
|
2
2
|
|
|
3
|
-
The visual editor lets a non-technical user open their real site inside the Crafty admin, click (or tap) a text or image, edit it in a side panel, watch the change live, and publish. It only works when the frontend is prepared with `@craftware/crafty-sdk` **0.3.0 or later
|
|
3
|
+
The visual editor lets a non-technical user open their real site inside the Crafty admin, click (or tap) a text or image, edit it in a side panel, watch the change live, and publish. It only works when the frontend is prepared with `@craftware/crafty-sdk` **0.3.0 or later**; use **0.4.0 or later** so buttons and links select instead of navigating and `hrefField` is available. This guide is the complete checklist.
|
|
4
4
|
|
|
5
5
|
## The mandatory question
|
|
6
6
|
|
|
@@ -34,7 +34,14 @@ Do every step. Keep changes minimal and in the site's existing style.
|
|
|
34
34
|
### 2. Upgrade the SDK
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
npm install @craftware/crafty-sdk@^0.
|
|
37
|
+
npm install @craftware/crafty-sdk@^0.4.0
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The package ships this skill. If the project keeps its own copy (for example `.claude/skills/crafty-cms`), refresh it after every SDK upgrade so it matches the installed version:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
rm -rf .claude/skills/crafty-cms
|
|
44
|
+
cp -R node_modules/@craftware/crafty-sdk/skills/crafty-cms .claude/skills/crafty-cms
|
|
38
45
|
```
|
|
39
46
|
|
|
40
47
|
### 3. Mark every editable element
|
|
@@ -45,8 +52,38 @@ Rules:
|
|
|
45
52
|
|
|
46
53
|
- Mark only content that comes from Crafty. Never mark hardcoded text.
|
|
47
54
|
- Put the attributes on the innermost element whose **entire text** is the field value (`<h1>`, `<p>`, `<span>`, the `<a>` or `<button>` label, `<li>`). Live preview replaces that element's text, so an element that also contains icons or other fields must not be marked; wrap the value in a `<span>` and mark the span.
|
|
48
|
-
- Images from a media `reference` field: mark the `<img>` with the field key (`image`, `photo`).
|
|
49
|
-
-
|
|
55
|
+
- Images from a media `reference` field: mark the `<img>` with the field key (`image`, `photo`).
|
|
56
|
+
- Buttons and links (CTAs): mark the label and pass the destination field as `hrefField`, so the editor shows the text and an «Enlace» input together and saves each as its own draft. A click anywhere on a link selects its marked label (the editor never follows links); on a real `<button>`, `<summary>` or `<label>` only a click on the marked element selects, so menus and accordions keep working. A link whose only editable value is its destination (a `url` field) is marked on the `<a>` itself; destinations update after saving the draft, not live while typing.
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<Link to={cta.href} className="btn">
|
|
60
|
+
<span {...attrs(entry, `sections[${i}].cta.label`, { label: "Texto del botón", hrefField: `sections[${i}].cta.href`, hrefLabel: "Enlace del botón" })}>{cta.label}</span>
|
|
61
|
+
<Arrow />
|
|
62
|
+
</Link>
|
|
63
|
+
```
|
|
64
|
+
- Values inside `json` fields: use the exact path of the rendered value, e.g. `sections[2].title`, `hero.title_segments[0].text`, `extra.ctaPrimaryLabel`. Array indexes are positions in the **stored** JSON. When you render the array as stored, the loop index is that position (`` `sections[${i}].title` ``). When you filter, sort, split or reorder it (featured vs regular products, items sorted by `order`, only visible sections), keep the stored index with each item **before** transforming it and use that, never the rendered index:
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
// Keep the stored position before filtering or sorting.
|
|
68
|
+
const items = section.items.map((item, index) => ({ item, index }));
|
|
69
|
+
const featured = items.filter(({ item }) => item.featured).sort((a, b) => a.item.order - b.item.order);
|
|
70
|
+
|
|
71
|
+
featured.map(({ item, index }) => (
|
|
72
|
+
<h3 key={index} {...attrs(entry, `sections[${sectionIndex}].items[${index}].title`, { label: "Título del producto" })}>{item.title}</h3>
|
|
73
|
+
));
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Section components that receive one slice of a JSON field can take a path-scoped helper instead of the whole path:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// editable(entry).at(`sections[${i}]`)("title", "Título") -> attrs(entry, `sections[${i}].title`, { label: "Título" })
|
|
80
|
+
export function editable(target, base = "") {
|
|
81
|
+
const join = (path) => (base ? `${base}.${path}` : path);
|
|
82
|
+
const edit = (field, label, options = {}) => attrs(target, join(field), { ...options, ...(label ? { label } : {}), ...(options.hrefField ? { hrefField: join(options.hrefField) } : {}) });
|
|
83
|
+
edit.at = (path) => editable(target, join(path));
|
|
84
|
+
return edit;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
50
87
|
- Editable types: `string`, `text`, `longText`, `url`, `number`, media `reference`, and string/number values inside `json`. Do not mark booleans, dates, selects, multi-references, or array items that are objects.
|
|
51
88
|
- `label` is a short Spanish name the client understands ("Título principal", "Texto del botón"). Without it the editor shows the field key.
|
|
52
89
|
- Pass blocks and entries as the API returns them. If an entry has fields named `order`, `data` and `type` at once, pass `{ kind: "entry", id: entry.id }` instead.
|
|
@@ -131,16 +168,47 @@ enableVisualEditing({
|
|
|
131
168
|
- Even then it stays inert until the backend confirms the token — a response with `X-Crafty-Preview-Status: active`, normally the site's own first Crafty request for that page. **`ssr` sites where the browser never calls the Crafty API itself must pass `client`** (a `CraftyClient`, typically the same one already created for that render mode) so the bridge can confirm the token itself with one lightweight request (`pages.list({ per_page: 1 })`): `enableVisualEditing({ client: crafty })`. `hybrid` and `static` sites already make a browser-side request that carries the header, so `client` is optional for them. If the API answers `invalid`, the bridge stays off and tells the admin instead of activating.
|
|
132
169
|
- If the site fetches Crafty through something other than this SDK's client (so neither path above ever runs), report `X-Crafty-Preview-Status` yourself with `notifyPreviewActive()` / `notifyPreviewInvalid()` from `@craftware/crafty-sdk/visual-editing` (also exports `getPreviewStatus()` and the `PREVIEW_ACTIVE_EVENT` / `PREVIEW_INVALID_EVENT` event names).
|
|
133
170
|
- `onRefresh`: register it when the site can re-fetch Crafty and re-render without a reload (SPAs, hybrid sites). Otherwise omit it.
|
|
171
|
+
- **React, Vue and other frameworks:** live preview writes text straight into the DOM, into nodes the framework owns. Reconciling against those nodes after a refresh can leave stale text or crash (for example when the element also renders `<strong>` from an emphasis helper). In `onRefresh`, re-fetch and then **remount** the tree (change a `key` on the root) instead of patching it:
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
// main.tsx (React)
|
|
175
|
+
let remount = () => {};
|
|
176
|
+
function Root() {
|
|
177
|
+
const [version, setVersion] = useState(0);
|
|
178
|
+
remount = () => setVersion((v) => v + 1);
|
|
179
|
+
return <App key={version} />;
|
|
180
|
+
}
|
|
181
|
+
enableVisualEditing({
|
|
182
|
+
onRefresh: async () => {
|
|
183
|
+
await refreshCrafty(); // re-fetch and update the content cache below
|
|
184
|
+
remount();
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Vue: the same with `<App :key="version" />` on the root component.
|
|
190
|
+
- **Hybrid sites: cache the latest fetch.** A remount (or a client-side navigation) must render the content fetched last (with drafts), not the build-time data embedded in the HTML. Keep the latest response per collection or page in a module-level cache, read it first when a component mounts, and update it in the refresh:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
const cache = new Map<string, unknown>();
|
|
194
|
+
export async function loadCollection(slug: string) {
|
|
195
|
+
const fresh = await crafty.entries.list(slug);
|
|
196
|
+
cache.set(slug, fresh.data);
|
|
197
|
+
return fresh.data;
|
|
198
|
+
}
|
|
199
|
+
export const cachedCollection = (slug: string, buildTime: unknown) => cache.get(slug) ?? buildTime;
|
|
200
|
+
export const refreshCrafty = () => Promise.all([...cache.keys()].map(loadCollection));
|
|
201
|
+
```
|
|
134
202
|
- SSR: pass what the server rendered, e.g. `enableVisualEditing({ client: crafty, page: { id: page.id, slug: page.slug }, entries: [{ id: post.id, collection: "blog" }] })`.
|
|
135
203
|
- `adminOrigins`: only when the tenant's admin is not on `https://<tenant>.crafty.do` (custom admin domain, or local development such as `http://<tenant>.crafty.test`). It replaces the default list.
|
|
136
204
|
- No bundler:
|
|
137
205
|
|
|
138
206
|
```html
|
|
139
|
-
<script src="https://cdn.jsdelivr.net/npm/@craftware/crafty-sdk@0.
|
|
207
|
+
<script src="https://cdn.jsdelivr.net/npm/@craftware/crafty-sdk@0.4/dist/crafty-visual-editing.global.js"></script>
|
|
140
208
|
<script>CraftyVisualEditing.enableVisualEditing();</script>
|
|
141
209
|
```
|
|
142
210
|
|
|
143
|
-
Pin an exact version (`@0.
|
|
211
|
+
Pin an exact version (`@0.4.0`) with an `integrity="sha384-…" crossorigin="anonymous"` attribute (jsDelivr shows the hash) when the site uses Subresource Integrity.
|
|
144
212
|
|
|
145
213
|
### 6. Allow the admin to frame the site
|
|
146
214
|
|
|
@@ -190,7 +258,14 @@ Call `configure_visual_editor` (scope `crafty:write`) with what you learned:
|
|
|
190
258
|
}
|
|
191
259
|
```
|
|
192
260
|
|
|
193
|
-
- `frontend_url`: the public URL of that environment (omit it when it is the site's domain in production or the Crafty Hosting URL).
|
|
261
|
+
- `frontend_url`: the public URL of that environment where **this** build runs (omit it when it is the site's domain in production or the Crafty Hosting URL). Before setting a domain, check which host actually serves it: a domain can point at a different app than the one you prepared (another server, an older site), and then the editor frames a page without the SDK.
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
curl -sI https://www.example.com/ | grep -iE "^(server|x-frame-options|content-security-policy|set-cookie|location)"
|
|
265
|
+
curl -sI https://<site>.pages.crafty.do/ | grep -iE "^(server|x-frame-options|content-security-policy)"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Crafty Hosting answers with `content-security-policy: frame-ancestors 'self' https://<tenant>.crafty.do`. `x-frame-options: deny`, a foreign framework cookie (for example `laravel_session`) or a different `server` means another app serves that domain: do not use it as `frontend_url`; use the Crafty Hosting URL (omit `frontend_url`) or the URL that really serves this build.
|
|
194
269
|
- `routes.page_pattern` / `home_slug`: only if the site renders Crafty **pages**; patterns start with `/` and contain `{slug}`.
|
|
195
270
|
- `routes.collections`: collections whose entries have their own URL; patterns contain `{slug}` or `{id}`.
|
|
196
271
|
- `routes.fixed`: every other URL that shows Crafty content (home in other languages, listing pages, single-page sites: just `["/"]`).
|
|
@@ -205,6 +280,8 @@ Call `configure_visual_editor` (scope `crafty:write`) with what you learned:
|
|
|
205
280
|
- `document.querySelectorAll("[data-crafty-field]").length` is greater than 0 on every page type (home, a page, a collection entry).
|
|
206
281
|
- Requests to the Crafty API carry `X-Crafty-Preview: test`, and the responses say `X-Crafty-Preview-Status: invalid` (expected: `test` is not a real token; the content stays public).
|
|
207
282
|
- Nothing is highlighted: outside the admin iframe the bridge stays off.
|
|
283
|
+
- The console has no hydration errors (React #418/#423, Vue "Hydration mismatch"). Compare with a build without your changes: if they were already there, say so to the user instead of hiding them; if they are new, the marked markup differs between the prerender and the client render.
|
|
284
|
+
- Prerendered (hybrid/static) pages first show the published content and then the drafts once the browser re-fetch finishes. A short flash of published text in preview is expected; if drafts never appear, the preview re-fetch is missing or a remount reads build-time data (see the cache in step 5).
|
|
208
285
|
3. After deploying, ask the user to open Crafty → the site → **Editar sitio** (`https://<tenant>.crafty.do/sites/<site_id>/visual-editor?path=/`). If hovering highlights texts and a click opens the field, the editor received `crafty:ready`. If it shows «Este sitio aún no tiene edición con clic activada», go through the troubleshooting list.
|
|
209
286
|
|
|
210
287
|
End with a short summary for the user in Spanish: what was marked, the render mode, and what they must do after publishing (nothing for `ssr`/`hybrid`; a deploy for `static`).
|
|
@@ -214,5 +291,7 @@ End with a short summary for the user in Spanish: what was marked, the render mo
|
|
|
214
291
|
- **The editor shows «Este sitio aún no tiene edición con clic activada»** — the iframe is blocked (browser console: `frame-ancestors` or `X-Frame-Options`), `enableVisualEditing()` is not in the bundle of that page, the SDK is older than 0.3.0, the admin origin is not allowed (custom admin domain → `adminOrigins`), a redirect dropped the query string (trailing-slash or locale redirects must keep `?crafty_preview=`), or the site is `ssr` and never confirmed the token because `client` was not passed to `enableVisualEditing()`.
|
|
215
292
|
- **«Esta URL no mostró la página …»** — `routes` do not match the site's URLs; fix them with `configure_visual_editor`.
|
|
216
293
|
- **Saved drafts do not appear in the editor** — SSR: the client was created once at module level or the response was cached; static: the preview re-fetch is missing.
|
|
294
|
+
- **Text reverts or the page crashes after saving** — a framework reconciled DOM that live preview had changed; remount in `onRefresh` (step 5).
|
|
217
295
|
- **Typing does not update the text live** — the attributes are on a wrapper that contains more than the value, or the field is rich text (`longText` shows after saving the draft).
|
|
218
|
-
- **Clicking
|
|
296
|
+
- **Clicking a menu link opens its text instead of the page** — expected: with the bridge active, marked menu labels are selected for editing, not followed. Change pages with the editor's route selector (unmarked internal links still navigate).
|
|
297
|
+
- **Clicking an editable card navigates away** — the SDK is older than 0.4.0 (earlier versions only selected when the click landed exactly on the marked element) or nothing inside the link is marked; mark its label.
|