domma-cms 1.6.30 → 1.6.31
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.
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
function L(){I.register("bold",{viewBox:"0 0 24 24",path:"M7 5H14a3 3 0 0 1 0 6H7V5zM7 11H15a3 3 0 0 1 0 6H7V11z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("italic",{viewBox:"0 0 24 24",path:"M11 5h4M9 19h4M13 5l-2 14",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("strikethrough",{viewBox:"0 0 24 24",path:"M16 4H9a3 3 0 0 0 0 6h6a3 3 0 0 1 0 6H6M3 12h18",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("quote",{viewBox:"0 0 24 24",path:"M3 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1zM15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("eye",{viewBox:"0 0 24 24",path:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("expand",{viewBox:"0 0 24 24",path:"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("columns",{viewBox:"0 0 24 24",path:"M3 4h18a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zM12 4v16",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("card",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z","M3 9h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("help-circle",{viewBox:"0 0 24 24",path:"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 17h.01M12 13a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("book-open",{viewBox:"0 0 24 24",paths:["M2 4h7a2 2 0 0 1 2 2v14a2 2 0 0 0-2-2H2z","M22 4h-7a2 2 0 0 0-2 2v14a2 2 0 0 1 2-2h7z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("spacer-insert",{viewBox:"0 0 24 24",paths:["M3 8h18","M3 16h18","M12 8v8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("icon-pick",{viewBox:"0 0 24 24",paths:["M4 4h6v6H4z","M14 4h6v6h-6z","M4 14h6v6H4z","M14 14h6v6h-6z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("colour-picker",{viewBox:"0 0 24 24",paths:["M12 2a5 5 0 0 1 5 5c0 3-5 10-5 10S7 10 7 7a5 5 0 0 1 5-5z","M12 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("btn-insert",{viewBox:"0 0 24 24",paths:["M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z","M8 12h8M12 9v6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("link-shortcode",{viewBox:"0 0 24 24",paths:["M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71","M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("layout-list",{viewBox:"0 0 24 24",paths:["M3 5h18M3 9h18","M3 14h4v6H3zM9 14h12M9 17h8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("sparkles",{viewBox:"0 0 24 24",paths:["M12 3L13.5 8.5H19L14.5 11.5L16 17L12 14L8 17L9.5 11.5L5 8.5H10.5L12 3Z","M19 3L19.7 5.3H22L20.2 6.6L20.9 9L19 7.7L17.1 9L17.8 6.6L16 5.3H18.3L19 3Z","M5 13L5.5 14.7H7L5.8 15.5L6.3 17.2L5 16.3L3.7 17.2L4.2 15.5L3 14.7H4.5L5 13Z"],stroke:"currentColor",fill:"none",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("accordion-insert",{viewBox:"0 0 24 24",paths:["M3 4h18","M3 8h18","M8 11l4 4 4-4","M3 16h18","M3 20h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("banner-insert",{viewBox:"0 0 24 24",paths:["M3 6h18","M3 10h18","M3 14h12"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("hero",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5z","M7 8h10M7 11h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("text-style",{viewBox:"0 0 24 24",paths:["M4 7V5h16v2","M9 19h6","M12 5v14","M5 12h14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("css-code",{viewBox:"0 0 24 24",paths:["M9 9l-6 3 6 3","M15 9l6 3-6 3","M13 5l-2 14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("scribe-insert",{viewBox:"0 0 24 24",paths:["M4 20h3l10-10-3-3L4 17v3z","M14 7l3 3","M4 4h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("carousel-insert",{viewBox:"0 0 24 24",paths:["M7 5h10v14H7z","M3 8h2v8H3z","M19 8h2v8h-2z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"})}export function replaceRange(e,t,
|
|
2
|
-
`,i-1)+1,
|
|
1
|
+
function L(){I.register("bold",{viewBox:"0 0 24 24",path:"M7 5H14a3 3 0 0 1 0 6H7V5zM7 11H15a3 3 0 0 1 0 6H7V11z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("italic",{viewBox:"0 0 24 24",path:"M11 5h4M9 19h4M13 5l-2 14",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("strikethrough",{viewBox:"0 0 24 24",path:"M16 4H9a3 3 0 0 0 0 6h6a3 3 0 0 1 0 6H6M3 12h18",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("quote",{viewBox:"0 0 24 24",path:"M3 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1zM15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("eye",{viewBox:"0 0 24 24",path:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8zM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6z",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("expand",{viewBox:"0 0 24 24",path:"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("columns",{viewBox:"0 0 24 24",path:"M3 4h18a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zM12 4v16",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("card",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z","M3 9h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("help-circle",{viewBox:"0 0 24 24",path:"M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zM12 17h.01M12 13a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2",stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("book-open",{viewBox:"0 0 24 24",paths:["M2 4h7a2 2 0 0 1 2 2v14a2 2 0 0 0-2-2H2z","M22 4h-7a2 2 0 0 0-2 2v14a2 2 0 0 1 2-2h7z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("spacer-insert",{viewBox:"0 0 24 24",paths:["M3 8h18","M3 16h18","M12 8v8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("icon-pick",{viewBox:"0 0 24 24",paths:["M4 4h6v6H4z","M14 4h6v6h-6z","M4 14h6v6H4z","M14 14h6v6h-6z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("colour-picker",{viewBox:"0 0 24 24",paths:["M12 2a5 5 0 0 1 5 5c0 3-5 10-5 10S7 10 7 7a5 5 0 0 1 5-5z","M12 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("btn-insert",{viewBox:"0 0 24 24",paths:["M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z","M8 12h8M12 9v6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("link-shortcode",{viewBox:"0 0 24 24",paths:["M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71","M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("layout-list",{viewBox:"0 0 24 24",paths:["M3 5h18M3 9h18","M3 14h4v6H3zM9 14h12M9 17h8"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("sparkles",{viewBox:"0 0 24 24",paths:["M12 3L13.5 8.5H19L14.5 11.5L16 17L12 14L8 17L9.5 11.5L5 8.5H10.5L12 3Z","M19 3L19.7 5.3H22L20.2 6.6L20.9 9L19 7.7L17.1 9L17.8 6.6L16 5.3H18.3L19 3Z","M5 13L5.5 14.7H7L5.8 15.5L6.3 17.2L5 16.3L3.7 17.2L4.2 15.5L3 14.7H4.5L5 13Z"],stroke:"currentColor",fill:"none",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("accordion-insert",{viewBox:"0 0 24 24",paths:["M3 4h18","M3 8h18","M8 11l4 4 4-4","M3 16h18","M3 20h18"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("banner-insert",{viewBox:"0 0 24 24",paths:["M3 6h18","M3 10h18","M3 14h12"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("hero",{viewBox:"0 0 24 24",paths:["M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5z","M7 8h10M7 11h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("text-style",{viewBox:"0 0 24 24",paths:["M4 7V5h16v2","M9 19h6","M12 5v14","M5 12h14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("css-code",{viewBox:"0 0 24 24",paths:["M9 9l-6 3 6 3","M15 9l6 3-6 3","M13 5l-2 14"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("scribe-insert",{viewBox:"0 0 24 24",paths:["M4 20h3l10-10-3-3L4 17v3z","M14 7l3 3","M4 4h6"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"}),I.register("carousel-insert",{viewBox:"0 0 24 24",paths:["M7 5h10v14H7z","M3 8h2v8H3z","M19 8h2v8h-2z"],stroke:"currentColor",fill:"none",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"})}export function replaceRange(e,t,r,i){if(t===r&&!i)return;const n=typeof document<"u"&&typeof e.setSelectionRange=="function"&&typeof document.execCommand=="function";let s=!1;if(n){e.focus(),e.setSelectionRange(t,r);try{s=i?document.execCommand("insertText",!1,i):document.execCommand("delete")}catch{s=!1}}if(!s){const a=e.value;e.value=a.substring(0,t)+i+a.substring(r),e.selectionStart=e.selectionEnd=t+i.length,e.dispatchEvent(new Event("input",{bubbles:!0}))}}export function wrapSelection(e,t,r){const i=e.selectionStart,n=e.selectionEnd,s=e.value.substring(i,n);replaceRange(e,i,n,t+s+r),s?e.setSelectionRange(i+t.length,n+t.length):e.setSelectionRange(i+t.length,i+t.length)}export function insertAtCursor(e,t){const r=e.selectionStart;replaceRange(e,r,r,t),e.setSelectionRange(r+t.length,r+t.length)}export function attachEditorKeybindings(e){e.addEventListener("keydown",t=>{if(t.key==="Tab"){t.preventDefault();const i=e.selectionStart;if(t.shiftKey){const n=e.value.lastIndexOf(`
|
|
2
|
+
`,i-1)+1,s=e.value.substring(n).match(/^ {1,2}/);s&&(replaceRange(e,n,n+s[0].length,""),e.setSelectionRange(Math.max(n,i-s[0].length),Math.max(n,i-s[0].length)),E.toast("Dedented",{type:"info",duration:800}))}else replaceRange(e,i,i," "),E.toast("Indented",{type:"info",duration:800});return}if(!(t.ctrlKey||t.metaKey))return;const r=t.key.toLowerCase();if(r==="z")t.preventDefault(),document.execCommand("undo"),E.toast("Undo",{type:"info",duration:1200});else if(r==="y")t.preventDefault(),document.execCommand("redo"),E.toast("Redo",{type:"info",duration:1200});else if(r==="x"&&e.selectionStart===e.selectionEnd){t.preventDefault();const i=e.value.lastIndexOf(`
|
|
3
3
|
`,e.selectionStart-1)+1,n=e.value.indexOf(`
|
|
4
|
-
`,e.selectionStart),
|
|
5
|
-
`,i-1)+1,
|
|
6
|
-
`,i),a=
|
|
7
|
-
`,
|
|
8
|
-
`,n);i.substring(n,
|
|
4
|
+
`,e.selectionStart),s=n===-1?e.value.length:n+1;e.setSelectionRange(i,s),document.execCommand("cut"),e.dispatchEvent(new Event("input",{bubbles:!0})),E.toast("Line cut",{type:"info",duration:1200})}else if(r==="c"&&e.selectionStart===e.selectionEnd){t.preventDefault();const i=e.selectionStart,n=e.value.lastIndexOf(`
|
|
5
|
+
`,i-1)+1,s=e.value.indexOf(`
|
|
6
|
+
`,i),a=s===-1?e.value.length:s+1;e.setSelectionRange(n,a),document.execCommand("copy"),e.setSelectionRange(i,i),E.toast("Line copied",{type:"info",duration:1200})}})}export function insertLine(e,t){const r=e.selectionStart,i=e.value,n=i.lastIndexOf(`
|
|
7
|
+
`,r-1)+1,s=i.indexOf(`
|
|
8
|
+
`,n);i.substring(n,s===-1?i.length:s).startsWith(t)?(replaceRange(e,n,n+t.length,""),e.setSelectionRange(Math.max(n,r-t.length),Math.max(n,r-t.length))):(replaceRange(e,n,n,t),e.setSelectionRange(r+t.length,r+t.length))}function k(e,t,r,i){const n=document.querySelector(".editor-toolbar-dropdown");if(n){n.remove();return}const s=document.createElement("div");s.className="editor-toolbar-dropdown",r.forEach(function(o){if(o.heading){const d=document.createElement("div");d.className="editor-toolbar-dropdown-heading",d.textContent=o.heading,s.appendChild(d);return}const l=document.createElement("button");if(l.type="button",l.className="editor-toolbar-dropdown-item",o.icon){const d=document.createElement("span");d.setAttribute("data-icon",o.icon),l.appendChild(d)}const c=document.createElement("span");c.textContent=o.label,l.appendChild(c),l.addEventListener("click",function(){s.remove(),document.removeEventListener("click",f,!0),m(o.action,e,t,i)}),s.appendChild(l)});const a=t.getBoundingClientRect(),p=t.closest(".editor-toolbar").getBoundingClientRect();s.style.top=a.bottom-p.top+4+"px";const h=a.left-p.left;s.style.left=Math.min(h,p.width-180-8)+"px",t.closest(".editor-toolbar").appendChild(s),Domma.icons.scan(s);function f(o){!s.contains(o.target)&&o.target!==t&&(s.remove(),document.removeEventListener("click",f,!0))}setTimeout(function(){document.addEventListener("click",f,!0)},0)}function b(){return import("./shortcode-insert.js").then(e=>[{label:"Insert Image",icon:"image-add",action:"insert:image"},...e.insertMenuGroups().map(t=>({...t,items:t.items.filter(r=>r.name!=="image")})).filter(t=>t.items.length).flatMap(t=>[{heading:t.category},...t.items.map(r=>({label:r.label,icon:r.icon,action:`insert:${r.name}`}))])])}function m(e,t,r,i){const{handlers:n}=i;typeof e=="function"?e(t):typeof e=="string"&&e.startsWith("insert:")?g(e.slice(7),t):e==="effects"?n.effects&&n.effects(t):e==="help"?n.help&&n.help(t):e==="tutorial"&&n.tutorial&&n.tutorial(t)}function g(e,t){import("./shortcode-insert.js").then(r=>r.insertShortcodeByName(e,t)).catch(r=>console.error("Insert router failed to load",r))}const v=[{icon:"bold",title:"Bold (Ctrl+B)",action:e=>wrapSelection(e,"**","**")},{icon:"italic",title:"Italic (Ctrl+I)",action:e=>wrapSelection(e,"_","_")},{icon:"strikethrough",title:"Strikethrough",action:e=>wrapSelection(e,"~~","~~")},"|",{type:"dropdown",icon:"heading-1",title:"Headings",items:[{label:"Heading 1",icon:"heading-1",action:e=>insertLine(e,"# ")},{label:"Heading 2",icon:"heading-2",action:e=>insertLine(e,"## ")},{label:"Heading 3",icon:"heading-3",action:e=>insertLine(e,"### ")}]},"|",{icon:"list-bullet",title:"Bullet list",action:e=>insertLine(e,"- ")},{icon:"list-numbered",title:"Numbered list",action:e=>insertLine(e,"1. ")},"|",{type:"dropdown",icon:"quote",title:"Paragraph",items:[{label:"Blockquote",icon:"quote",action:e=>insertLine(e,"> ")},{label:"Horizontal rule",icon:"minus-circle",action:e=>insertAtCursor(e,`
|
|
9
9
|
---
|
|
10
|
-
`)}]},"|",{type:"dropdown",icon:"code-inline",title:"Code",items:[{label:"Inline code",icon:"code-inline",action:e=>wrapSelection(e,"`","`")},{label:"Code block",icon:"code-block",action:e=>wrapSelection(e,"\n```\n","\n```\n")}]},"|",{type:"dropdown",icon:"plus-circle",title:"Insert",insertMenu:!0,items:[]},"|",{icon:"sparkles",title:"Effects",action:"effects"},{icon:"book-open",title:"CRUD tutorial",action:"tutorial"},{icon:"image-add",title:"Upload or insert image",action:"insert:image"},{icon:"help-circle",title:"Editor help",action:"help"}];export function createToolbar(e,t,
|
|
10
|
+
`)}]},"|",{type:"dropdown",icon:"code-inline",title:"Code",items:[{label:"Inline code",icon:"code-inline",action:e=>wrapSelection(e,"`","`")},{label:"Code block",icon:"code-block",action:e=>wrapSelection(e,"\n```\n","\n```\n")}]},"|",{type:"dropdown",icon:"plus-circle",title:"Insert",insertMenu:!0,items:[]},"|",{icon:"sparkles",title:"Effects",action:"effects"},{icon:"book-open",title:"CRUD tutorial",action:"tutorial"},{icon:"image-add",title:"Upload or insert image",action:"insert:image"},{icon:"help-circle",title:"Editor help",action:"help"}];export function createToolbar(e,t,r={}){L();const i={help:null,tutorial:null,effects:null};r.spacerDefault&&import("./shortcode-insert.js").then(o=>o.registerInsertDefaults({spacer:{size:String(r.spacerDefault)}})).catch(()=>{});const n=e.get(0),s=t.get(0);s.textContent="",v.forEach((o,l)=>{if(o==="|"){const c=document.createElement("span");c.className="editor-toolbar-sep",s.appendChild(c)}else{const c=document.createElement("button");c.className=o.type==="dropdown"?"editor-toolbar-btn editor-toolbar-dropdown-trigger":"editor-toolbar-btn",c.setAttribute("data-tooltip",o.title),c.setAttribute("data-idx",String(l)),c.type="button";const d=document.createElement("span");if(d.setAttribute("data-icon",o.icon),c.appendChild(d),o.type==="dropdown"){const u=document.createElement("span");u.className="editor-toolbar-caret",u.setAttribute("data-icon","chevron-down"),u.setAttribute("data-icon-size","12"),u.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",c.appendChild(u)}s.appendChild(c)}});const a=document.createElement("div");a.className="editor-toolbar-right",[{mode:"split",icon:"columns",label:"Split view",active:!0},{mode:"write",icon:"file-text",label:"Write only",active:!1},{mode:"preview",icon:"eye",label:"Preview only",active:!1}].forEach(o=>{const l=document.createElement("button");l.className="editor-view-btn"+(o.active?" active":""),l.setAttribute("data-mode",o.mode),l.setAttribute("data-tooltip",o.label),l.type="button";const c=document.createElement("span");c.setAttribute("data-icon",o.icon),l.appendChild(c),a.appendChild(l)});const p=document.createElement("span");p.className="editor-toolbar-sep",a.appendChild(p);const h=document.createElement("button");h.id="fullscreen-btn",h.className="editor-toolbar-btn",h.setAttribute("data-tooltip","Toggle fullscreen"),h.type="button";const f=document.createElement("span");return f.setAttribute("data-icon","expand"),h.appendChild(f),a.appendChild(h),s.appendChild(a),Domma.icons.scan(),s.querySelectorAll("[data-tooltip]").forEach(o=>{E.tooltip(o,{content:o.getAttribute("data-tooltip"),position:"top"})}),t.on("click",".editor-toolbar-btn[data-idx]",function(){const o=parseInt($(this).data("idx"),10),l=v[o];if(!l||l==="|")return;const c=t.get(0).querySelector(`[data-idx="${o}"]`),d={handlers:i};l.type==="dropdown"?l.insertMenu?b().then(u=>k(n,c,u,d)).catch(u=>console.error("Insert menu failed to load",u)):k(n,c,l.items,d):m(l.action,n,c,d)}),attachEditorKeybindings(n),n.addEventListener("keydown",o=>{const l=o.key.toLowerCase();(o.ctrlKey||o.metaKey)&&(l==="b"?(o.preventDefault(),wrapSelection(n,"**","**")):l==="i"?(o.preventDefault(),wrapSelection(n,"_","_")):l==="k"&&(o.preventDefault(),g("link",n)))}),{$toolbar:t,onHelp(o){i.help=o},onTutorial(o){i.tutorial=o},onEffects(o){i.effects=o}}}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import{api as y}from"../api.js";import{onceClosed as x}from"./tool-kit.js";const c=l=>String(l||"/").trim().replace(/\/+$/,"")||"/";export function clonePath(l,t=[]){const n=c(l),e=`${n==="/"?"/home":n}-copy`,o=new Set(t.map(a=>c(a.urlPath)));let s=e;for(let a=2;o.has(s);a++)s=`${e}-${a}`;return s}export function clonePayload(l,t,n,e,o){const s=new Set(["urlPath","content","html","usedComponents","cacheTags","perViewer","slug","createdAt","updatedAt","plugin","presetOwner","bundled"]),a=Object.fromEntries(Object.entries(l||{}).filter(([i])=>!s.has(i)));return{urlPath:c(e),frontmatter:{...a,...t,seo:{...a.seo,...t.seo},theme:t.theme||"",breadcrumbs:t.breadcrumbs!==!1,title:String(o||"").trim(),status:"draft",showInNav:!1,bundled:!1},body:n}}export function cloneProblem(l,t,n){const e=c(l);return String(t||"").trim()?!String(l||"").trim()||!e.startsWith("/")?"The URL starts with /, for example /about-copy.":/[\s?#\\]/.test(e)||e.split("/").some(o=>o==="."||o==="..")?"Use a page URL without spaces, query strings or parent directory segments.":e===c(n)?"Choose a different URL from the original page.":"":"Give the copy a title."}export function openPageClone({page:l,frontmatter:t,body:n,source:e,pages:o,onCloned:s}){const a=M.observable(`${t.title||"Untitled"} (copy)`),i=M.observable(clonePath(e,o)),p=M.observable(!1),u=M.observable(""),b=M.computed(()=>cloneProblem(i.value,a.value,e)),r=E.slideover({title:"Clone page",size:"sm",position:"right"}),m=document.createElement("template");m.innerHTML=`<div class="page-clone-panel">
|
|
2
|
+
<p class="text-muted">Create a draft copy, including the page edits currently in the editor.</p>
|
|
3
|
+
<label class="form-label" for="page-clone-title">Title</label>
|
|
4
|
+
<input id="page-clone-title" class="form-input" type="text" data-model="title.value">
|
|
5
|
+
<label class="form-label" for="page-clone-url">URL</label>
|
|
6
|
+
<input id="page-clone-url" class="form-input" type="text" data-model="urlPath.value">
|
|
7
|
+
<p class="text-danger" data-bind-text="problem.value" data-bind-hidden="!problem.value"></p>
|
|
8
|
+
<p class="text-danger" data-bind-text="error.value" data-bind-hidden="!error.value"></p>
|
|
9
|
+
<div class="flex gap-2 mt-3">
|
|
10
|
+
<button type="button" class="btn btn-secondary" data-on-click="cancel" data-bind-disabled="saving.value">Cancel</button>
|
|
11
|
+
<button type="button" class="btn btn-primary" data-on-click="clone" data-bind-disabled="saving.value || !!problem.value">Clone page</button>
|
|
12
|
+
</div>
|
|
13
|
+
</div>`;const f=m.content.firstElementChild;let d=!1;const h=M.applyBindings({title:a,urlPath:i,saving:p,error:u,problem:b},f,{methods:{cancel:()=>r.close(),clone:async()=>{if(p.peek()||b.peek())return;p.value=!0,u.value="";const g=clonePayload(l,t,n,i.peek(),a.peek());try{if(await y.pages.create(g),d)return;r.close(),E.toast("Draft copy created.",{type:"success"}),s(g.urlPath)}catch(v){d||(u.value=v.message||"Could not clone this page.")}finally{d||(p.value=!1)}}}});return x(r,()=>{d=!0,h.dispose()}),r.setContent(f),r.open(),r}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const SCREEN=/^\/pages\/(new|edit\/.*?)(\?.*)?$/;export function pageOfPath(t){const e=String(t||"").match(/^\/pages\/edit(\/[^?#]*)/);return e?e[1]:""}export const draftKey=t=>`page-editor.draft.${t||"new"}`,FIELDS=["urlPath","title","description","layout","status","sortOrder","showInNav","sidebar","breadcrumbs","bundled","tags","category","visibility","project","theme","seoTitle","seoDesc","dconfig","body","css"];export function snapshot(t={}){const e=t||{},
|
|
1
|
+
export const SCREEN=/^\/pages\/(new|edit\/.*?)(\?.*)?$/;export function pageOfPath(t){const e=String(t||"").match(/^\/pages\/edit(\/[^?#]*)/);return e?e[1]:""}export const draftKey=t=>`page-editor.draft.${t||"new"}`,FIELDS=["urlPath","title","description","layout","status","sortOrder","showInNav","sidebar","breadcrumbs","bundled","tags","category","visibility","project","theme","seoTitle","seoDesc","dconfig","body","css"];export function snapshot(t={}){const e=t||{},o={};for(const n of FIELDS){const r=e[n];n==="tags"?o[n]=Array.isArray(r)?r.map(String):[]:typeof r=="boolean"?o[n]=r:n==="css"?o[n]=r==null?null:String(r):o[n]=r==null?"":String(r)}return JSON.stringify(o)}export function makeDraft(t,e,o=new Date().toISOString()){return{state:JSON.parse(snapshot(t)),base:e,at:o}}export function readDraft(t){return!t||typeof t!="object"||!t.state||typeof t.state!="object"?null:{state:JSON.parse(snapshot(t.state)),base:typeof t.base=="string"?t.base:"",at:typeof t.at=="string"?t.at:""}}export const draftIsStale=(t,e)=>!!(t?.base&&e&&t.base!==e);export function problems(t={}){const e=[],o=String(t.urlPath||"").trim();o?o.startsWith("/")?/\s/.test(o)&&e.push({field:"urlPath",text:"The address cannot contain spaces."}):e.push({field:"urlPath",text:"The address starts with / - for example /about."}):e.push({field:"urlPath",text:"The page needs an address - its URL path."});const n=String(t.dconfig||"").trim();if(n)try{const r=JSON.parse(n);(!r||typeof r!="object"||Array.isArray(r))&&e.push({field:"dconfig",text:"DConfig must be a JSON object ({ \u2026 })."})}catch{e.push({field:"dconfig",text:"DConfig is not valid JSON."})}return e}export function bannerSection(t,e,o){return t?String(e||"").trim()||o||"Untitled":"New page"}export function initialProject({isEdit:t,page:e=null,projects:o=[],fromHash:n="",urlPath:r=""}){if(!t&&n)return n;if(!e||e.project===null)return"";if(typeof e.project=="string"&&e.project)return e.project;if(!r)return"";let i="",a=-1;for(const s of o||[])s?.rootUrl&&(r===s.rootUrl||r.startsWith(s.rootUrl+"/"))&&s.rootUrl.length>a&&(i=s.slug,a=s.rootUrl.length);return i}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- Page editor. No page heading: the Tool banner above is the heading ("Pages ›
|
|
1
|
+
<!-- Page editor. No page heading: the Tool banner above is the heading ("Pages › …", set by
|
|
2
2
|
admin/js/views/page-editor.js), with Back, Editor reference, View on the site and Save in it. This bar
|
|
3
3
|
carries the page switcher and the unsaved state; Ctrl+S saves; leaving with unsaved changes asks and
|
|
4
4
|
keeps a draft.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{api as g}from"../api.js";import{CardBuilder as
|
|
1
|
+
import{api as g}from"../api.js";import{CardBuilder as lt}from"../lib/card-builder.js";import{TimelineBuilder as ct}from"../lib/timeline-builder.js";import{attachEditorKeybindings as dt,createToolbar as pt,insertAtCursor as ut}from"../lib/markdown-toolbar.js";import{EffectsBuilder as vt}from"../lib/effects-builder.js";import{attachContextMenu as ft}from"../lib/shortcode-context-menu.js";import{registerCustomInserters as mt}from"../lib/shortcode-insert.js";import{populateThemeSelect as bt}from"../lib/themes.js";import{createFoldingManager as gt}from"../lib/editor-folding.js";import{openScribeComposer as ht}from"../lib/scribe-composer.js";import{openCrudTutorial as yt}from"../lib/crud-tutorial.js";import{addBannerAction as $}from"../lib/plugin-chrome.js";import{helpPopovers as je}from"../lib/help-popover.js";import{onceClosed as he,openMenuAt as qe}from"../lib/tool-kit.js";import{pickMedia as wt}from"../lib/media-picker.js";import{openPageClone as kt}from"../lib/page-clone.js";import{openEditorReference as Ve}from"../lib/page-editor-reference.js";import{cleanType as G,DEFAULT_TYPE as Y,EDITOR_FONTS as Et,fontHref as Mt,isDefaultType as St,LINE_HEIGHTS as Ct,SIZES as Tt,typeVars as He}from"../lib/editor-type.js";import{getProjectFromHash as xt}from"../lib/project-context.js";import{SCREEN as Pt,bannerSection as Lt,draftIsStale as Dt,draftKey as At,initialProject as Ot,makeDraft as Rt,problems as ye,readDraft as Ft,snapshot as z}from"../lib/page-editor-arrange.js";import{fmtDateTime as X}from"../lib/dates.js";function Z(a){const r=document.createElement("template");return r.innerHTML=a.trim(),r.content.firstElementChild}const Nt=X,Ke=a=>X(a.createdAt)+(a.label?` - ${a.label}`:""),Bt=`
|
|
2
2
|
<div class="pe-share">
|
|
3
3
|
<p class="form-hint" style="margin-top:0">Anyone with the link can view this page even while it is unpublished, without
|
|
4
4
|
signing in. The link works for this page only, expires on its own, and can be revoked at any time.</p>
|
|
@@ -30,7 +30,7 @@ import{api as g}from"../api.js";import{CardBuilder as it}from"../lib/card-builde
|
|
|
30
30
|
.pe-share [hidden] { display: none !important; }
|
|
31
31
|
.pe-share-row { display: flex; align-items: center; gap: .6rem; padding: .5rem 0; border-bottom: 1px solid var(--dm-border-light); }
|
|
32
32
|
.pe-share-text { flex: 1 1 auto; min-width: 0; font-size: .82rem; }
|
|
33
|
-
</style>`;function
|
|
33
|
+
</style>`;function Ue(a){const r=Mt(a);if(!r||document.querySelector(`link[data-pe-font="${CSS.escape(a)}"]`))return;const l=Object.assign(document.createElement("link"),{rel:"stylesheet",href:r});l.dataset.peFont=a,document.head.appendChild(l)}const It=`
|
|
34
34
|
<div class="pe-settings">
|
|
35
35
|
<p class="pe-settings-note">How the editor looks to you - kept in this browser, for every page.</p>
|
|
36
36
|
<label class="form-label" for="pe-set-font">Font <span data-help="The lettering in the editor (not on the site). Monospace keeps every character the same width, so shortcodes and Markdown line up."></span></label>
|
|
@@ -61,17 +61,17 @@ The quick brown fox - 0O 1lI {} [] () => ==
|
|
|
61
61
|
.pe-settings-sample { white-space: pre-wrap; padding: .75rem 1rem; border-radius: var(--dm-radius-md); border: 1px solid var(--dm-border);
|
|
62
62
|
background: var(--dm-background-alt); font-family: var(--pe-font); font-size: var(--pe-size); line-height: var(--pe-line); }
|
|
63
63
|
.pe-settings-actions { display: flex; gap: .5rem; border-top: 1px solid var(--dm-border); padding-top: .75rem; }
|
|
64
|
-
</style>`;function
|
|
64
|
+
</style>`;function $t(a){const r=E.slideover({title:"Editor settings",size:"sm",position:"right"}),l=Z(`<div>${It}</div>`),s=G(a.peek()),i={font:M.observable(s.font),size:M.observable(String(s.size)),line:M.observable(String(s.line)),wrap:M.observable(s.wrap)},f=M.computed(()=>G({font:i.font.value,size:i.size.value,line:i.line.value,wrap:i.wrap.value}));i.isDefault=M.computed(()=>St(f.value));const p=l.querySelector("#pe-set-font");for(const[v,C]of[["mono","Monospace"],["sans","Other"],["serif",null]]){const N=Et.filter(b=>b.kind===v),q=C?Object.assign(document.createElement("optgroup"),{label:C}):p.querySelector("optgroup:last-of-type");q.append(...N.map(b=>new Option(b.label,b.id))),C&&p.appendChild(q)}l.querySelector("#pe-set-size").append(...Tt.map(v=>new Option(`${v}px`,String(v)))),l.querySelector("#pe-set-line").append(...Ct.map(v=>new Option({1.3:"Tight",1.45:"Snug",1.6:"Normal",1.8:"Relaxed",2:"Double"}[v]||String(v),String(v))));const c=l.querySelector(".pe-settings-sample"),u=M.effect(()=>{const v=f.value;Ue(v.font);for(const[C,N]of Object.entries(He(v)))c.style.setProperty(C,N);c.style.whiteSpace=v.wrap?"pre-wrap":"pre",c.style.overflowX=v.wrap?"":"auto",JSON.stringify(v)!==JSON.stringify(G(a.peek()))&&(a.value=v,Q("type",v))});i.reset=()=>{i.font.value=Y.font,i.size.value=String(Y.size),i.line.value=String(Y.line),i.wrap.value=Y.wrap},i.done=()=>r.close(),r.element.appendChild(l);const T=M.applyBindings(i,l),d=je(l);return he(r,()=>{T.dispose(),d(),u?.()}),Domma.icons?.scan?.(l),r.open(),r}async function zt(a){const r=E.slideover({title:"Share preview link",size:"md",position:"right"}),l=Z(`<div>${Bt}</div>`),s={expiry:M.observable("7d"),note:M.observable(""),creating:M.observable(!1),url:M.observable(""),links:M.observable([]),loaded:M.observable(!1),listError:M.observable("")},i=async()=>{try{const p=await g.pages.previewLinks.list(a);s.links.value=p.filter(c=>!c.revokedAt&&!c.expired).map(c=>({id:c.id,title:c.label||"Untitled link",meta:`Expires ${Nt(c.expiresAt)} - ${c.useCount===1?"1 view":`${c.useCount||0} views`}`})),s.listError.value=""}catch(p){s.listError.value="Could not load existing links: "+(p.message||"unknown error")}finally{s.loaded.value=!0}};s.create=async()=>{s.creating.value=!0;try{const p=await g.pages.previewLinks.create(a,s.expiry.peek(),s.note.peek().trim());s.url.value=p.url,s.note.value="",E.toast("Share link created.",{type:"success"}),await i(),l.querySelector(".pe-share-url")?.select()}catch(p){E.toast("Could not create link: "+(p.message||"unknown error"),{type:"error"})}finally{s.creating.value=!1}},s.copy=async()=>{try{await navigator.clipboard.writeText(s.url.peek()),E.toast("Link copied to clipboard.",{type:"success"})}catch{l.querySelector(".pe-share-url")?.select(),E.toast("Press Ctrl+C to copy the selected link.",{type:"info"})}},s.revoke=async p=>{if(await E.confirm("Revoke this link? Anyone holding it loses access immediately."))try{await g.pages.previewLinks.revoke(p),E.toast("Link revoked.",{type:"success"}),await i()}catch(c){E.toast("Could not revoke: "+(c.message||"unknown error"),{type:"error"})}};const f=M.applyBindings(s,l);he(r,()=>f.dispose()),r.element.appendChild(l),r.open(),await i()}function jt(a){return new Promise(r=>{const l=E.slideover({title:"Save Named Version",size:"sm",position:"right"}),s=Z(`
|
|
65
65
|
<div style="padding:1rem">
|
|
66
66
|
<label class="form-label" for="pe-version-label">Version Label</label>
|
|
67
67
|
<input id="pe-version-label" type="text" class="form-input" style="margin-bottom:.75rem"
|
|
68
68
|
placeholder="e.g. Initial design, Before restructure" data-model="label.value" data-on-keydown="key">
|
|
69
69
|
<button type="button" class="btn btn-primary" data-on-click="save" data-bind-disabled="saving.value">Save Version</button>
|
|
70
|
-
</div>`);let i=!1;const f={label:M.observable(""),saving:M.observable(!1)};f.save=async()=>{f.saving.value=!0;try{await g.versions.create(a,f.label.peek().trim()||null),E.toast("Named version saved.",{type:"success"}),i=!0,l.close()}catch(c){E.toast("Failed to save version: "+c.message,{type:"error"})}finally{f.saving.value=!1}},f.key=c=>{c.key==="Enter"&&(c.preventDefault(),f.save())};const p=M.applyBindings(f,s);
|
|
70
|
+
</div>`);let i=!1;const f={label:M.observable(""),saving:M.observable(!1)};f.save=async()=>{f.saving.value=!0;try{await g.versions.create(a,f.label.peek().trim()||null),E.toast("Named version saved.",{type:"success"}),i=!0,l.close()}catch(c){E.toast("Failed to save version: "+c.message,{type:"error"})}finally{f.saving.value=!1}},f.key=c=>{c.key==="Enter"&&(c.preventDefault(),f.save())};const p=M.applyBindings(f,s);he(l,()=>{p.dispose(),r(i)}),l.element.appendChild(s),l.open(),setTimeout(()=>s.querySelector("input")?.focus(),100)})}let w=null,_e=!1;function qt(){_e||!window.R?.use||(_e=!0,R.use((a,r,l)=>{const s=r?.path||"",i=a?.path||"",f=Pt.test(s)&&i!==s;return f&&w?.path===s&&w.cloneTarget===i?(w.cloneTarget=null,w.keepDraft(),l()):!f||!w||w.path!==s||!w.dirty()?l():E.confirm("You have unsaved changes to this page. Leave anyway? They are kept as a draft for your next visit.").then(p=>{p?(w?.keepDraft(),l()):history.replaceState(null,"","#"+s)})}),M.subscribe("router:afterChange",({to:a}={})=>{if(w&&(a?.path||"")!==w.path){const r=w;w=null,r.dispose()}}))}function Vt(a){return a.split(`
|
|
71
71
|
`).map(r=>r.trimEnd()).join(`
|
|
72
72
|
`).replace(/\n{3,}/g,`
|
|
73
73
|
|
|
74
|
-
`)}const
|
|
74
|
+
`)}const We="editor_prefs";function j(){return S.get(We)||{viewMode:"split",fullscreen:!1}}function Q(a,r){const l=j();l[a]=r,S.set(We,l)}const Ht=["edit","details","seo","dconfig","live","history"],Je=["split","write","preview"],Kt=a=>a.replace(/<\/head>/i,"<style>body.dm-cloaked{opacity:1 !important;transition:none !important}</style></head>");function Ge(a,r,l=()=>{}){let s=0;try{s=a.contentWindow.scrollY||0}catch{}a.addEventListener("load",()=>{try{a.contentWindow.scrollTo(0,s)}catch{}l()},{once:!0}),a.srcdoc=r}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(a){if(qt(),w){const e=w;w=null,e.dispose()}const r=window.location.hash.replace(/^#/,""),l=[],s=e=>(l.push(e),e);let i=()=>!1,f=()=>{};const p={path:r,dirty:()=>i(),keepDraft:()=>f(),dispose:()=>{l.splice(0).forEach(e=>{try{e()}catch{}})}};w=p;const c=a.get(0),u=()=>w===p&&c.isConnected,T=window.location.hash.match(/#\/pages\/edit(\/[^?]*)/),d=T?T[1]:null,v=!!d,C=E.loader(c,{type:"dots"}),[N,q,b,ee,we,Ye]=await Promise.all([g.layouts.get().catch(()=>({})),g.settings.get().catch(()=>({})),v?g.pages.get(d).catch(()=>null):null,v?g.pages.list().catch(()=>[]):[],g.projects.list().catch(()=>[]),g.pages.tags().catch(()=>[])]);if(!u()){C.destroy();return}if(C.destroy(),v&&!b){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}const y=e=>c.querySelector(e);if(bt(y("#field-theme"),{includeDefault:!0}),await Gt(y("#field-visibility"),b?.visibility),!u())return;const Xe=Jt(y("#field-layout"),N,b?.layout||"default");for(const e of we)y("#field-project").append(new Option(e.name||e.slug,e.slug));const ke=[...Array.isArray(ee)?ee:[]].sort((e,t)=>(e.title||e.urlPath).localeCompare(t.title||t.urlPath));for(const e of ke)y("#quick-switch").append(new Option(`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath,!1,e.urlPath===d));const V=j(),o={urlPath:M.observable(d||""),title:M.observable(b?.title||""),description:M.observable(b?.description||""),layout:M.observable(Xe),status:M.observable(b?.status||"draft"),sortOrder:M.observable(String(b?.sortOrder??99)),showInNav:M.observable(!!b?.showInNav),sidebar:M.observable(!!b?.sidebar),breadcrumbs:M.observable(b?b.breadcrumbs!==!1:!0),bundled:M.observable(!!b?.bundled),tags:M.observable(Array.isArray(b?.tags)?b.tags:[]),category:M.observable(b?.category||""),visibility:M.observable(typeof b?.visibility=="string"&&b.visibility?b.visibility:"public"),project:M.observable(Ot({isEdit:v,page:b,projects:we,fromHash:xt()||"",urlPath:d||""})),theme:M.observable(b?.theme||""),seoTitle:M.observable(b?.seo?.title||""),seoDesc:M.observable(b?.seo?.description||""),dconfig:M.observable(b?.dconfig?JSON.stringify(b.dconfig,null,2):""),css:M.observable(""),cssOpened:M.observable(!1)},n={bodyRev:M.observable(0),base:M.observable(""),saving:M.observable(!1),tab:M.observable("edit"),viewMode:M.observable(Je.includes(V.viewMode)?V.viewMode:"split"),fullscreen:M.observable(!!V.fullscreen),cssMode:M.observable(!1),folded:M.observable(!1),liveStatus:M.observable("Showing unsaved changes"),liveWidth:M.observable("full"),versions:M.observable([]),histLoading:M.observable(!1),histError:M.observable(""),compare:M.observable(null)},k=y("#markdown-editor"),B=y("#css-editor");k.value=b?.content||"";const L=document.createElement("div");L.className="editor-line-numbers editor-line-numbers--foldable",k.parentElement.insertBefore(L,k);const x=gt(k,L,{onFoldChange:()=>{}});let O=!1;x.setGuard(e=>{O=e});const I=()=>x.getUnfoldedContent(),Ee=M.observable(G(V.type));s(M.effect(()=>{const e=Ee.value,t=y("#editor-body");if(t){Ue(e.font);for(const[m,h]of Object.entries(He(e)))t.style.setProperty(m,h);t.classList.toggle("pe-nowrap",!e.wrap),k.wrap=e.wrap?"soft":"off",B.wrap=e.wrap?"soft":"off"}}));let Me=null;s(()=>{try{Me?.close()}catch{}});const D=()=>(n.bodyRev.value,{urlPath:o.urlPath.value.trim(),title:o.title.value,description:o.description.value,layout:o.layout.value,status:o.status.value,sortOrder:o.sortOrder.value,showInNav:o.showInNav.value,sidebar:o.sidebar.value,breadcrumbs:o.breadcrumbs.value,bundled:o.bundled.value,tags:o.tags.value,category:o.category.value,visibility:o.visibility.value,project:o.project.value,theme:o.theme.value,seoTitle:o.seoTitle.value,seoDesc:o.seoDesc.value,dconfig:o.dconfig.value,body:I(),css:o.cssOpened.value?o.css.value:null}),Ze=M.computed(()=>z(D())!==n.base.value),Qe=M.computed(()=>ye({urlPath:o.urlPath.value,dconfig:o.dconfig.value})[0]?.text||""),et=M.computed(()=>n.versions.value.some(e=>e.checked.value)),tt=M.computed(()=>n.versions.value.length>0&&n.versions.value.every(e=>e.checked.value)),at=M.computed(()=>{const e=n.versions.value.filter(t=>t.checked.value).length;return e>0&&e<n.versions.value.length});i=()=>z(D())!==n.base.peek();const H=e=>({title:o.title.peek().trim()||"Untitled",description:o.description.peek().trim(),layout:o.layout.peek(),status:o.status.peek(),sortOrder:parseInt(String(o.sortOrder.peek()),10)||99,showInNav:o.showInNav.peek(),sidebar:o.sidebar.peek(),...o.breadcrumbs.peek()?{}:{breadcrumbs:!1},...o.bundled.peek()?{bundled:!0}:{},tags:o.tags.peek(),category:o.category.peek().trim()||null,visibility:o.visibility.peek()||"public",project:o.project.peek()||"",seo:{title:o.seoTitle.peek().trim(),description:o.seoDesc.peek().trim()},dconfig:e,...o.theme.peek()?{theme:o.theme.peek()}:{}}),te=()=>{const e=o.dconfig.peek().trim();if(!e)return null;try{return JSON.parse(e)}catch{return null}},Se=()=>o.urlPath.peek().trim()||d||"/",K=y("#markdown-preview");let Ce="";g.settings.getCustomCss().then(({css:e})=>{Ce=e||""}).catch(()=>{});const Te=()=>{const e=K?.contentDocument;if(!e?.head)return;const t=o.cssOpened.peek()?o.css.peek():"";if(!t)return;let m=e.getElementById("preview-custom-css");m||(m=e.createElement("style"),m.id="preview-custom-css",e.head.appendChild(m)),m.textContent=t};let ae=null;const U=()=>{clearTimeout(ae),ae=setTimeout(async()=>{if(!(!K||n.viewMode.peek()==="write"))try{const{html:e}=await g.pages.previewFull(Se(),H(te()),I());u()&&Ge(K,Kt(e),Te)}catch(e){K.srcdoc='<!doctype html><meta charset="utf-8"><body style="font:14px system-ui;padding:1rem;color:#b91c1c;">Preview failed: '+String(e?.message||"unknown error").replace(/[<&]/g,t=>t==="<"?"<":"&")+"</body>"}},500)},xe=y("#live-preview-frame");let se=!0,oe=null,ne=!1;const re=async()=>{if(!(ne||!xe)){ne=!0,n.liveStatus.value="Rendering\u2026";try{const{html:e}=await g.pages.previewFull(Se(),H(te()),I());if(!u())return;Ge(xe,e),se=!1,n.liveStatus.value="Showing unsaved changes"}catch(e){n.liveStatus.value="Preview failed - "+(e?.message||"unknown error")}finally{ne=!1}}},Pe=()=>{se=!0,n.tab.peek()==="live"&&(clearTimeout(oe),oe=setTimeout(re,600))};s(()=>{clearTimeout(ae),clearTimeout(oe)});const ie=pt(a.find("#markdown-editor"),a.find("#editor-toolbar"),{spacerDefault:q?.layoutOptions?.spacerSize??40});ft(k);const le=c.querySelector(".editor-toolbar-right");le.querySelectorAll(".editor-view-btn[data-mode]").forEach(e=>{const t=e.getAttribute("data-mode");e.classList.remove("active"),e.setAttribute("data-bind-class",`viewMode.value === '${t}' && 'active'`),e.setAttribute("data-on-click",`setMode('${t}')`)}),y("#fullscreen-btn")?.setAttribute("data-on-click","toggleFullscreen");const st=Z(`
|
|
75
75
|
<span class="pe-toolbar-extras" style="display:contents">
|
|
76
76
|
<button type="button" class="editor-view-btn" data-tip="Edit Custom CSS" data-on-click="toggleCss"
|
|
77
77
|
data-bind-class="cssMode.value && 'active'"><span>CSS</span></button>
|
|
@@ -83,5 +83,5 @@ The quick brown fox - 0O 1lI {} [] () => ==
|
|
|
83
83
|
<span class="pe-fold-icon" hidden data-bind-hidden="!folded.value"><span data-icon="chevrons-right" data-icon-size="10"></span></span>
|
|
84
84
|
</button>
|
|
85
85
|
<span class="editor-toolbar-sep"></span>
|
|
86
|
-
</span>`);
|
|
87
|
-
`).map((s,i)=>{const f=document.createElement("span");f.className="editor-line-number-row";const p=document.createElement("span");p.className="fold-toggle fold-toggle--empty";const c=document.createElement("span");return c.className="editor-line-num",c.textContent=String(i+1),f.append(p,c),f})),a.scrollTop=l.scrollTop}function
|
|
86
|
+
</span>`);le.prepend(st);const Le=y("#field-tags"),ce=Le?E.pillbox(Le,{data:Ye,value:o.tags.peek(),creatable:!0,searchable:!0,placeholder:"Add tag\u2026",onChange:()=>{o.tags.value=ce?[...ce.getValue()]:[]}}):null;let de=!1,pe=null;const _=async()=>{de=!0,n.histLoading.value=!0,n.histError.value="";try{const e=(await g.versions.list(d)).versions||[];if(!u())return;n.versions.value=e.map(t=>({...t,when:X(t.createdAt),author:t.author||"",label:t.label||"",checked:M.observable(!1)}))}catch(e){n.histError.value="Failed to load versions: "+e.message}finally{n.histLoading.value=!1}},ue=e=>n.versions.peek().find(t=>t.filename===e),ve=async e=>{try{const t=await g.versions.get(d,e.filename);pe=e.filename,n.compare.value={label:Ke(e),old:t.content,current:I()}}catch(t){E.toast("Failed to load version: "+t.message,{type:"error"})}},De=async e=>{if(!(!e||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await g.versions.restore(d,e),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${d}`),300)}catch(t){E.toast("Restore failed: "+t.message,{type:"error"})}},ot=async e=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await g.versions.delete(d,e.filename),E.toast("Version deleted.",{type:"success"}),await _()}catch(t){E.toast("Failed to delete: "+t.message,{type:"error"})}},Ae=()=>{n.bodyRev.value=n.bodyRev.peek()+1},Oe=()=>{o.cssOpened.peek()||(o.css.value=Ce,o.cssOpened.value=!0,dt(B))},Re=e=>{for(const t of["urlPath","title","description","layout","status","sortOrder","category","visibility","project","theme","seoTitle","seoDesc","dconfig"])o[t].value=e[t]==null?"":String(e[t]);for(const t of["showInNav","sidebar","breadcrumbs","bundled"])o[t].value=!!e[t];o.tags.value=Array.isArray(e.tags)?e.tags:[],ce?.setValue(o.tags.peek()),x.unfoldAll(),O=!0,k.value=e.body==null?"":String(e.body),O=!1,x.refresh(),e.css!=null&&(Oe(),o.css.value=String(e.css)),Ae()};n.base.value=z(D());const W=At(d||"");f=()=>{if(i())try{S.set(W,Rt(D(),n.base.peek()))}catch{}};const fe=()=>{try{S.remove?S.remove(W):S.set(W,null)}catch{}},Fe=e=>{i()&&(f(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",Fe),s(()=>window.removeEventListener("beforeunload",Fe));const Ne=async()=>{if(n.saving.peek())return;const e=D(),t=ye(e);if(t.length){E.toast(t[0].text,{type:"warning"}),c.querySelectorAll("#editor-meta-tabs .tab-item")[Ht.indexOf(t[0].field==="dconfig"?"dconfig":"details")]?.click();return}const m=(e.dconfig||"").trim(),h=H(m?JSON.parse(m):null),P=o.cssOpened.peek();n.saving.value=!0;try{if(v){const A={frontmatter:h,body:e.body};e.urlPath!==d&&(A.newUrlPath=e.urlPath),await g.pages.update(d,A)}else await g.pages.create({urlPath:e.urlPath,frontmatter:h,body:e.body});P&&await g.settings.saveCustomCss(o.css.peek()),E.toast(P?"Page and CSS saved.":"Page saved.",{type:"success"}),fe(),n.base.value=z(D()),v?e.urlPath!==d&&R.navigate(`/pages/edit${e.urlPath}`):R.navigate("/pages")}catch(A){E.toast(`Save failed: ${A.message||"Unknown error"}`,{type:"error"})}finally{n.saving.value=!1}},Be=c.querySelector(".dm-plugin-body")||c,nt={...o,...n,dirty:Ze,problem:Qe,anySelected:et,allSelected:tt,someSelected:at,isEdit:v,savedPath:d||"",hasPages:ke.length>0},rt={save:()=>Ne(),discard:async()=>{!i()||!await E.confirm("Discard the changes you have not saved?")||(Re(JSON.parse(n.base.peek())),fe())},switchPage:e=>{const t=e?.target?.value;t&&R.navigate("/pages/edit"+t)},showTab:e=>{n.tab.value=e,e==="live"&&se&&re(),e==="history"&&v&&!de&&_()},setMode:e=>{n.cssMode.peek()&&(n.cssMode.value=!1),n.viewMode.value=e,Q("viewMode",e),e!=="write"&&U()},toggleFullscreen:()=>{n.fullscreen.value=!n.fullscreen.peek(),Q("fullscreen",n.fullscreen.peek())},toggleCss:()=>{n.cssMode.peek()?(n.cssMode.value=!1,n.viewMode.value=Je.includes(j().viewMode)?j().viewMode:"split",x.refresh()):(Oe(),n.cssMode.value=!0,n.viewMode.value="split")},formatMarkdown:()=>{const e=k.selectionStart,t=Vt(I());x.unfoldAll(),O=!0,k.value=t,O=!1,k.selectionStart=k.selectionEnd=Math.min(e,t.length),k.dispatchEvent(new Event("input")),x.refresh(),E.toast("Markdown formatted.",{type:"success"})},toggleFold:()=>{n.folded.peek()?x.unfoldAll():x.foldAll(),n.folded.value=!n.folded.peek()},setWidth:e=>{n.liveWidth.value=e;const t=y("#live-preview-stage");t&&(t.scrollTop=0)},refreshLive:()=>re(),share:async()=>{if(!v){E.toast("Save the page first - a share link needs a page to point at.",{type:"warning"});return}await zt(d)},toggleAll:e=>{const t=!!e?.target?.checked;n.versions.peek().forEach(m=>{m.checked.value=t})},deleteSelected:async()=>{const e=n.versions.peek().filter(m=>m.checked.peek()).map(m=>m.filename),t=e.length;if(!(!t||!await E.confirm(`Delete ${t} version${t>1?"s":""}? This cannot be undone.`)))try{await g.versions.bulkDelete(d,e),E.toast(`${t} version${t>1?"s":""} deleted.`,{type:"success"}),await _()}catch(m){E.toast("Delete failed: "+m.message,{type:"error"})}},saveNamed:async()=>{await jt(d)&&u()&&(n.tab.peek()==="history"?await _():de=!1)},closeCompare:()=>{n.compare.value=null,pe=null},restoreCompared:()=>De(pe)};le.querySelectorAll("[data-tip]").forEach(e=>E.tooltip(e,{content:e.getAttribute("data-tip"),position:"top"}));const it=M.applyBindings(nt,Be,{methods:rt});s(()=>it.dispose()),E.tabs(y("#editor-meta-tabs"));let me=null;s(()=>clearTimeout(me)),k.addEventListener("input",()=>{x.refresh(),L.scrollTop=k.scrollTop,!O&&(clearTimeout(me),me=setTimeout(Ae,120),U(),Pe())}),k.addEventListener("scroll",()=>{L.scrollTop=k.scrollTop}),B.addEventListener("scroll",()=>{L.scrollTop=B.scrollTop});let Ie=!0;s(M.effect(()=>{for(const e of Object.keys(o))e!=="css"&&e!=="cssOpened"&&o[e].value;if(n.bodyRev.value,Ie){Ie=!1,U();return}U(),Pe()}));let be=null;if(s(()=>clearTimeout(be)),s(M.effect(()=>{const e=o.css.value;n.cssMode.value&&(Ut(L,e,B),clearTimeout(be),be=setTimeout(Te,400))})),v){const e=y(".pe-version-list"),t=E.contextMenu(e,{cursor:"glyph",match:"tr[data-file]",inherit:!1,density:"compact",items:m=>{const h=ue(m.dataset.file);return h?[{header:Ke(h)},{label:"Compare with the editor",icon:"columns",action:()=>ve(h)},{label:"Restore this version\u2026",icon:"rotate-ccw",action:()=>De(h.filename)},{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>ot(h)}]:[]}});s(()=>t?.destroy?.()),e.addEventListener("click",m=>{const h=m.target.closest("tr[data-file]");if(!h||m.target.matches("input"))return;const P=m.target.closest(".pe-kebab");if(P){qe(P);return}const A=ue(h.dataset.file);A&&ve(A)}),e.addEventListener("keydown",m=>{const h=m.target.closest("tr[data-file]");if(h){if(m.key==="F10"&&m.shiftKey)m.preventDefault(),qe(h);else if(m.key==="Enter"&&m.target===h){const P=ue(h.dataset.file);P&&ve(P)}}})}_t(y("#editor-body"),y("#editor-divider"),s),mt({image:e=>(n.cssMode.value=!1,Wt(e)),scribe:e=>ht(e),card:e=>lt.open(e,{onMediaBrowse:()=>g.media.list().catch(()=>[])}),timeline:e=>ct.open(e,{onPreview:async t=>{try{return await g.pages.preview(t)}catch{return null}},onListCollections:()=>g.collections.list().catch(()=>[]),onGetCollection:t=>g.collections.get(t).catch(()=>null)})}),ie.onEffects(e=>vt.open(e)),ie.onHelp(()=>Ve()),ie.onTutorial(e=>yt(e));const $e=e=>{(e.ctrlKey||e.metaKey)&&!e.shiftKey&&!e.altKey&&e.key.toLowerCase()==="s"&&u()&&(e.preventDefault(),Ne())};document.addEventListener("keydown",$e),s(()=>document.removeEventListener("keydown",$e));const J=c.querySelector(".dm-plugin-banner-name");s(M.effect(()=>{const e=Lt(v,o.title.value,d);if(!u()||(document.title=`${e} - Domma CMS`,!J))return;const t=J.lastChild;t&&t.nodeType===3&&J.querySelector(".dm-plugin-banner-sep")?t.textContent=e:J.textContent=`Pages \u203A ${e}`})),$(a,{id:"page-editor-back",icon:"arrow-left",title:"Back to Pages",onClick:()=>R.navigate("/pages")}),$(a,{id:"page-editor-help",icon:"help-circle",title:"Editor reference",onClick:()=>Ve()}),v&&$(a,{id:"page-editor-view",icon:"external-link",title:"View on the site",onClick:()=>window.open(o.urlPath.peek()||d,"_blank","noopener")});const ge=$(a,{id:"page-editor-clone",icon:"copy",title:"Clone page",onClick:()=>{if(!v||n.saving.peek()||!u())return;const e=D(),t=ye({...e,urlPath:d});if(t.length){E.toast(t[0].text,{type:"warning"});return}const m=kt({page:b,frontmatter:H(te()),body:e.body,source:d,pages:ee,onCloned:h=>{u()&&(p.cloneTarget=`/pages/edit${h}`,R.navigate(p.cloneTarget))}});s(()=>m.close())}});ge&&(ge.disabled=!v,v||(ge.title="Save the page before cloning it")),$(a,{id:"page-editor-settings",icon:"settings",title:"Editor settings - font, size, spacing",onClick:()=>{Me=$t(Ee)}}),s(je(Be,{position:"bottom"})),Domma.icons.scan();let ze=null;try{ze=S.get(W)}catch{}const F=Ft(ze);if(F&&(fe(),z(F.state)!==n.base.peek())){const e=F.at?` (${X(F.at)})`:"",t=Dt(F,n.base.peek())?" The saved page has changed since - restoring puts your version back over it (the saved one stays in History).":"";await E.confirm(`You left unsaved changes to this page${e}. Restore them?${t}`)&&u()&&Re(F.state)}}};function Ut(a,r,l){a.replaceChildren(...String(r).split(`
|
|
87
|
+
`).map((s,i)=>{const f=document.createElement("span");f.className="editor-line-number-row";const p=document.createElement("span");p.className="fold-toggle fold-toggle--empty";const c=document.createElement("span");return c.className="editor-line-num",c.textContent=String(i+1),f.append(p,c),f})),a.scrollTop=l.scrollTop}function _t(a,r,l){if(!a||!r)return;const s=15,i=85,f=d=>Math.min(i,Math.max(s,d));let p=f(parseFloat(j().splitRatio)||50);const c=d=>{a.style.setProperty("--dm-editor-split",p+"%"),r.setAttribute("aria-valuenow",String(Math.round(p))),d&&Q("splitRatio",p)};c(!1);const u=d=>{const v=a.getBoundingClientRect();v.width&&(p=f((d.clientX-v.left)/v.width*100)),c(!1)},T=()=>{document.removeEventListener("pointermove",u),document.removeEventListener("pointerup",T),a.classList.remove("is-resizing"),r.classList.remove("is-dragging"),c(!0)};l(T),r.addEventListener("pointerdown",d=>{window.matchMedia("(max-width: 768px)").matches||(d.preventDefault(),a.classList.add("is-resizing"),r.classList.add("is-dragging"),document.addEventListener("pointermove",u),document.addEventListener("pointerup",T))}),r.addEventListener("dblclick",()=>{p=50,c(!0)}),r.addEventListener("keydown",d=>{const v=d.shiftKey?10:2;let C=p;if(d.key==="ArrowLeft")C=p-v;else if(d.key==="ArrowRight")C=p+v;else if(d.key==="Home")C=s;else if(d.key==="End")C=i;else if(d.key==="Enter"||d.key===" ")C=50;else return;d.preventDefault(),p=f(C),c(!0)})}async function Wt(a){const r=a.selectionStart,l=a.selectionEnd,s=await wt({title:"Upload or insert an image"});if(!s||!a.isConnected)return;let i=s.split("/").pop().split("?")[0];try{i=decodeURIComponent(i)}catch{}const f=i.replace(/[\\[\]]/g,"\\$&"),p=s.replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/ /g,"%20");a.setSelectionRange(r,l),ut(a,``),a.dispatchEvent(new Event("input",{bubbles:!0}))}function Jt(a,r,l){const s=Object.entries(r||{});return a?(a.replaceChildren(...s.map(([i,f])=>new Option(f?.label||i,i))),s.some(([i])=>i===l)?l:s[0]?.[0]||l):l}async function Gt(a,r){if(!a)return;let l=[];try{const u=await g.get("/collections/roles/entries?limit=100");l=Array.isArray(u)?u:u?.entries||[]}catch{}const s=l.map(u=>({name:u.data?.name,label:u.data?.label||u.data?.name,level:u.data?.level??99})).filter(u=>u.name&&u.level!==0).sort((u,T)=>T.level-u.level),i=(u,T)=>Object.assign(document.createElement("option"),{value:u,textContent:T}),f=()=>{typeof r=="string"&&r&&![...a.options].some(u=>u.value===r)&&a.append(i(r,`${r} (custom)`))};if(!s.length)return f();const p=document.createElement("optgroup");p.label="Role and above",s.forEach(u=>p.append(i(u.name,`${u.label} and above`)));const c=document.createElement("optgroup");c.label="Role only",s.forEach(u=>c.append(i(`=${u.name}`,`${u.label} only`))),a.replaceChildren(i("public","Public - everyone"),p,c,i("private","Private - super-admin only")),f()}
|