@formfeed/engine 0.3.10 → 0.3.12
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/index.cjs +4728 -438
- package/index.js +4728 -438
- package/package.json +3 -2
- package/types/frame/fit.d.cts +13 -0
- package/types/frame/fit.d.ts +13 -0
- package/types/frame/fit.entry.d.cts +1 -0
- package/types/frame/fit.entry.d.ts +1 -0
- package/types/frame/stage.d.cts +22 -0
- package/types/frame/stage.d.ts +22 -0
- package/types/frame/stage.entry.d.cts +1 -0
- package/types/frame/stage.entry.d.ts +1 -0
- package/types/frame/text-edit.d.cts +82 -0
- package/types/frame/text-edit.d.ts +82 -0
- package/types/frame/text-edit.entry.d.cts +1 -0
- package/types/frame/text-edit.entry.d.ts +1 -0
- package/types/index.d.cts +23 -14
- package/types/index.d.ts +23 -14
- package/types/lib/assemble.d.cts +13 -0
- package/types/lib/assemble.d.ts +13 -0
- package/types/lib/design/emit.d.cts +20 -0
- package/types/lib/design/emit.d.ts +20 -0
- package/types/lib/design/fonts.d.cts +27 -0
- package/types/lib/design/fonts.d.ts +27 -0
- package/types/lib/design/hash.d.cts +6 -0
- package/types/lib/design/hash.d.ts +6 -0
- package/types/lib/design/index.d.cts +12 -0
- package/types/lib/design/index.d.ts +12 -0
- package/types/lib/design/layers.d.cts +12 -0
- package/types/lib/design/layers.d.ts +12 -0
- package/types/lib/design/parse.d.cts +25 -0
- package/types/lib/design/parse.d.ts +25 -0
- package/types/lib/design/starters.d.cts +14 -0
- package/types/lib/design/starters.d.ts +14 -0
- package/types/lib/design/types.d.cts +171 -0
- package/types/lib/design/types.d.ts +171 -0
- package/types/lib/dialect.d.cts +32 -0
- package/types/lib/dialect.d.ts +32 -0
- package/types/lib/einvoice/check.d.cts +181 -0
- package/types/lib/einvoice/check.d.ts +181 -0
- package/types/lib/einvoice/cii.d.cts +18 -0
- package/types/lib/einvoice/cii.d.ts +18 -0
- package/types/lib/einvoice/codes.generated.d.cts +14 -0
- package/types/lib/einvoice/codes.generated.d.ts +14 -0
- package/types/lib/einvoice/decimal.d.cts +29 -0
- package/types/lib/einvoice/decimal.d.ts +29 -0
- package/types/lib/einvoice/display.d.cts +43 -0
- package/types/lib/einvoice/display.d.ts +43 -0
- package/types/lib/einvoice/html-text.d.cts +17 -0
- package/types/lib/einvoice/html-text.d.ts +17 -0
- package/types/lib/einvoice/index.d.cts +45 -0
- package/types/lib/einvoice/index.d.ts +45 -0
- package/types/lib/einvoice/locate.d.cts +21 -0
- package/types/lib/einvoice/locate.d.ts +21 -0
- package/types/lib/einvoice/report.d.cts +59 -0
- package/types/lib/einvoice/report.d.ts +59 -0
- package/types/lib/einvoice/schema.d.cts +293 -0
- package/types/lib/einvoice/schema.d.ts +293 -0
- package/types/lib/einvoice/skeleton.d.cts +10 -0
- package/types/lib/einvoice/skeleton.d.ts +10 -0
- package/types/lib/generated/frames.d.cts +6 -0
- package/types/lib/generated/frames.d.ts +6 -0
- package/types/lib/preview.d.cts +22 -2
- package/types/lib/preview.d.ts +22 -2
- package/types/lib/source-edit.d.cts +117 -0
- package/types/lib/source-edit.d.ts +117 -0
- package/types/lib/source-positions.d.cts +12 -3
- package/types/lib/source-positions.d.ts +12 -3
- package/types/lib/source-scan.d.cts +61 -0
- package/types/lib/source-scan.d.ts +61 -0
- package/types/lib/translation.d.cts +17 -0
- package/types/lib/translation.d.ts +17 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Bundled from src/frame/text-edit.entry.ts. */
|
|
2
|
+
export declare const textEditRuntime = "\"use strict\";(()=>{var O=`\nhtml.ff-edit-mode [data-ff-edit] { cursor: text; }\nhtml.ff-edit-mode [data-ff-edit]:hover { outline: 1px dashed rgba(37,99,235,.85); outline-offset: 2px; }\nhtml.ff-edit-mode [data-ff-edit=\"t\"]:hover { outline-color: rgba(147,51,234,.9); }\n.ff-editing { outline: 2px solid #2563eb !important; outline-offset: 2px; cursor: text; }\n.ff-editing .ff-chip { background: rgba(37,99,235,.14) !important; box-shadow: inset 0 0 0 1px rgba(37,99,235,.45) !important; border-radius: 3px !important; padding: 0 1px !important; cursor: default; }\n.ff-edit-badge { position: absolute; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif !important; color: #fff !important; background: #2563eb !important; padding: 1px 6px !important; border-radius: 4px !important; pointer-events: none; white-space: nowrap; }\n`;function F(l,d={}){let m=d.clicks!==!1,g=d.live===!0,o=l.document,i=null,s=null,f=e=>{try{l.parent.postMessage(e,\"*\")}catch{}},v=m?o.querySelector('meta[name=\"formfeed:document\"]')?.getAttribute(\"content\")??null:null,h=!1;l.addEventListener(\"blur\",()=>{h=!0}),l.addEventListener(\"focus\",()=>{h=!1});let y=o.createElement(\"style\");y.setAttribute(\"data-formfeed\",\"edit\"),y.setAttribute(\"data-pagedjs-ignore\",\"\"),y.textContent=O,(o.head??o.documentElement).appendChild(y),m&&o.documentElement.classList.add(\"ff-edit-mode\");let M=e=>(e&&typeof e.closest==\"function\"?e:null)?.closest(\"[data-ff-edit]\")??null;o.addEventListener(\"click\",e=>{if(!m)return;if(i&&!i.done&&i.element.contains(e.target)){e.stopImmediatePropagation();return}let t=M(e.target);t&&(e.preventDefault(),e.stopImmediatePropagation(),C(t,{x:e.clientX,y:e.clientY}))},!0);function C(e,t){i&&!i.done&&x();let n=e.getAttribute(\"data-ff-src\")??\"\",r=e.getBoundingClientRect(),u=Array.from(o.querySelectorAll(`[data-ff-src=\"${n.replace(/\"/g,\"\")}\"]`));s={src:n,element:e,point:t},f({type:\"formfeed:edit-request\",src:n,doc:v,edit:e.getAttribute(\"data-ff-edit\"),text:e.textContent??\"\",elements:e.childElementCount,count:u.length,index:Math.max(0,u.indexOf(e)),split:e.hasAttribute(\"data-split-from\")||e.hasAttribute(\"data-split-to\"),rect:{left:r.left,top:r.top,width:r.width,height:r.height}})}o.addEventListener(\"keydown\",e=>{if(!m||i&&!i.done||!(e.ctrlKey||e.metaKey)||e.altKey)return;let t=e.key.toLowerCase();(t===\"z\"||t===\"y\")&&(e.preventDefault(),f({type:t===\"y\"||e.shiftKey?\"formfeed:redo\":\"formfeed:undo\"}))}),l.addEventListener(\"message\",e=>{if(e.source!==l.parent)return;let t=e.data;!t||typeof t.type!=\"string\"||(t.type===\"formfeed:edit-begin\"?P(t):t.type===\"formfeed:edit-refuse\"||t.type===\"formfeed:edit-end\"?(s=null,i&&!i.done&&E(!1)):t.type===\"formfeed:edit-open\"&&B(t))});function B(e){if(!m||typeof e.src!=\"string\"||i&&!i.done)return;let t=Array.from(o.querySelectorAll(`[data-ff-src=\"${e.src.replace(/\"/g,\"\")}\"][data-ff-edit]`)),n=Number.isInteger(e.index)?Number(e.index):0,r=t[n]??t[0];r&&C(r,null)}if(m){let e=()=>f({type:\"formfeed:edit-ready\",doc:v}),t=l;t.PagedConfig?t.formfeedEditReady=e:o.readyState===\"loading\"?o.addEventListener(\"DOMContentLoaded\",e):e()}function P(e){i&&!i.done&&E(!1);let t=e.layer?o.querySelector(`[data-ff-layer=\"${String(e.layer).replace(/\"/g,\"\")}\"] > .ff-text`):s&&s.src===e.src?s.element:o.querySelector(`[data-ff-src=\"${String(e.src).replace(/\"/g,\"\")}\"]`),n=e.at,r=e.layer?n&&Number.isFinite(n.x)&&Number.isFinite(n.y)?{x:Number(n.x),y:Number(n.y)}:null:s&&s.src===e.src?s.point:null;s=null;let u=h&&!o.hasFocus();if(!t||!Array.isArray(e.items)||u){f({type:\"formfeed:edit-cancel\",token:String(e.token)});return}let c=Array.from(t.childNodes),b=o.createDocumentFragment();for(let a of e.items)if(a.kind===\"text\")b.appendChild(o.createTextNode(String(a.text)));else if(a.kind===\"break\")b.appendChild(o.createElement(\"br\"));else if(a.kind===\"chip\"){let p=o.createElement(\"span\");p.className=\"ff-chip\",p.setAttribute(\"data-ff-chip\",String(a.index)),p.setAttribute(\"contenteditable\",\"false\"),a.title&&(p.title=String(a.title)),p.textContent=String(a.text),b.appendChild(p)}for(let a of c)t.removeChild(a);t.appendChild(b),t.contentEditable=\"true\",t.classList.add(\"ff-editing\"),t.setAttribute(\"role\",\"textbox\"),e.label&&t.setAttribute(\"aria-label\",String(e.label)),t.spellcheck=!0,i={token:String(e.token),element:t,saved:c,allowBreaks:e.allowBreaks===!0,badge:e.note?H(t,String(e.note)):null,done:!1},t.addEventListener(\"keydown\",A),t.addEventListener(\"beforeinput\",T),t.addEventListener(\"paste\",S),t.addEventListener(\"drop\",N),t.addEventListener(\"focusout\",R),g&&t.addEventListener(\"input\",k),t.focus(),e.select===\"all\"?I(t):K(t,r),f({type:\"formfeed:edit-started\",token:i.token}),typeof e.insert==\"string\"&&e.insert&&L(e.insert.replace(/\\r\\n?|\\n/g,\" \"))}function L(e){if(typeof o.execCommand==\"function\"&&o.execCommand(\"insertText\",!1,e))return;let t=l.getSelection(),n=t&&t.rangeCount?t.getRangeAt(0):null;n&&(n.deleteContents(),n.insertNode(o.createTextNode(e)),n.collapse(!1),g&&k())}function k(){i&&!i.done&&f({type:\"formfeed:edit-input\",token:i.token,items:D(i.element)})}function H(e,t){let n=o.createElement(\"div\");n.className=\"ff-edit-badge\",n.textContent=t;let r=e.getBoundingClientRect();return n.style.left=`${r.left+l.scrollX}px`,n.style.top=`${Math.max(0,r.top+l.scrollY-22)}px`,o.body.appendChild(n),n}function I(e){let t=l.getSelection();if(!t)return;let n=o.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}function K(e,t){let n=l.getSelection();if(!n)return;let r=null,u=o;if(t){if(u.caretRangeFromPoint)r=u.caretRangeFromPoint(t.x,t.y);else if(u.caretPositionFromPoint){let c=u.caretPositionFromPoint(t.x,t.y);c&&(r=o.createRange(),r.setStart(c.offsetNode,c.offset))}}if(!r||!e.contains(r.startContainer))r=o.createRange(),r.selectNodeContents(e),r.collapse(!1);else if(t){let c=r.startContainer,a=(c.nodeType===1?c:c.parentElement)?.closest(\"[data-ff-chip]\")??null;if(a&&a!==e&&e.contains(a)){let p=a.getBoundingClientRect();r=o.createRange(),t.x<p.left+p.width/2?r.setStartBefore(a):r.setStartAfter(a),r.collapse(!0)}}n.removeAllRanges(),n.addRange(r)}function A(e){let t=e.key;t===\"Escape\"?(e.preventDefault(),E(!0)):t===\"Enter\"&&!e.shiftKey?(e.preventDefault(),x()):t===\"Enter\"?(e.preventDefault(),i?.allowBreaks&&q()):t===\"Tab\"?(e.preventDefault(),x()):(e.ctrlKey||e.metaKey)&&[\"b\",\"i\",\"u\"].includes(t.toLowerCase())&&(e.preventDefault(),g&&i&&!e.altKey&&f({type:\"formfeed:edit-style\",token:i.token,key:t.toLowerCase()}))}function T(e){let t=e.inputType??\"\";(t.startsWith(\"format\")||t===\"insertFromDrop\"||t===\"insertParagraph\"||t===\"insertLineBreak\")&&e.preventDefault()}function S(e){e.preventDefault(),L((e.clipboardData?.getData(\"text/plain\")??\"\").replace(/\\r\\n?|\\n/g,\" \"))}function N(e){e.preventDefault()}function R(){l.setTimeout(()=>{i&&!i.done&&(!o.hasFocus()||!i.element.contains(o.activeElement))&&x()},0)}function q(){let e=l.getSelection();if(!e||!e.rangeCount)return;let t=e.getRangeAt(0);t.deleteContents();let n=o.createElement(\"br\");t.insertNode(n),n.nextSibling||n.parentNode?.appendChild(o.createElement(\"br\"));let r=o.createRange();r.setStartAfter(n),r.collapse(!0),e.removeAllRanges(),e.addRange(r)}function w(e){e.done=!0;let t=e.element;t.removeEventListener(\"keydown\",A),t.removeEventListener(\"beforeinput\",T),t.removeEventListener(\"paste\",S),t.removeEventListener(\"drop\",N),t.removeEventListener(\"focusout\",R),t.removeEventListener(\"input\",k),t.removeAttribute(\"contenteditable\"),t.removeAttribute(\"role\"),t.removeAttribute(\"aria-label\"),t.classList.remove(\"ff-editing\"),e.badge?.remove(),i===e&&(i=null)}function x(){let e=i;if(!e||e.done)return;let t=D(e.element);w(e),f({type:\"formfeed:edit-commit\",token:e.token,items:t})}function E(e){let t=i;if(!t||t.done)return;let n=t.element;for(;n.firstChild;)n.removeChild(n.firstChild);for(let r of t.saved)n.appendChild(r);w(t),e&&f({type:\"formfeed:edit-cancel\",token:t.token})}}function D(l){let d=[],m=o=>{let i=d[d.length-1];i?.kind===\"text\"?i.text+=o:o&&d.push({kind:\"text\",text:o})},g=o=>{for(let i of Array.from(o.childNodes))if(i.nodeType===3)m(i.data);else if(i.nodeType===1){let s=i,f=s.getAttribute(\"data-ff-chip\");f!==null?d.push({kind:\"chip\",index:Number(f)}):s.tagName===\"BR\"?d.push({kind:\"break\"}):((s.tagName===\"DIV\"||s.tagName===\"P\")&&d.length&&d.push({kind:\"break\"}),g(s))}};for(g(l);d[d.length-1]?.kind===\"break\";)d.pop();return d}F(window);})();";
|
|
3
|
+
/** Bundled from src/frame/fit.entry.ts. */
|
|
4
|
+
export declare const fitRuntime = "\"use strict\";(()=>{function a(t,e,n){if(e===t)return t.scrollHeight<=t.clientHeight+.5&&t.scrollWidth<=t.clientWidth+.5;let o=n.getComputedStyle(t),i=t.clientHeight-(parseFloat(o.paddingTop)||0)-(parseFloat(o.paddingBottom)||0);return e.scrollHeight<=i+.5&&e.scrollWidth<=e.clientWidth+.5}function m(t,e){let n=t.firstElementChild??t;n.style.fontSize=\"\";let o=parseFloat(e.getComputedStyle(n).fontSize)||16,i=Math.min(o,parseFloat(t.getAttribute(\"data-ff-fit-min\")??\"\")||o/2);if(a(t,n,e))return o;let l=i,s=o;for(let d=0;d<14;d++){let r=(l+s)/2;n.style.fontSize=`${r}px`,a(t,n,e)?l=r:s=r}let f=Math.floor(l*100)/100;return n.style.fontSize=`${f}px`,f}function c(t){let e=()=>{for(let o of Array.from(t.document.querySelectorAll('[data-ff-fit=\"shrink\"]')))m(o,t);t.document.documentElement.setAttribute(\"data-ff-fit\",\"done\")};t.formfeedFit=e;let n=t.document.fonts;n?n.ready.then(e):t.addEventListener(\"load\",e)}c(window);})();";
|
|
5
|
+
/** Bundled from src/frame/stage.entry.ts. */
|
|
6
|
+
export declare const stageRuntime = "\"use strict\";(()=>{var W=`\nhtml.ff-edit-mode [data-ff-edit] { cursor: text; }\nhtml.ff-edit-mode [data-ff-edit]:hover { outline: 1px dashed rgba(37,99,235,.85); outline-offset: 2px; }\nhtml.ff-edit-mode [data-ff-edit=\"t\"]:hover { outline-color: rgba(147,51,234,.9); }\n.ff-editing { outline: 2px solid #2563eb !important; outline-offset: 2px; cursor: text; }\n.ff-editing .ff-chip { background: rgba(37,99,235,.14) !important; box-shadow: inset 0 0 0 1px rgba(37,99,235,.45) !important; border-radius: 3px !important; padding: 0 1px !important; cursor: default; }\n.ff-edit-badge { position: absolute; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif !important; color: #fff !important; background: #2563eb !important; padding: 1px 6px !important; border-radius: 4px !important; pointer-events: none; white-space: nowrap; }\n`;function H(a,l={}){let f=l.clicks!==!1,p=l.live===!0,n=a.document,o=null,d=null,u=e=>{try{a.parent.postMessage(e,\"*\")}catch{}},m=f?n.querySelector('meta[name=\"formfeed:document\"]')?.getAttribute(\"content\")??null:null,s=!1;a.addEventListener(\"blur\",()=>{s=!0}),a.addEventListener(\"focus\",()=>{s=!1});let g=n.createElement(\"style\");g.setAttribute(\"data-formfeed\",\"edit\"),g.setAttribute(\"data-pagedjs-ignore\",\"\"),g.textContent=W,(n.head??n.documentElement).appendChild(g),f&&n.documentElement.classList.add(\"ff-edit-mode\");let x=e=>(e&&typeof e.closest==\"function\"?e:null)?.closest(\"[data-ff-edit]\")??null;n.addEventListener(\"click\",e=>{if(!f)return;if(o&&!o.done&&o.element.contains(e.target)){e.stopImmediatePropagation();return}let t=x(e.target);t&&(e.preventDefault(),e.stopImmediatePropagation(),v(t,{x:e.clientX,y:e.clientY}))},!0);function v(e,t){o&&!o.done&&L();let r=e.getAttribute(\"data-ff-src\")??\"\",i=e.getBoundingClientRect(),b=Array.from(n.querySelectorAll(`[data-ff-src=\"${r.replace(/\"/g,\"\")}\"]`));d={src:r,element:e,point:t},u({type:\"formfeed:edit-request\",src:r,doc:m,edit:e.getAttribute(\"data-ff-edit\"),text:e.textContent??\"\",elements:e.childElementCount,count:b.length,index:Math.max(0,b.indexOf(e)),split:e.hasAttribute(\"data-split-from\")||e.hasAttribute(\"data-split-to\"),rect:{left:i.left,top:i.top,width:i.width,height:i.height}})}n.addEventListener(\"keydown\",e=>{if(!f||o&&!o.done||!(e.ctrlKey||e.metaKey)||e.altKey)return;let t=e.key.toLowerCase();(t===\"z\"||t===\"y\")&&(e.preventDefault(),u({type:t===\"y\"||e.shiftKey?\"formfeed:redo\":\"formfeed:undo\"}))}),a.addEventListener(\"message\",e=>{if(e.source!==a.parent)return;let t=e.data;!t||typeof t.type!=\"string\"||(t.type===\"formfeed:edit-begin\"?B(t):t.type===\"formfeed:edit-refuse\"||t.type===\"formfeed:edit-end\"?(d=null,o&&!o.done&&S(!1)):t.type===\"formfeed:edit-open\"&&E(t))});function E(e){if(!f||typeof e.src!=\"string\"||o&&!o.done)return;let t=Array.from(n.querySelectorAll(`[data-ff-src=\"${e.src.replace(/\"/g,\"\")}\"][data-ff-edit]`)),r=Number.isInteger(e.index)?Number(e.index):0,i=t[r]??t[0];i&&v(i,null)}if(f){let e=()=>u({type:\"formfeed:edit-ready\",doc:m}),t=a;t.PagedConfig?t.formfeedEditReady=e:n.readyState===\"loading\"?n.addEventListener(\"DOMContentLoaded\",e):e()}function B(e){o&&!o.done&&S(!1);let t=e.layer?n.querySelector(`[data-ff-layer=\"${String(e.layer).replace(/\"/g,\"\")}\"] > .ff-text`):d&&d.src===e.src?d.element:n.querySelector(`[data-ff-src=\"${String(e.src).replace(/\"/g,\"\")}\"]`),r=e.at,i=e.layer?r&&Number.isFinite(r.x)&&Number.isFinite(r.y)?{x:Number(r.x),y:Number(r.y)}:null:d&&d.src===e.src?d.point:null;d=null;let b=s&&!n.hasFocus();if(!t||!Array.isArray(e.items)||b){u({type:\"formfeed:edit-cancel\",token:String(e.token)});return}let y=Array.from(t.childNodes),k=n.createDocumentFragment();for(let c of e.items)if(c.kind===\"text\")k.appendChild(n.createTextNode(String(c.text)));else if(c.kind===\"break\")k.appendChild(n.createElement(\"br\"));else if(c.kind===\"chip\"){let h=n.createElement(\"span\");h.className=\"ff-chip\",h.setAttribute(\"data-ff-chip\",String(c.index)),h.setAttribute(\"contenteditable\",\"false\"),c.title&&(h.title=String(c.title)),h.textContent=String(c.text),k.appendChild(h)}for(let c of y)t.removeChild(c);t.appendChild(k),t.contentEditable=\"true\",t.classList.add(\"ff-editing\"),t.setAttribute(\"role\",\"textbox\"),e.label&&t.setAttribute(\"aria-label\",String(e.label)),t.spellcheck=!0,o={token:String(e.token),element:t,saved:y,allowBreaks:e.allowBreaks===!0,badge:e.note?I(t,String(e.note)):null,done:!1},t.addEventListener(\"keydown\",T),t.addEventListener(\"beforeinput\",N),t.addEventListener(\"paste\",w),t.addEventListener(\"drop\",R),t.addEventListener(\"focusout\",F),p&&t.addEventListener(\"input\",C),t.focus(),e.select===\"all\"?q(t):K(t,i),u({type:\"formfeed:edit-started\",token:o.token}),typeof e.insert==\"string\"&&e.insert&&A(e.insert.replace(/\\r\\n?|\\n/g,\" \"))}function A(e){if(typeof n.execCommand==\"function\"&&n.execCommand(\"insertText\",!1,e))return;let t=a.getSelection(),r=t&&t.rangeCount?t.getRangeAt(0):null;r&&(r.deleteContents(),r.insertNode(n.createTextNode(e)),r.collapse(!1),p&&C())}function C(){o&&!o.done&&u({type:\"formfeed:edit-input\",token:o.token,items:D(o.element)})}function I(e,t){let r=n.createElement(\"div\");r.className=\"ff-edit-badge\",r.textContent=t;let i=e.getBoundingClientRect();return r.style.left=`${i.left+a.scrollX}px`,r.style.top=`${Math.max(0,i.top+a.scrollY-22)}px`,n.body.appendChild(r),r}function q(e){let t=a.getSelection();if(!t)return;let r=n.createRange();r.selectNodeContents(e),t.removeAllRanges(),t.addRange(r)}function K(e,t){let r=a.getSelection();if(!r)return;let i=null,b=n;if(t){if(b.caretRangeFromPoint)i=b.caretRangeFromPoint(t.x,t.y);else if(b.caretPositionFromPoint){let y=b.caretPositionFromPoint(t.x,t.y);y&&(i=n.createRange(),i.setStart(y.offsetNode,y.offset))}}if(!i||!e.contains(i.startContainer))i=n.createRange(),i.selectNodeContents(e),i.collapse(!1);else if(t){let y=i.startContainer,c=(y.nodeType===1?y:y.parentElement)?.closest(\"[data-ff-chip]\")??null;if(c&&c!==e&&e.contains(c)){let h=c.getBoundingClientRect();i=n.createRange(),t.x<h.left+h.width/2?i.setStartBefore(c):i.setStartAfter(c),i.collapse(!0)}}r.removeAllRanges(),r.addRange(i)}function T(e){let t=e.key;t===\"Escape\"?(e.preventDefault(),S(!0)):t===\"Enter\"&&!e.shiftKey?(e.preventDefault(),L()):t===\"Enter\"?(e.preventDefault(),o?.allowBreaks&&$()):t===\"Tab\"?(e.preventDefault(),L()):(e.ctrlKey||e.metaKey)&&[\"b\",\"i\",\"u\"].includes(t.toLowerCase())&&(e.preventDefault(),p&&o&&!e.altKey&&u({type:\"formfeed:edit-style\",token:o.token,key:t.toLowerCase()}))}function N(e){let t=e.inputType??\"\";(t.startsWith(\"format\")||t===\"insertFromDrop\"||t===\"insertParagraph\"||t===\"insertLineBreak\")&&e.preventDefault()}function w(e){e.preventDefault(),A((e.clipboardData?.getData(\"text/plain\")??\"\").replace(/\\r\\n?|\\n/g,\" \"))}function R(e){e.preventDefault()}function F(){a.setTimeout(()=>{o&&!o.done&&(!n.hasFocus()||!o.element.contains(n.activeElement))&&L()},0)}function $(){let e=a.getSelection();if(!e||!e.rangeCount)return;let t=e.getRangeAt(0);t.deleteContents();let r=n.createElement(\"br\");t.insertNode(r),r.nextSibling||r.parentNode?.appendChild(n.createElement(\"br\"));let i=n.createRange();i.setStartAfter(r),i.collapse(!0),e.removeAllRanges(),e.addRange(i)}function M(e){e.done=!0;let t=e.element;t.removeEventListener(\"keydown\",T),t.removeEventListener(\"beforeinput\",N),t.removeEventListener(\"paste\",w),t.removeEventListener(\"drop\",R),t.removeEventListener(\"focusout\",F),t.removeEventListener(\"input\",C),t.removeAttribute(\"contenteditable\"),t.removeAttribute(\"role\"),t.removeAttribute(\"aria-label\"),t.classList.remove(\"ff-editing\"),e.badge?.remove(),o===e&&(o=null)}function L(){let e=o;if(!e||e.done)return;let t=D(e.element);M(e),u({type:\"formfeed:edit-commit\",token:e.token,items:t})}function S(e){let t=o;if(!t||t.done)return;let r=t.element;for(;r.firstChild;)r.removeChild(r.firstChild);for(let i of t.saved)r.appendChild(i);M(t),e&&u({type:\"formfeed:edit-cancel\",token:t.token})}}function D(a){let l=[],f=n=>{let o=l[l.length-1];o?.kind===\"text\"?o.text+=n:n&&l.push({kind:\"text\",text:n})},p=n=>{for(let o of Array.from(n.childNodes))if(o.nodeType===3)f(o.data);else if(o.nodeType===1){let d=o,u=d.getAttribute(\"data-ff-chip\");u!==null?l.push({kind:\"chip\",index:Number(u)}):d.tagName===\"BR\"?l.push({kind:\"break\"}):((d.tagName===\"DIV\"||d.tagName===\"P\")&&l.length&&l.push({kind:\"break\"}),p(d))}};for(p(a);l[l.length-1]?.kind===\"break\";)l.pop();return l}function O(a,l){return Array.from(a.querySelectorAll(\"[data-ff-layer]\")).map(f=>{let p=f.querySelector(\":scope > .ff-text\"),n=!1;if(p&&f.style.height!==\"auto\"){let o=l.getComputedStyle(f),d=f.clientHeight-(parseFloat(o.paddingTop)||0)-(parseFloat(o.paddingBottom)||0);n=o.overflow===\"hidden\"&&(p.scrollHeight>d+1||p.scrollWidth>p.clientWidth+1)}return{id:f.getAttribute(\"data-ff-layer\")??\"\",width:f.offsetWidth,height:f.offsetHeight,overflow:n}})}function P(a){let l=a.document,f=m=>{try{a.parent.postMessage(m,\"*\")}catch{}},p=m=>typeof m==\"string\"?l.querySelector(`[data-ff-layer=\"${m.replace(/\"/g,\"\")}\"]`):null,n=()=>{for(let m of Array.from(l.querySelectorAll(\"[data-ff-layer]\")))for(let s of[\"left\",\"top\",\"width\",\"height\",\"transform\"])m.style.removeProperty(s)},o=()=>{a.formfeedFit?.(),f({type:\"formfeed:ready\",layers:O(l,a)})};a.addEventListener(\"message\",m=>{if(m.source!==a.parent)return;let s=m.data;if(!(!s||typeof s.type!=\"string\")){if(s.type===\"formfeed:layer-style\"){let g=p(s.id);if(!g)return;let x=(v,E)=>{typeof E==\"number\"&&Number.isFinite(E)&&g.style.setProperty(v,`${E}px`)};x(\"left\",s.left),x(\"top\",s.top),x(\"width\",s.width),x(\"height\",s.height),typeof s.rotation==\"number\"&&Number.isFinite(s.rotation)&&g.style.setProperty(\"transform\",s.rotation?`rotate(${s.rotation}deg)`:\"none\")}else if(s.type===\"formfeed:layer-style-clear\")n();else if(s.type===\"formfeed:css\"&&typeof s.css==\"string\"){let g=l.querySelector('style[data-formfeed=\"template\"]');g&&(g.textContent=s.css),n(),o()}}}),H(a,{clicks:!1,live:!0});let d=l.fonts,u=()=>d?void d.ready.then(o):o();l.readyState===\"complete\"?u():a.addEventListener(\"load\",u)}P(window);})();";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Bundled from src/frame/text-edit.entry.ts. */
|
|
2
|
+
export declare const textEditRuntime = "\"use strict\";(()=>{var O=`\nhtml.ff-edit-mode [data-ff-edit] { cursor: text; }\nhtml.ff-edit-mode [data-ff-edit]:hover { outline: 1px dashed rgba(37,99,235,.85); outline-offset: 2px; }\nhtml.ff-edit-mode [data-ff-edit=\"t\"]:hover { outline-color: rgba(147,51,234,.9); }\n.ff-editing { outline: 2px solid #2563eb !important; outline-offset: 2px; cursor: text; }\n.ff-editing .ff-chip { background: rgba(37,99,235,.14) !important; box-shadow: inset 0 0 0 1px rgba(37,99,235,.45) !important; border-radius: 3px !important; padding: 0 1px !important; cursor: default; }\n.ff-edit-badge { position: absolute; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif !important; color: #fff !important; background: #2563eb !important; padding: 1px 6px !important; border-radius: 4px !important; pointer-events: none; white-space: nowrap; }\n`;function F(l,d={}){let m=d.clicks!==!1,g=d.live===!0,o=l.document,i=null,s=null,f=e=>{try{l.parent.postMessage(e,\"*\")}catch{}},v=m?o.querySelector('meta[name=\"formfeed:document\"]')?.getAttribute(\"content\")??null:null,h=!1;l.addEventListener(\"blur\",()=>{h=!0}),l.addEventListener(\"focus\",()=>{h=!1});let y=o.createElement(\"style\");y.setAttribute(\"data-formfeed\",\"edit\"),y.setAttribute(\"data-pagedjs-ignore\",\"\"),y.textContent=O,(o.head??o.documentElement).appendChild(y),m&&o.documentElement.classList.add(\"ff-edit-mode\");let M=e=>(e&&typeof e.closest==\"function\"?e:null)?.closest(\"[data-ff-edit]\")??null;o.addEventListener(\"click\",e=>{if(!m)return;if(i&&!i.done&&i.element.contains(e.target)){e.stopImmediatePropagation();return}let t=M(e.target);t&&(e.preventDefault(),e.stopImmediatePropagation(),C(t,{x:e.clientX,y:e.clientY}))},!0);function C(e,t){i&&!i.done&&x();let n=e.getAttribute(\"data-ff-src\")??\"\",r=e.getBoundingClientRect(),u=Array.from(o.querySelectorAll(`[data-ff-src=\"${n.replace(/\"/g,\"\")}\"]`));s={src:n,element:e,point:t},f({type:\"formfeed:edit-request\",src:n,doc:v,edit:e.getAttribute(\"data-ff-edit\"),text:e.textContent??\"\",elements:e.childElementCount,count:u.length,index:Math.max(0,u.indexOf(e)),split:e.hasAttribute(\"data-split-from\")||e.hasAttribute(\"data-split-to\"),rect:{left:r.left,top:r.top,width:r.width,height:r.height}})}o.addEventListener(\"keydown\",e=>{if(!m||i&&!i.done||!(e.ctrlKey||e.metaKey)||e.altKey)return;let t=e.key.toLowerCase();(t===\"z\"||t===\"y\")&&(e.preventDefault(),f({type:t===\"y\"||e.shiftKey?\"formfeed:redo\":\"formfeed:undo\"}))}),l.addEventListener(\"message\",e=>{if(e.source!==l.parent)return;let t=e.data;!t||typeof t.type!=\"string\"||(t.type===\"formfeed:edit-begin\"?P(t):t.type===\"formfeed:edit-refuse\"||t.type===\"formfeed:edit-end\"?(s=null,i&&!i.done&&E(!1)):t.type===\"formfeed:edit-open\"&&B(t))});function B(e){if(!m||typeof e.src!=\"string\"||i&&!i.done)return;let t=Array.from(o.querySelectorAll(`[data-ff-src=\"${e.src.replace(/\"/g,\"\")}\"][data-ff-edit]`)),n=Number.isInteger(e.index)?Number(e.index):0,r=t[n]??t[0];r&&C(r,null)}if(m){let e=()=>f({type:\"formfeed:edit-ready\",doc:v}),t=l;t.PagedConfig?t.formfeedEditReady=e:o.readyState===\"loading\"?o.addEventListener(\"DOMContentLoaded\",e):e()}function P(e){i&&!i.done&&E(!1);let t=e.layer?o.querySelector(`[data-ff-layer=\"${String(e.layer).replace(/\"/g,\"\")}\"] > .ff-text`):s&&s.src===e.src?s.element:o.querySelector(`[data-ff-src=\"${String(e.src).replace(/\"/g,\"\")}\"]`),n=e.at,r=e.layer?n&&Number.isFinite(n.x)&&Number.isFinite(n.y)?{x:Number(n.x),y:Number(n.y)}:null:s&&s.src===e.src?s.point:null;s=null;let u=h&&!o.hasFocus();if(!t||!Array.isArray(e.items)||u){f({type:\"formfeed:edit-cancel\",token:String(e.token)});return}let c=Array.from(t.childNodes),b=o.createDocumentFragment();for(let a of e.items)if(a.kind===\"text\")b.appendChild(o.createTextNode(String(a.text)));else if(a.kind===\"break\")b.appendChild(o.createElement(\"br\"));else if(a.kind===\"chip\"){let p=o.createElement(\"span\");p.className=\"ff-chip\",p.setAttribute(\"data-ff-chip\",String(a.index)),p.setAttribute(\"contenteditable\",\"false\"),a.title&&(p.title=String(a.title)),p.textContent=String(a.text),b.appendChild(p)}for(let a of c)t.removeChild(a);t.appendChild(b),t.contentEditable=\"true\",t.classList.add(\"ff-editing\"),t.setAttribute(\"role\",\"textbox\"),e.label&&t.setAttribute(\"aria-label\",String(e.label)),t.spellcheck=!0,i={token:String(e.token),element:t,saved:c,allowBreaks:e.allowBreaks===!0,badge:e.note?H(t,String(e.note)):null,done:!1},t.addEventListener(\"keydown\",A),t.addEventListener(\"beforeinput\",T),t.addEventListener(\"paste\",S),t.addEventListener(\"drop\",N),t.addEventListener(\"focusout\",R),g&&t.addEventListener(\"input\",k),t.focus(),e.select===\"all\"?I(t):K(t,r),f({type:\"formfeed:edit-started\",token:i.token}),typeof e.insert==\"string\"&&e.insert&&L(e.insert.replace(/\\r\\n?|\\n/g,\" \"))}function L(e){if(typeof o.execCommand==\"function\"&&o.execCommand(\"insertText\",!1,e))return;let t=l.getSelection(),n=t&&t.rangeCount?t.getRangeAt(0):null;n&&(n.deleteContents(),n.insertNode(o.createTextNode(e)),n.collapse(!1),g&&k())}function k(){i&&!i.done&&f({type:\"formfeed:edit-input\",token:i.token,items:D(i.element)})}function H(e,t){let n=o.createElement(\"div\");n.className=\"ff-edit-badge\",n.textContent=t;let r=e.getBoundingClientRect();return n.style.left=`${r.left+l.scrollX}px`,n.style.top=`${Math.max(0,r.top+l.scrollY-22)}px`,o.body.appendChild(n),n}function I(e){let t=l.getSelection();if(!t)return;let n=o.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}function K(e,t){let n=l.getSelection();if(!n)return;let r=null,u=o;if(t){if(u.caretRangeFromPoint)r=u.caretRangeFromPoint(t.x,t.y);else if(u.caretPositionFromPoint){let c=u.caretPositionFromPoint(t.x,t.y);c&&(r=o.createRange(),r.setStart(c.offsetNode,c.offset))}}if(!r||!e.contains(r.startContainer))r=o.createRange(),r.selectNodeContents(e),r.collapse(!1);else if(t){let c=r.startContainer,a=(c.nodeType===1?c:c.parentElement)?.closest(\"[data-ff-chip]\")??null;if(a&&a!==e&&e.contains(a)){let p=a.getBoundingClientRect();r=o.createRange(),t.x<p.left+p.width/2?r.setStartBefore(a):r.setStartAfter(a),r.collapse(!0)}}n.removeAllRanges(),n.addRange(r)}function A(e){let t=e.key;t===\"Escape\"?(e.preventDefault(),E(!0)):t===\"Enter\"&&!e.shiftKey?(e.preventDefault(),x()):t===\"Enter\"?(e.preventDefault(),i?.allowBreaks&&q()):t===\"Tab\"?(e.preventDefault(),x()):(e.ctrlKey||e.metaKey)&&[\"b\",\"i\",\"u\"].includes(t.toLowerCase())&&(e.preventDefault(),g&&i&&!e.altKey&&f({type:\"formfeed:edit-style\",token:i.token,key:t.toLowerCase()}))}function T(e){let t=e.inputType??\"\";(t.startsWith(\"format\")||t===\"insertFromDrop\"||t===\"insertParagraph\"||t===\"insertLineBreak\")&&e.preventDefault()}function S(e){e.preventDefault(),L((e.clipboardData?.getData(\"text/plain\")??\"\").replace(/\\r\\n?|\\n/g,\" \"))}function N(e){e.preventDefault()}function R(){l.setTimeout(()=>{i&&!i.done&&(!o.hasFocus()||!i.element.contains(o.activeElement))&&x()},0)}function q(){let e=l.getSelection();if(!e||!e.rangeCount)return;let t=e.getRangeAt(0);t.deleteContents();let n=o.createElement(\"br\");t.insertNode(n),n.nextSibling||n.parentNode?.appendChild(o.createElement(\"br\"));let r=o.createRange();r.setStartAfter(n),r.collapse(!0),e.removeAllRanges(),e.addRange(r)}function w(e){e.done=!0;let t=e.element;t.removeEventListener(\"keydown\",A),t.removeEventListener(\"beforeinput\",T),t.removeEventListener(\"paste\",S),t.removeEventListener(\"drop\",N),t.removeEventListener(\"focusout\",R),t.removeEventListener(\"input\",k),t.removeAttribute(\"contenteditable\"),t.removeAttribute(\"role\"),t.removeAttribute(\"aria-label\"),t.classList.remove(\"ff-editing\"),e.badge?.remove(),i===e&&(i=null)}function x(){let e=i;if(!e||e.done)return;let t=D(e.element);w(e),f({type:\"formfeed:edit-commit\",token:e.token,items:t})}function E(e){let t=i;if(!t||t.done)return;let n=t.element;for(;n.firstChild;)n.removeChild(n.firstChild);for(let r of t.saved)n.appendChild(r);w(t),e&&f({type:\"formfeed:edit-cancel\",token:t.token})}}function D(l){let d=[],m=o=>{let i=d[d.length-1];i?.kind===\"text\"?i.text+=o:o&&d.push({kind:\"text\",text:o})},g=o=>{for(let i of Array.from(o.childNodes))if(i.nodeType===3)m(i.data);else if(i.nodeType===1){let s=i,f=s.getAttribute(\"data-ff-chip\");f!==null?d.push({kind:\"chip\",index:Number(f)}):s.tagName===\"BR\"?d.push({kind:\"break\"}):((s.tagName===\"DIV\"||s.tagName===\"P\")&&d.length&&d.push({kind:\"break\"}),g(s))}};for(g(l);d[d.length-1]?.kind===\"break\";)d.pop();return d}F(window);})();";
|
|
3
|
+
/** Bundled from src/frame/fit.entry.ts. */
|
|
4
|
+
export declare const fitRuntime = "\"use strict\";(()=>{function a(t,e,n){if(e===t)return t.scrollHeight<=t.clientHeight+.5&&t.scrollWidth<=t.clientWidth+.5;let o=n.getComputedStyle(t),i=t.clientHeight-(parseFloat(o.paddingTop)||0)-(parseFloat(o.paddingBottom)||0);return e.scrollHeight<=i+.5&&e.scrollWidth<=e.clientWidth+.5}function m(t,e){let n=t.firstElementChild??t;n.style.fontSize=\"\";let o=parseFloat(e.getComputedStyle(n).fontSize)||16,i=Math.min(o,parseFloat(t.getAttribute(\"data-ff-fit-min\")??\"\")||o/2);if(a(t,n,e))return o;let l=i,s=o;for(let d=0;d<14;d++){let r=(l+s)/2;n.style.fontSize=`${r}px`,a(t,n,e)?l=r:s=r}let f=Math.floor(l*100)/100;return n.style.fontSize=`${f}px`,f}function c(t){let e=()=>{for(let o of Array.from(t.document.querySelectorAll('[data-ff-fit=\"shrink\"]')))m(o,t);t.document.documentElement.setAttribute(\"data-ff-fit\",\"done\")};t.formfeedFit=e;let n=t.document.fonts;n?n.ready.then(e):t.addEventListener(\"load\",e)}c(window);})();";
|
|
5
|
+
/** Bundled from src/frame/stage.entry.ts. */
|
|
6
|
+
export declare const stageRuntime = "\"use strict\";(()=>{var W=`\nhtml.ff-edit-mode [data-ff-edit] { cursor: text; }\nhtml.ff-edit-mode [data-ff-edit]:hover { outline: 1px dashed rgba(37,99,235,.85); outline-offset: 2px; }\nhtml.ff-edit-mode [data-ff-edit=\"t\"]:hover { outline-color: rgba(147,51,234,.9); }\n.ff-editing { outline: 2px solid #2563eb !important; outline-offset: 2px; cursor: text; }\n.ff-editing .ff-chip { background: rgba(37,99,235,.14) !important; box-shadow: inset 0 0 0 1px rgba(37,99,235,.45) !important; border-radius: 3px !important; padding: 0 1px !important; cursor: default; }\n.ff-edit-badge { position: absolute; z-index: 2147483647; font: 500 11px/1.4 system-ui, sans-serif !important; color: #fff !important; background: #2563eb !important; padding: 1px 6px !important; border-radius: 4px !important; pointer-events: none; white-space: nowrap; }\n`;function H(a,l={}){let f=l.clicks!==!1,p=l.live===!0,n=a.document,o=null,d=null,u=e=>{try{a.parent.postMessage(e,\"*\")}catch{}},m=f?n.querySelector('meta[name=\"formfeed:document\"]')?.getAttribute(\"content\")??null:null,s=!1;a.addEventListener(\"blur\",()=>{s=!0}),a.addEventListener(\"focus\",()=>{s=!1});let g=n.createElement(\"style\");g.setAttribute(\"data-formfeed\",\"edit\"),g.setAttribute(\"data-pagedjs-ignore\",\"\"),g.textContent=W,(n.head??n.documentElement).appendChild(g),f&&n.documentElement.classList.add(\"ff-edit-mode\");let x=e=>(e&&typeof e.closest==\"function\"?e:null)?.closest(\"[data-ff-edit]\")??null;n.addEventListener(\"click\",e=>{if(!f)return;if(o&&!o.done&&o.element.contains(e.target)){e.stopImmediatePropagation();return}let t=x(e.target);t&&(e.preventDefault(),e.stopImmediatePropagation(),v(t,{x:e.clientX,y:e.clientY}))},!0);function v(e,t){o&&!o.done&&L();let r=e.getAttribute(\"data-ff-src\")??\"\",i=e.getBoundingClientRect(),b=Array.from(n.querySelectorAll(`[data-ff-src=\"${r.replace(/\"/g,\"\")}\"]`));d={src:r,element:e,point:t},u({type:\"formfeed:edit-request\",src:r,doc:m,edit:e.getAttribute(\"data-ff-edit\"),text:e.textContent??\"\",elements:e.childElementCount,count:b.length,index:Math.max(0,b.indexOf(e)),split:e.hasAttribute(\"data-split-from\")||e.hasAttribute(\"data-split-to\"),rect:{left:i.left,top:i.top,width:i.width,height:i.height}})}n.addEventListener(\"keydown\",e=>{if(!f||o&&!o.done||!(e.ctrlKey||e.metaKey)||e.altKey)return;let t=e.key.toLowerCase();(t===\"z\"||t===\"y\")&&(e.preventDefault(),u({type:t===\"y\"||e.shiftKey?\"formfeed:redo\":\"formfeed:undo\"}))}),a.addEventListener(\"message\",e=>{if(e.source!==a.parent)return;let t=e.data;!t||typeof t.type!=\"string\"||(t.type===\"formfeed:edit-begin\"?B(t):t.type===\"formfeed:edit-refuse\"||t.type===\"formfeed:edit-end\"?(d=null,o&&!o.done&&S(!1)):t.type===\"formfeed:edit-open\"&&E(t))});function E(e){if(!f||typeof e.src!=\"string\"||o&&!o.done)return;let t=Array.from(n.querySelectorAll(`[data-ff-src=\"${e.src.replace(/\"/g,\"\")}\"][data-ff-edit]`)),r=Number.isInteger(e.index)?Number(e.index):0,i=t[r]??t[0];i&&v(i,null)}if(f){let e=()=>u({type:\"formfeed:edit-ready\",doc:m}),t=a;t.PagedConfig?t.formfeedEditReady=e:n.readyState===\"loading\"?n.addEventListener(\"DOMContentLoaded\",e):e()}function B(e){o&&!o.done&&S(!1);let t=e.layer?n.querySelector(`[data-ff-layer=\"${String(e.layer).replace(/\"/g,\"\")}\"] > .ff-text`):d&&d.src===e.src?d.element:n.querySelector(`[data-ff-src=\"${String(e.src).replace(/\"/g,\"\")}\"]`),r=e.at,i=e.layer?r&&Number.isFinite(r.x)&&Number.isFinite(r.y)?{x:Number(r.x),y:Number(r.y)}:null:d&&d.src===e.src?d.point:null;d=null;let b=s&&!n.hasFocus();if(!t||!Array.isArray(e.items)||b){u({type:\"formfeed:edit-cancel\",token:String(e.token)});return}let y=Array.from(t.childNodes),k=n.createDocumentFragment();for(let c of e.items)if(c.kind===\"text\")k.appendChild(n.createTextNode(String(c.text)));else if(c.kind===\"break\")k.appendChild(n.createElement(\"br\"));else if(c.kind===\"chip\"){let h=n.createElement(\"span\");h.className=\"ff-chip\",h.setAttribute(\"data-ff-chip\",String(c.index)),h.setAttribute(\"contenteditable\",\"false\"),c.title&&(h.title=String(c.title)),h.textContent=String(c.text),k.appendChild(h)}for(let c of y)t.removeChild(c);t.appendChild(k),t.contentEditable=\"true\",t.classList.add(\"ff-editing\"),t.setAttribute(\"role\",\"textbox\"),e.label&&t.setAttribute(\"aria-label\",String(e.label)),t.spellcheck=!0,o={token:String(e.token),element:t,saved:y,allowBreaks:e.allowBreaks===!0,badge:e.note?I(t,String(e.note)):null,done:!1},t.addEventListener(\"keydown\",T),t.addEventListener(\"beforeinput\",N),t.addEventListener(\"paste\",w),t.addEventListener(\"drop\",R),t.addEventListener(\"focusout\",F),p&&t.addEventListener(\"input\",C),t.focus(),e.select===\"all\"?q(t):K(t,i),u({type:\"formfeed:edit-started\",token:o.token}),typeof e.insert==\"string\"&&e.insert&&A(e.insert.replace(/\\r\\n?|\\n/g,\" \"))}function A(e){if(typeof n.execCommand==\"function\"&&n.execCommand(\"insertText\",!1,e))return;let t=a.getSelection(),r=t&&t.rangeCount?t.getRangeAt(0):null;r&&(r.deleteContents(),r.insertNode(n.createTextNode(e)),r.collapse(!1),p&&C())}function C(){o&&!o.done&&u({type:\"formfeed:edit-input\",token:o.token,items:D(o.element)})}function I(e,t){let r=n.createElement(\"div\");r.className=\"ff-edit-badge\",r.textContent=t;let i=e.getBoundingClientRect();return r.style.left=`${i.left+a.scrollX}px`,r.style.top=`${Math.max(0,i.top+a.scrollY-22)}px`,n.body.appendChild(r),r}function q(e){let t=a.getSelection();if(!t)return;let r=n.createRange();r.selectNodeContents(e),t.removeAllRanges(),t.addRange(r)}function K(e,t){let r=a.getSelection();if(!r)return;let i=null,b=n;if(t){if(b.caretRangeFromPoint)i=b.caretRangeFromPoint(t.x,t.y);else if(b.caretPositionFromPoint){let y=b.caretPositionFromPoint(t.x,t.y);y&&(i=n.createRange(),i.setStart(y.offsetNode,y.offset))}}if(!i||!e.contains(i.startContainer))i=n.createRange(),i.selectNodeContents(e),i.collapse(!1);else if(t){let y=i.startContainer,c=(y.nodeType===1?y:y.parentElement)?.closest(\"[data-ff-chip]\")??null;if(c&&c!==e&&e.contains(c)){let h=c.getBoundingClientRect();i=n.createRange(),t.x<h.left+h.width/2?i.setStartBefore(c):i.setStartAfter(c),i.collapse(!0)}}r.removeAllRanges(),r.addRange(i)}function T(e){let t=e.key;t===\"Escape\"?(e.preventDefault(),S(!0)):t===\"Enter\"&&!e.shiftKey?(e.preventDefault(),L()):t===\"Enter\"?(e.preventDefault(),o?.allowBreaks&&$()):t===\"Tab\"?(e.preventDefault(),L()):(e.ctrlKey||e.metaKey)&&[\"b\",\"i\",\"u\"].includes(t.toLowerCase())&&(e.preventDefault(),p&&o&&!e.altKey&&u({type:\"formfeed:edit-style\",token:o.token,key:t.toLowerCase()}))}function N(e){let t=e.inputType??\"\";(t.startsWith(\"format\")||t===\"insertFromDrop\"||t===\"insertParagraph\"||t===\"insertLineBreak\")&&e.preventDefault()}function w(e){e.preventDefault(),A((e.clipboardData?.getData(\"text/plain\")??\"\").replace(/\\r\\n?|\\n/g,\" \"))}function R(e){e.preventDefault()}function F(){a.setTimeout(()=>{o&&!o.done&&(!n.hasFocus()||!o.element.contains(n.activeElement))&&L()},0)}function $(){let e=a.getSelection();if(!e||!e.rangeCount)return;let t=e.getRangeAt(0);t.deleteContents();let r=n.createElement(\"br\");t.insertNode(r),r.nextSibling||r.parentNode?.appendChild(n.createElement(\"br\"));let i=n.createRange();i.setStartAfter(r),i.collapse(!0),e.removeAllRanges(),e.addRange(i)}function M(e){e.done=!0;let t=e.element;t.removeEventListener(\"keydown\",T),t.removeEventListener(\"beforeinput\",N),t.removeEventListener(\"paste\",w),t.removeEventListener(\"drop\",R),t.removeEventListener(\"focusout\",F),t.removeEventListener(\"input\",C),t.removeAttribute(\"contenteditable\"),t.removeAttribute(\"role\"),t.removeAttribute(\"aria-label\"),t.classList.remove(\"ff-editing\"),e.badge?.remove(),o===e&&(o=null)}function L(){let e=o;if(!e||e.done)return;let t=D(e.element);M(e),u({type:\"formfeed:edit-commit\",token:e.token,items:t})}function S(e){let t=o;if(!t||t.done)return;let r=t.element;for(;r.firstChild;)r.removeChild(r.firstChild);for(let i of t.saved)r.appendChild(i);M(t),e&&u({type:\"formfeed:edit-cancel\",token:t.token})}}function D(a){let l=[],f=n=>{let o=l[l.length-1];o?.kind===\"text\"?o.text+=n:n&&l.push({kind:\"text\",text:n})},p=n=>{for(let o of Array.from(n.childNodes))if(o.nodeType===3)f(o.data);else if(o.nodeType===1){let d=o,u=d.getAttribute(\"data-ff-chip\");u!==null?l.push({kind:\"chip\",index:Number(u)}):d.tagName===\"BR\"?l.push({kind:\"break\"}):((d.tagName===\"DIV\"||d.tagName===\"P\")&&l.length&&l.push({kind:\"break\"}),p(d))}};for(p(a);l[l.length-1]?.kind===\"break\";)l.pop();return l}function O(a,l){return Array.from(a.querySelectorAll(\"[data-ff-layer]\")).map(f=>{let p=f.querySelector(\":scope > .ff-text\"),n=!1;if(p&&f.style.height!==\"auto\"){let o=l.getComputedStyle(f),d=f.clientHeight-(parseFloat(o.paddingTop)||0)-(parseFloat(o.paddingBottom)||0);n=o.overflow===\"hidden\"&&(p.scrollHeight>d+1||p.scrollWidth>p.clientWidth+1)}return{id:f.getAttribute(\"data-ff-layer\")??\"\",width:f.offsetWidth,height:f.offsetHeight,overflow:n}})}function P(a){let l=a.document,f=m=>{try{a.parent.postMessage(m,\"*\")}catch{}},p=m=>typeof m==\"string\"?l.querySelector(`[data-ff-layer=\"${m.replace(/\"/g,\"\")}\"]`):null,n=()=>{for(let m of Array.from(l.querySelectorAll(\"[data-ff-layer]\")))for(let s of[\"left\",\"top\",\"width\",\"height\",\"transform\"])m.style.removeProperty(s)},o=()=>{a.formfeedFit?.(),f({type:\"formfeed:ready\",layers:O(l,a)})};a.addEventListener(\"message\",m=>{if(m.source!==a.parent)return;let s=m.data;if(!(!s||typeof s.type!=\"string\")){if(s.type===\"formfeed:layer-style\"){let g=p(s.id);if(!g)return;let x=(v,E)=>{typeof E==\"number\"&&Number.isFinite(E)&&g.style.setProperty(v,`${E}px`)};x(\"left\",s.left),x(\"top\",s.top),x(\"width\",s.width),x(\"height\",s.height),typeof s.rotation==\"number\"&&Number.isFinite(s.rotation)&&g.style.setProperty(\"transform\",s.rotation?`rotate(${s.rotation}deg)`:\"none\")}else if(s.type===\"formfeed:layer-style-clear\")n();else if(s.type===\"formfeed:css\"&&typeof s.css==\"string\"){let g=l.querySelector('style[data-formfeed=\"template\"]');g&&(g.textContent=s.css),n(),o()}}}),H(a,{clicks:!1,live:!0});let d=l.fonts,u=()=>d?void d.ready.then(o):o();l.readyState===\"complete\"?u():a.addEventListener(\"load\",u)}P(window);})();";
|
package/types/lib/preview.d.cts
CHANGED
|
@@ -22,6 +22,20 @@ export declare function paperOf(settings: TemplateSettings): {
|
|
|
22
22
|
* the element stays so its styling applies.
|
|
23
23
|
*/
|
|
24
24
|
export declare const pageNumberSpans: (html: string, page: string, total: string) => string;
|
|
25
|
+
/** Options of the flow and paged previews. */
|
|
26
|
+
export interface PreviewOptions {
|
|
27
|
+
/**
|
|
28
|
+
* The editor's edit mode: text in elements marked `data-ff-edit` (`annotateSourcePositions` with
|
|
29
|
+
* `editable`) can be edited in place, and the frame talks to the editor about it by message.
|
|
30
|
+
*/
|
|
31
|
+
editing?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* A name the editor gives this document, which the edit session's messages carry back
|
|
34
|
+
* (`formfeed:document` in the head). The editor has the next document ready a moment before the
|
|
35
|
+
* frame takes it; with the name it can tell a click that still came from the one before.
|
|
36
|
+
*/
|
|
37
|
+
document?: string;
|
|
38
|
+
}
|
|
25
39
|
/** What the preview frame reports about content wider than the page, or `null` when nothing is. */
|
|
26
40
|
export interface PreviewOverflow {
|
|
27
41
|
/** How far the widest element reaches past the right edge of the page's content area. */
|
|
@@ -43,8 +57,14 @@ export interface PreviewOverflow {
|
|
|
43
57
|
* The office quick preview's frame uses the same script.
|
|
44
58
|
*/
|
|
45
59
|
export declare const zoomGestureScript = "<script>\n(function () {\n var say = function (message) { try { parent.postMessage(message, '*'); } catch (e) {} };\n window.addEventListener('wheel', function (event) {\n if (!event.ctrlKey && !event.metaKey) return;\n event.preventDefault();\n say({ type: 'formfeed:zoom', deltaY: event.deltaY, deltaMode: event.deltaMode });\n }, { passive: false });\n window.addEventListener('keydown', function (event) {\n if (!(event.ctrlKey || event.metaKey) || event.altKey) return;\n var step = event.key === '+' || event.key === '=' ? 'in' : event.key === '-' ? 'out' : event.key === '0' ? 'reset' : null;\n if (!step) return;\n event.preventDefault();\n say({ type: 'formfeed:zoom', step: step });\n });\n})();\n</script>";
|
|
46
|
-
export declare function flowDocument(draft: RenderedDraft): string;
|
|
47
|
-
|
|
60
|
+
export declare function flowDocument(draft: RenderedDraft, options?: PreviewOptions): string;
|
|
61
|
+
/**
|
|
62
|
+
* The design stage's document (plan 16 §4.6): the assembled image template exactly as rendered, with
|
|
63
|
+
* no preview chrome around it (the stage draws its own background), and the stage runtime, which
|
|
64
|
+
* measures layers and takes drag styles and stylesheet patches by message.
|
|
65
|
+
*/
|
|
66
|
+
export declare function canvasDocument(draft: RenderedDraft): string;
|
|
67
|
+
export interface PagedOptions extends PreviewOptions {
|
|
48
68
|
/** URL of the Paged.js polyfill the frame can load. */
|
|
49
69
|
pagedScriptUrl: string;
|
|
50
70
|
}
|
package/types/lib/preview.d.ts
CHANGED
|
@@ -22,6 +22,20 @@ export declare function paperOf(settings: TemplateSettings): {
|
|
|
22
22
|
* the element stays so its styling applies.
|
|
23
23
|
*/
|
|
24
24
|
export declare const pageNumberSpans: (html: string, page: string, total: string) => string;
|
|
25
|
+
/** Options of the flow and paged previews. */
|
|
26
|
+
export interface PreviewOptions {
|
|
27
|
+
/**
|
|
28
|
+
* The editor's edit mode: text in elements marked `data-ff-edit` (`annotateSourcePositions` with
|
|
29
|
+
* `editable`) can be edited in place, and the frame talks to the editor about it by message.
|
|
30
|
+
*/
|
|
31
|
+
editing?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* A name the editor gives this document, which the edit session's messages carry back
|
|
34
|
+
* (`formfeed:document` in the head). The editor has the next document ready a moment before the
|
|
35
|
+
* frame takes it; with the name it can tell a click that still came from the one before.
|
|
36
|
+
*/
|
|
37
|
+
document?: string;
|
|
38
|
+
}
|
|
25
39
|
/** What the preview frame reports about content wider than the page, or `null` when nothing is. */
|
|
26
40
|
export interface PreviewOverflow {
|
|
27
41
|
/** How far the widest element reaches past the right edge of the page's content area. */
|
|
@@ -43,8 +57,14 @@ export interface PreviewOverflow {
|
|
|
43
57
|
* The office quick preview's frame uses the same script.
|
|
44
58
|
*/
|
|
45
59
|
export declare const zoomGestureScript = "<script>\n(function () {\n var say = function (message) { try { parent.postMessage(message, '*'); } catch (e) {} };\n window.addEventListener('wheel', function (event) {\n if (!event.ctrlKey && !event.metaKey) return;\n event.preventDefault();\n say({ type: 'formfeed:zoom', deltaY: event.deltaY, deltaMode: event.deltaMode });\n }, { passive: false });\n window.addEventListener('keydown', function (event) {\n if (!(event.ctrlKey || event.metaKey) || event.altKey) return;\n var step = event.key === '+' || event.key === '=' ? 'in' : event.key === '-' ? 'out' : event.key === '0' ? 'reset' : null;\n if (!step) return;\n event.preventDefault();\n say({ type: 'formfeed:zoom', step: step });\n });\n})();\n</script>";
|
|
46
|
-
export declare function flowDocument(draft: RenderedDraft): string;
|
|
47
|
-
|
|
60
|
+
export declare function flowDocument(draft: RenderedDraft, options?: PreviewOptions): string;
|
|
61
|
+
/**
|
|
62
|
+
* The design stage's document (plan 16 §4.6): the assembled image template exactly as rendered, with
|
|
63
|
+
* no preview chrome around it (the stage draws its own background), and the stage runtime, which
|
|
64
|
+
* measures layers and takes drag styles and stylesheet patches by message.
|
|
65
|
+
*/
|
|
66
|
+
export declare function canvasDocument(draft: RenderedDraft): string;
|
|
67
|
+
export interface PagedOptions extends PreviewOptions {
|
|
48
68
|
/** URL of the Paged.js polyfill the frame can load. */
|
|
49
69
|
pagedScriptUrl: string;
|
|
50
70
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { EngineId } from './types.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* Editing text from the preview (plan 16 §3). An element whose content is literal text, output tags,
|
|
4
|
+
* inline children and line breaks — nothing that decides what is printed — is an *editable region*:
|
|
5
|
+
* the preview shows its text editable and everything else as atomic chips, and the edit comes back
|
|
6
|
+
* here to be written into the source. Text the user did not change keeps its source bytes, so
|
|
7
|
+
* indentation, line breaks and character references survive a one-word edit; changed text is
|
|
8
|
+
* HTML-escaped, and a `{` that could open template syntax is written as `{`. Every result is
|
|
9
|
+
* parsed again and compared with what the user typed before it is returned.
|
|
10
|
+
*/
|
|
11
|
+
export type RegionRefusal = 'not-an-element' | 'dynamic-tag' | 'void' | 'raw-text' | 'control-flow' | 'block-child' | 'unclosed' | 'no-text' | 'too-large';
|
|
12
|
+
export type ChipKind = 'expression' | 'element' | 'comment' | 'entity';
|
|
13
|
+
export type RegionPart = {
|
|
14
|
+
kind: 'text';
|
|
15
|
+
start: number;
|
|
16
|
+
end: number;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'break';
|
|
19
|
+
start: number;
|
|
20
|
+
end: number;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'chip';
|
|
23
|
+
start: number;
|
|
24
|
+
end: number;
|
|
25
|
+
chip: ChipKind;
|
|
26
|
+
label: string;
|
|
27
|
+
inner?: string;
|
|
28
|
+
};
|
|
29
|
+
export interface EditableRegion {
|
|
30
|
+
/** `t`: the whole content is one `t()` call, and the edit goes into the dictionary. */
|
|
31
|
+
kind: 'text' | 't';
|
|
32
|
+
tag: string;
|
|
33
|
+
/** Offset of the start tag's `<`. */
|
|
34
|
+
tagStart: number;
|
|
35
|
+
/** First character of the content, and the `<` of the end tag. */
|
|
36
|
+
start: number;
|
|
37
|
+
end: number;
|
|
38
|
+
/** After the end tag's `>`. */
|
|
39
|
+
outerEnd: number;
|
|
40
|
+
parts: RegionPart[];
|
|
41
|
+
/** `t` regions: the dictionary key and each parameter's expression by name. */
|
|
42
|
+
key?: string;
|
|
43
|
+
params?: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
/** What the preview shows and sends back: text, a chip by its index among the region's chips, a line break. */
|
|
46
|
+
export type EditItem = {
|
|
47
|
+
kind: 'text';
|
|
48
|
+
text: string;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'chip';
|
|
51
|
+
index: number;
|
|
52
|
+
} | {
|
|
53
|
+
kind: 'break';
|
|
54
|
+
};
|
|
55
|
+
export interface RegionChip {
|
|
56
|
+
index: number;
|
|
57
|
+
kind: ChipKind;
|
|
58
|
+
/** What the chip stands for: the expression, `<strong>`, a character reference. */
|
|
59
|
+
label: string;
|
|
60
|
+
source: string;
|
|
61
|
+
}
|
|
62
|
+
export type ApplyResult = {
|
|
63
|
+
source: string;
|
|
64
|
+
} | {
|
|
65
|
+
error: 'chips' | 'invalid';
|
|
66
|
+
};
|
|
67
|
+
/** A region, or why the element at that place is none. */
|
|
68
|
+
export type RegionLookup = EditableRegion | {
|
|
69
|
+
reason: RegionRefusal;
|
|
70
|
+
};
|
|
71
|
+
/** The region whose start tag's `<` is at `line`/`column` (1-based, as `data-ff-src` names it). */
|
|
72
|
+
export declare function editableRegion(source: string, engine: EngineId, location: {
|
|
73
|
+
line: number;
|
|
74
|
+
column: number;
|
|
75
|
+
}): RegionLookup;
|
|
76
|
+
/** The region whose start tag's `<` is at `at`. */
|
|
77
|
+
export declare function editableRegionAt(source: string, engine: EngineId, at: number): RegionLookup;
|
|
78
|
+
/**
|
|
79
|
+
* The region again after the source changed around it (someone typed in the code editor while the
|
|
80
|
+
* preview was being edited): found by its unique original markup, or null.
|
|
81
|
+
*/
|
|
82
|
+
export declare function findRegionAgain(source: string, engine: EngineId, outer: string): EditableRegion | null;
|
|
83
|
+
/** Where a region's start tag is, as `data-ff-src` names it: line and column, both 1-based. */
|
|
84
|
+
export declare function regionPosition(source: string, region: EditableRegion): {
|
|
85
|
+
line: number;
|
|
86
|
+
column: number;
|
|
87
|
+
};
|
|
88
|
+
/** The chips of a region in order, with what they stand for. */
|
|
89
|
+
export declare function regionChips(source: string, region: EditableRegion): RegionChip[];
|
|
90
|
+
/** What the preview shows while editing: decoded text (whitespace as written), chips and breaks. */
|
|
91
|
+
export declare function regionItems(source: string, region: EditableRegion): EditItem[];
|
|
92
|
+
/**
|
|
93
|
+
* Writes edited items back into the region. Chips may be deleted, never reordered or repeated. Text
|
|
94
|
+
* between the same two chips is diffed against what it was, so only the changed stretch is
|
|
95
|
+
* rewritten; if the result does not read back as the items (a kept `{` meeting a typed `%`), the
|
|
96
|
+
* whole content is written anew with every brace escaped.
|
|
97
|
+
*/
|
|
98
|
+
export declare function applyRegionEdit(source: string, engine: EngineId, region: EditableRegion, items: EditItem[]): ApplyResult;
|
|
99
|
+
/** A dictionary text as items: `{name}` placeholders become chips, in order of appearance. */
|
|
100
|
+
export declare function translationItems(text: string): {
|
|
101
|
+
items: EditItem[];
|
|
102
|
+
names: string[];
|
|
103
|
+
};
|
|
104
|
+
/** Edited dictionary items back into text: chips become their placeholders again, breaks spaces. */
|
|
105
|
+
export declare function translationText(items: EditItem[], names: string[]): string;
|
|
106
|
+
/**
|
|
107
|
+
* The value each chip shows while editing, read off the element's rendered text: the text between
|
|
108
|
+
* the chips must appear in it in order, and exactly one way of placing them must exist. Null when
|
|
109
|
+
* there is none or more than one (an empty value, a value that repeats a literal): the chips then
|
|
110
|
+
* show their labels.
|
|
111
|
+
*/
|
|
112
|
+
export declare function chipValues(rendered: string, items: EditItem[]): string[] | null;
|
|
113
|
+
/**
|
|
114
|
+
* Literal text for a template's HTML, as the design emitter writes it: escaped like an edit from the
|
|
115
|
+
* preview, so a `{` that could open template syntax is written as `{`.
|
|
116
|
+
*/
|
|
117
|
+
export declare function encodeTemplateText(text: string): string;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { EngineId } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Editing text from the preview (plan 16 §3). An element whose content is literal text, output tags,
|
|
4
|
+
* inline children and line breaks — nothing that decides what is printed — is an *editable region*:
|
|
5
|
+
* the preview shows its text editable and everything else as atomic chips, and the edit comes back
|
|
6
|
+
* here to be written into the source. Text the user did not change keeps its source bytes, so
|
|
7
|
+
* indentation, line breaks and character references survive a one-word edit; changed text is
|
|
8
|
+
* HTML-escaped, and a `{` that could open template syntax is written as `{`. Every result is
|
|
9
|
+
* parsed again and compared with what the user typed before it is returned.
|
|
10
|
+
*/
|
|
11
|
+
export type RegionRefusal = 'not-an-element' | 'dynamic-tag' | 'void' | 'raw-text' | 'control-flow' | 'block-child' | 'unclosed' | 'no-text' | 'too-large';
|
|
12
|
+
export type ChipKind = 'expression' | 'element' | 'comment' | 'entity';
|
|
13
|
+
export type RegionPart = {
|
|
14
|
+
kind: 'text';
|
|
15
|
+
start: number;
|
|
16
|
+
end: number;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'break';
|
|
19
|
+
start: number;
|
|
20
|
+
end: number;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'chip';
|
|
23
|
+
start: number;
|
|
24
|
+
end: number;
|
|
25
|
+
chip: ChipKind;
|
|
26
|
+
label: string;
|
|
27
|
+
inner?: string;
|
|
28
|
+
};
|
|
29
|
+
export interface EditableRegion {
|
|
30
|
+
/** `t`: the whole content is one `t()` call, and the edit goes into the dictionary. */
|
|
31
|
+
kind: 'text' | 't';
|
|
32
|
+
tag: string;
|
|
33
|
+
/** Offset of the start tag's `<`. */
|
|
34
|
+
tagStart: number;
|
|
35
|
+
/** First character of the content, and the `<` of the end tag. */
|
|
36
|
+
start: number;
|
|
37
|
+
end: number;
|
|
38
|
+
/** After the end tag's `>`. */
|
|
39
|
+
outerEnd: number;
|
|
40
|
+
parts: RegionPart[];
|
|
41
|
+
/** `t` regions: the dictionary key and each parameter's expression by name. */
|
|
42
|
+
key?: string;
|
|
43
|
+
params?: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
/** What the preview shows and sends back: text, a chip by its index among the region's chips, a line break. */
|
|
46
|
+
export type EditItem = {
|
|
47
|
+
kind: 'text';
|
|
48
|
+
text: string;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'chip';
|
|
51
|
+
index: number;
|
|
52
|
+
} | {
|
|
53
|
+
kind: 'break';
|
|
54
|
+
};
|
|
55
|
+
export interface RegionChip {
|
|
56
|
+
index: number;
|
|
57
|
+
kind: ChipKind;
|
|
58
|
+
/** What the chip stands for: the expression, `<strong>`, a character reference. */
|
|
59
|
+
label: string;
|
|
60
|
+
source: string;
|
|
61
|
+
}
|
|
62
|
+
export type ApplyResult = {
|
|
63
|
+
source: string;
|
|
64
|
+
} | {
|
|
65
|
+
error: 'chips' | 'invalid';
|
|
66
|
+
};
|
|
67
|
+
/** A region, or why the element at that place is none. */
|
|
68
|
+
export type RegionLookup = EditableRegion | {
|
|
69
|
+
reason: RegionRefusal;
|
|
70
|
+
};
|
|
71
|
+
/** The region whose start tag's `<` is at `line`/`column` (1-based, as `data-ff-src` names it). */
|
|
72
|
+
export declare function editableRegion(source: string, engine: EngineId, location: {
|
|
73
|
+
line: number;
|
|
74
|
+
column: number;
|
|
75
|
+
}): RegionLookup;
|
|
76
|
+
/** The region whose start tag's `<` is at `at`. */
|
|
77
|
+
export declare function editableRegionAt(source: string, engine: EngineId, at: number): RegionLookup;
|
|
78
|
+
/**
|
|
79
|
+
* The region again after the source changed around it (someone typed in the code editor while the
|
|
80
|
+
* preview was being edited): found by its unique original markup, or null.
|
|
81
|
+
*/
|
|
82
|
+
export declare function findRegionAgain(source: string, engine: EngineId, outer: string): EditableRegion | null;
|
|
83
|
+
/** Where a region's start tag is, as `data-ff-src` names it: line and column, both 1-based. */
|
|
84
|
+
export declare function regionPosition(source: string, region: EditableRegion): {
|
|
85
|
+
line: number;
|
|
86
|
+
column: number;
|
|
87
|
+
};
|
|
88
|
+
/** The chips of a region in order, with what they stand for. */
|
|
89
|
+
export declare function regionChips(source: string, region: EditableRegion): RegionChip[];
|
|
90
|
+
/** What the preview shows while editing: decoded text (whitespace as written), chips and breaks. */
|
|
91
|
+
export declare function regionItems(source: string, region: EditableRegion): EditItem[];
|
|
92
|
+
/**
|
|
93
|
+
* Writes edited items back into the region. Chips may be deleted, never reordered or repeated. Text
|
|
94
|
+
* between the same two chips is diffed against what it was, so only the changed stretch is
|
|
95
|
+
* rewritten; if the result does not read back as the items (a kept `{` meeting a typed `%`), the
|
|
96
|
+
* whole content is written anew with every brace escaped.
|
|
97
|
+
*/
|
|
98
|
+
export declare function applyRegionEdit(source: string, engine: EngineId, region: EditableRegion, items: EditItem[]): ApplyResult;
|
|
99
|
+
/** A dictionary text as items: `{name}` placeholders become chips, in order of appearance. */
|
|
100
|
+
export declare function translationItems(text: string): {
|
|
101
|
+
items: EditItem[];
|
|
102
|
+
names: string[];
|
|
103
|
+
};
|
|
104
|
+
/** Edited dictionary items back into text: chips become their placeholders again, breaks spaces. */
|
|
105
|
+
export declare function translationText(items: EditItem[], names: string[]): string;
|
|
106
|
+
/**
|
|
107
|
+
* The value each chip shows while editing, read off the element's rendered text: the text between
|
|
108
|
+
* the chips must appear in it in order, and exactly one way of placing them must exist. Null when
|
|
109
|
+
* there is none or more than one (an empty value, a value that repeats a literal): the chips then
|
|
110
|
+
* show their labels.
|
|
111
|
+
*/
|
|
112
|
+
export declare function chipValues(rendered: string, items: EditItem[]): string[] | null;
|
|
113
|
+
/**
|
|
114
|
+
* Literal text for a template's HTML, as the design emitter writes it: escaped like an edit from the
|
|
115
|
+
* preview, so a `{` that could open template syntax is written as `{`.
|
|
116
|
+
*/
|
|
117
|
+
export declare function encodeTemplateText(text: string): string;
|
|
@@ -5,16 +5,21 @@ import type { EngineId } from './types.cjs';
|
|
|
5
5
|
* rendered element says where it came from instead of the editor searching the template for it.
|
|
6
6
|
* Elements from a loop all point at the loop body, which is the line that wrote them.
|
|
7
7
|
*
|
|
8
|
+
* With `editable`, a start tag whose content is a region the preview can edit (plan 16 §3.1,
|
|
9
|
+
* `editableRegionAt`) also gets `data-ff-edit="text"`, or `data-ff-edit="t"` when its whole content
|
|
10
|
+
* is one `t()` call.
|
|
11
|
+
*
|
|
8
12
|
* The annotation must never change what the template means: tags inside template syntax, in
|
|
9
13
|
* blocks whose output is captured or filtered as a string (`{% set %}…{% endset %}`, `{% filter %}`,
|
|
10
14
|
* `{% capture %}`), in raw and comment blocks, in `<script>`/`<style>`/`<textarea>`/`<title>` and
|
|
11
15
|
* HTML comments, closing tags, declarations, tags whose name is built by template syntax and tags
|
|
12
|
-
* that already carry the attribute stay untouched. Removing the
|
|
16
|
+
* that already carry the attribute stay untouched. Removing the attributes from the rendered output
|
|
13
17
|
* gives the document of the original source. Preview only: saved versions, API renders and the
|
|
14
|
-
* render-worker never see
|
|
18
|
+
* render-worker never see them.
|
|
15
19
|
*/
|
|
16
20
|
export type SourceFile = 'body' | 'header' | 'footer';
|
|
17
21
|
export declare const sourceAttribute = "data-ff-src";
|
|
22
|
+
export declare const editAttribute = "data-ff-edit";
|
|
18
23
|
export interface SourceLocation {
|
|
19
24
|
file: SourceFile;
|
|
20
25
|
/** 1-based, as Monaco counts. */
|
|
@@ -22,6 +27,10 @@ export interface SourceLocation {
|
|
|
22
27
|
/** 1-based UTF-16 column of the tag's `<`. */
|
|
23
28
|
column: number;
|
|
24
29
|
}
|
|
30
|
+
export interface AnnotateOptions {
|
|
31
|
+
/** Mark editable regions with `data-ff-edit` as well (the preview's edit mode). */
|
|
32
|
+
editable?: boolean;
|
|
33
|
+
}
|
|
25
34
|
/** Parses a `data-ff-src` value; null when it is not one. */
|
|
26
35
|
export declare function parseSourceAttribute(value: string | null | undefined): SourceLocation | null;
|
|
27
|
-
export declare function annotateSourcePositions(source: string, engine: EngineId, file: SourceFile): string;
|
|
36
|
+
export declare function annotateSourcePositions(source: string, engine: EngineId, file: SourceFile, options?: AnnotateOptions): string;
|
|
@@ -5,16 +5,21 @@ import type { EngineId } from './types.js';
|
|
|
5
5
|
* rendered element says where it came from instead of the editor searching the template for it.
|
|
6
6
|
* Elements from a loop all point at the loop body, which is the line that wrote them.
|
|
7
7
|
*
|
|
8
|
+
* With `editable`, a start tag whose content is a region the preview can edit (plan 16 §3.1,
|
|
9
|
+
* `editableRegionAt`) also gets `data-ff-edit="text"`, or `data-ff-edit="t"` when its whole content
|
|
10
|
+
* is one `t()` call.
|
|
11
|
+
*
|
|
8
12
|
* The annotation must never change what the template means: tags inside template syntax, in
|
|
9
13
|
* blocks whose output is captured or filtered as a string (`{% set %}…{% endset %}`, `{% filter %}`,
|
|
10
14
|
* `{% capture %}`), in raw and comment blocks, in `<script>`/`<style>`/`<textarea>`/`<title>` and
|
|
11
15
|
* HTML comments, closing tags, declarations, tags whose name is built by template syntax and tags
|
|
12
|
-
* that already carry the attribute stay untouched. Removing the
|
|
16
|
+
* that already carry the attribute stay untouched. Removing the attributes from the rendered output
|
|
13
17
|
* gives the document of the original source. Preview only: saved versions, API renders and the
|
|
14
|
-
* render-worker never see
|
|
18
|
+
* render-worker never see them.
|
|
15
19
|
*/
|
|
16
20
|
export type SourceFile = 'body' | 'header' | 'footer';
|
|
17
21
|
export declare const sourceAttribute = "data-ff-src";
|
|
22
|
+
export declare const editAttribute = "data-ff-edit";
|
|
18
23
|
export interface SourceLocation {
|
|
19
24
|
file: SourceFile;
|
|
20
25
|
/** 1-based, as Monaco counts. */
|
|
@@ -22,6 +27,10 @@ export interface SourceLocation {
|
|
|
22
27
|
/** 1-based UTF-16 column of the tag's `<`. */
|
|
23
28
|
column: number;
|
|
24
29
|
}
|
|
30
|
+
export interface AnnotateOptions {
|
|
31
|
+
/** Mark editable regions with `data-ff-edit` as well (the preview's edit mode). */
|
|
32
|
+
editable?: boolean;
|
|
33
|
+
}
|
|
25
34
|
/** Parses a `data-ff-src` value; null when it is not one. */
|
|
26
35
|
export declare function parseSourceAttribute(value: string | null | undefined): SourceLocation | null;
|
|
27
|
-
export declare function annotateSourcePositions(source: string, engine: EngineId, file: SourceFile): string;
|
|
36
|
+
export declare function annotateSourcePositions(source: string, engine: EngineId, file: SourceFile, options?: AnnotateOptions): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { EngineId } from './types.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* A template source read as HTML with template constructs in it: the scanner that finds start tags
|
|
4
|
+
* for click-to-source (`source-positions.ts`) and the regions text can be edited in from the preview
|
|
5
|
+
* (`source-edit.ts`). It knows each engine's delimiters, string literals inside expressions, raw and
|
|
6
|
+
* comment blocks, and blocks whose output is captured as a string. Internal to the engine.
|
|
7
|
+
*/
|
|
8
|
+
export declare const tagName: RegExp;
|
|
9
|
+
/** Elements whose content the HTML parser reads as text, so a `<b>` inside is not an element. */
|
|
10
|
+
export declare const rawTextElements: Set<string>;
|
|
11
|
+
/**
|
|
12
|
+
* What a template construct is, for a reader that has to tell output from control flow: `output` is
|
|
13
|
+
* a value printed in place (`{{ x }}`, `{{{ x }}}`, `{{t 'k'}}`), `comment` prints nothing, and
|
|
14
|
+
* `statement` is everything that decides what is printed (`{% if %}`, `{{#each}}`, `{{else}}`,
|
|
15
|
+
* `{{> partial}}`, raw blocks).
|
|
16
|
+
*/
|
|
17
|
+
export type TemplateConstruct = {
|
|
18
|
+
type: 'output';
|
|
19
|
+
end: number;
|
|
20
|
+
inner: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'comment';
|
|
23
|
+
end: number;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'statement';
|
|
26
|
+
end: number;
|
|
27
|
+
keyword?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare class Scanner {
|
|
30
|
+
private readonly source;
|
|
31
|
+
private readonly engine;
|
|
32
|
+
private readonly n;
|
|
33
|
+
private readonly escapes;
|
|
34
|
+
constructor(source: string, engine: EngineId);
|
|
35
|
+
/** End of the template construct starting at `at` (with a capturing block's body), or null. */
|
|
36
|
+
skipTemplate(at: number): number | null;
|
|
37
|
+
/** The construct starting at `at` and what kind it is, or null when `{` starts none. */
|
|
38
|
+
classify(at: number): TemplateConstruct | null;
|
|
39
|
+
/** Index after `close`, stepping over template constructs; the end of the source when missing. */
|
|
40
|
+
skipTo(from: number, close: string): number;
|
|
41
|
+
/** Index after the `>` that ends a tag, stepping over quoted values and template constructs. */
|
|
42
|
+
tagEnd(from: number): number;
|
|
43
|
+
/** Index of the `</name` that closes a raw text element. */
|
|
44
|
+
skipToClosingTag(from: number, name: string): number;
|
|
45
|
+
private captures;
|
|
46
|
+
private blockEnd;
|
|
47
|
+
private templateTag;
|
|
48
|
+
/** `{{{{raw}}}} … {{{{/raw}}}}`: the content is never parsed. */
|
|
49
|
+
private handlebarsRawBlock;
|
|
50
|
+
private indexAfter;
|
|
51
|
+
/** End of an expression or statement; a `close` inside a string literal does not end it. */
|
|
52
|
+
private expressionEnd;
|
|
53
|
+
}
|
|
54
|
+
/** Offsets where lines start; `\r\n`, `\n` and a lone `\r` all end a line, as in Monaco. */
|
|
55
|
+
export declare function lineStarts(source: string): number[];
|
|
56
|
+
export declare function locate(starts: number[], offset: number): {
|
|
57
|
+
line: number;
|
|
58
|
+
column: number;
|
|
59
|
+
};
|
|
60
|
+
/** The offset of a 1-based line and column, or null when the source has no such place. */
|
|
61
|
+
export declare function offsetOf(starts: number[], sourceLength: number, line: number, column: number): number | null;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { EngineId } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A template source read as HTML with template constructs in it: the scanner that finds start tags
|
|
4
|
+
* for click-to-source (`source-positions.ts`) and the regions text can be edited in from the preview
|
|
5
|
+
* (`source-edit.ts`). It knows each engine's delimiters, string literals inside expressions, raw and
|
|
6
|
+
* comment blocks, and blocks whose output is captured as a string. Internal to the engine.
|
|
7
|
+
*/
|
|
8
|
+
export declare const tagName: RegExp;
|
|
9
|
+
/** Elements whose content the HTML parser reads as text, so a `<b>` inside is not an element. */
|
|
10
|
+
export declare const rawTextElements: Set<string>;
|
|
11
|
+
/**
|
|
12
|
+
* What a template construct is, for a reader that has to tell output from control flow: `output` is
|
|
13
|
+
* a value printed in place (`{{ x }}`, `{{{ x }}}`, `{{t 'k'}}`), `comment` prints nothing, and
|
|
14
|
+
* `statement` is everything that decides what is printed (`{% if %}`, `{{#each}}`, `{{else}}`,
|
|
15
|
+
* `{{> partial}}`, raw blocks).
|
|
16
|
+
*/
|
|
17
|
+
export type TemplateConstruct = {
|
|
18
|
+
type: 'output';
|
|
19
|
+
end: number;
|
|
20
|
+
inner: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'comment';
|
|
23
|
+
end: number;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'statement';
|
|
26
|
+
end: number;
|
|
27
|
+
keyword?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare class Scanner {
|
|
30
|
+
private readonly source;
|
|
31
|
+
private readonly engine;
|
|
32
|
+
private readonly n;
|
|
33
|
+
private readonly escapes;
|
|
34
|
+
constructor(source: string, engine: EngineId);
|
|
35
|
+
/** End of the template construct starting at `at` (with a capturing block's body), or null. */
|
|
36
|
+
skipTemplate(at: number): number | null;
|
|
37
|
+
/** The construct starting at `at` and what kind it is, or null when `{` starts none. */
|
|
38
|
+
classify(at: number): TemplateConstruct | null;
|
|
39
|
+
/** Index after `close`, stepping over template constructs; the end of the source when missing. */
|
|
40
|
+
skipTo(from: number, close: string): number;
|
|
41
|
+
/** Index after the `>` that ends a tag, stepping over quoted values and template constructs. */
|
|
42
|
+
tagEnd(from: number): number;
|
|
43
|
+
/** Index of the `</name` that closes a raw text element. */
|
|
44
|
+
skipToClosingTag(from: number, name: string): number;
|
|
45
|
+
private captures;
|
|
46
|
+
private blockEnd;
|
|
47
|
+
private templateTag;
|
|
48
|
+
/** `{{{{raw}}}} … {{{{/raw}}}}`: the content is never parsed. */
|
|
49
|
+
private handlebarsRawBlock;
|
|
50
|
+
private indexAfter;
|
|
51
|
+
/** End of an expression or statement; a `close` inside a string literal does not end it. */
|
|
52
|
+
private expressionEnd;
|
|
53
|
+
}
|
|
54
|
+
/** Offsets where lines start; `\r\n`, `\n` and a lone `\r` all end a line, as in Monaco. */
|
|
55
|
+
export declare function lineStarts(source: string): number[];
|
|
56
|
+
export declare function locate(starts: number[], offset: number): {
|
|
57
|
+
line: number;
|
|
58
|
+
column: number;
|
|
59
|
+
};
|
|
60
|
+
/** The offset of a 1-based line and column, or null when the source has no such place. */
|
|
61
|
+
export declare function offsetOf(starts: number[], sourceLength: number, line: number, column: number): number | null;
|