UNPKG

@teipublisher/pb-components

Version:
28 lines (25 loc) 11.7 kB
import{p as e,h as t,c as i,L as o}from"./pb-mixin-886ece32.js";import{J as n,X as s}from"./jinn-codemirror-b4fb2138.js";import{t as r}from"./pb-i18n-4cc00bfe.js";class l{constructor(e){this.config=e}detectContext(e,t){const i=e.state.sliceDoc(Math.max(0,t-500),t),o=new RegExp(this.config.attributeName+"\\s*=\\s*([\"'])([^\"']*)$"),n=i.match(o);if(!n)return{isInAttribute:!1,elementName:null,conditionValue:null};const s=i.substring(0,i.length-n[0].length).match(/<(\w+)([^>]*?)$/);if(!s)return{isInAttribute:!0,elementName:null,conditionValue:null};const r=s[1],l=s[2];let a=null;if(this.config.conditionAttribute){const e=new RegExp(this.config.conditionAttribute.name+"\\s*=\\s*[\"']([^\"']+)[\"']"),t=l.match(e);a=t?t[1]:null}return{isInAttribute:!0,elementName:r,conditionValue:a}}createCompletionSource(){return async e=>{const{state:t,pos:i,view:o}=e;if(!o)return null;const n=this.detectContext(o,i);if(n.elementName!==this.config.elementName||!n.isInAttribute)return null;if(this.config.conditionAttribute&&n.conditionValue!==this.config.conditionAttribute.value)return null;const s=t.sliceDoc(Math.max(0,i-100),i),r=new RegExp(this.config.attributeName+"\\s*=\\s*([\"'])([^\"']*)$"),l=s.match(r);if(!l)return null;const a=l[2],d=a||"";return{from:i-a.length,to:i,options:await this.config.callback(d||void 0),filter:!1}}}}class a{}class d extends a{constructor(e=null){super(),this.baseUrl=e}createAutocomplete(){return new l({elementName:"ref",attributeName:"target",conditionAttribute:{name:"type",value:"biblio"},callback:this.createZoteroAutocompleteCallback()})}createZoteroAutocompleteCallback(){return async e=>{try{let t=(this.baseUrl||"")+"/api/zotero/items/suggest";e&&(t+="?q="+encodeURIComponent(e));const i=await fetch(t);if(!i.ok)return console.error("Failed to fetch Zotero suggestions:",i.status,i.statusText),[];const o=await i.json();let n=[];return Array.isArray(o)&&(n=o.map(e=>({displayLabel:e.tag,detail:e.title,label:"#"+e.tag,type:"text",info:()=>{if(!e.bib)return null;const t=document.createElement("span");return t.innerHTML=e.bib,t}}))),console.log("Zotero suggestions:",n),n}catch(e){return console.error("Error fetching Zotero suggestions:",e),[]}}}}class h extends n{constructor(){super(),this.unwrap=!1,this.autocompleteProviders=[],this.schema=null,this.schemaRoot=null,this.baseUrl=null}connectedCallback(){var e;this.schema=this.getAttribute("schema"),this.schemaRoot=this.getAttribute("schema-root"),this.baseUrl=this.getAttribute("base-url"),this.unwrap=this.hasAttribute("unwrap"),this.autocompleteProviders=(null===(e=this.getAttribute("providers"))||void 0===e?void 0:e.split(",").map(e=>{if("zotero"===e)return new d(this.baseUrl);throw new Error("Unknown autocomplete provider: "+e)}))||[],super.connectedCallback();const t=this.getAttribute("wrapper");if(t){const e=new DOMParser;let i=e.parseFromString(t,"application/xml"),o=i.getElementsByTagName("parsererror"),n=null;if(o.length)console.error("<jinn-xml-editor> Invalid XML for wrapper attribute: %s",(new XMLSerializer).serializeToString(i));else{if(n=i.firstElementChild,n&&this.hasAttribute("code")){const t=this.getAttribute("code")||"";i=e.parseFromString(t,"application/xml"),o=i.getElementsByTagName("parsererror"),o.length?console.error("<jinn-xml-editor> Invalid XML for code attribute: %s",(new XMLSerializer).serializeToString(i)):i.firstElementChild&&n.appendChild(i.firstElementChild)}this.setValue(n)}}}configure(){var e;const t=this.getToolbarControls(null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("[name=toolbar]")),i=this.hasAttribute("check-namespace");this._config=new s(this,t,this.namespace,i,this.unwrap,this.autocompleteProviders.map(e=>e.createAutocomplete()))}emitUpdateEvent(e){if(!this.unwrap)return super.emitUpdateEvent(e);this.updateValue(),super.emitUpdateEvent(this._wrapper)}updateValue(){if(!this._wrapper)return console.log("no wrapper !!!"),null;if(this._wrapper.replaceChildren(),this._value)if(this._value instanceof NodeList)for(let t=0;t<this._value.length;t++){var e;const i=this._wrapper.ownerDocument.importNode(this._value[t],!0);null===(e=this._wrapper)||void 0===e||e.appendChild(i)}else{if(!(this._value instanceof Node))throw console.error("<xml-editor> Value is not a node"),new Error("value is not a node");var t;null===(t=this._wrapper)||void 0===t||t.appendChild(this._value)}else console.log("xml editor value is empty")}setValue(e){var t,i,o;if(!this.unwrap)return super.setValue(e);if((null===(t=this._config)||void 0===t?void 0:t.setFromValue(this._wrapper))===(null===(i=this._config)||void 0===i?void 0:i.setFromValue(e)))return!1;if(e||(this._wrapper=null),"string"==typeof e){const t=(new DOMParser).parseFromString(e,"application/xml");if(!t.firstElementChild)return!1;e=t.firstElementChild}return this._wrapper=e,this._value=null===(o=e)||void 0===o?void 0:o.childNodes,!0}getValue(){if(!this.unwrap)return super.getValue();if(!this._wrapper)return null;if(!(this._wrapper instanceof Element))throw new Error("Value is not a node");return this.updateValue(),this._wrapper}}customElements.get("jinn-xml-editor")||window.customElements.define("jinn-xml-editor",h);const c='\n :host {\n display: block;\n width: 100%;\n }\n jinn-codemirror {\n font-size: 1rem;\n display:block;\n width:100%;\n }\n jinn-codemirror[valid="true"] {\n outline: thin solid green;\n }\n jinn-codemirror[valid="false"] {\n outline: thin solid red;\n }\n #leiden-editor {\n margin-bottom:0.5rem;\n }\n [slot=toolbar] {\n display: flex;\n }\n .hidden {\n display: none;\n }\n #close-leiden {\n margin-left: .75rem;\n font-weight: bold;\n }',u=["Shift","Alt","Meta","Control","ArrowLeft","ArrowRight","ArrowDown","ArrowUp","PageDown","PageUp","Home","End"],m={leiden_plus:"Leiden+",edcs:"EDCS/EDH",default:"Petrae"};function p(e){const t=[];return Object.entries(m).forEach(([i,o])=>{t.push(`<option value="${i}" ${i===e?"selected":""}>${o}</option>`)}),`<select name="modes">${t.join("\n")}</select>`}class v extends HTMLElement{constructor(){super(),this.mode="leiden_plus",this.placeholder="",this.showLeiden=!1,this.xmlEditor=null,this.valid=!0,this.unwrap=!1,this.schema=null,this.schemaRoot=null,this.modeSelect=!1,this.attachShadow({mode:"open"})}set value(e){this.xmlEditor.value=e}get value(){return this.xmlEditor.value}connectedCallback(){var e,t,i,o;this.unwrap=this.hasAttribute("unwrap"),this.schema=this.getAttribute("schema"),this.schemaRoot=this.getAttribute("schema-root"),this.modeSelect=this.hasAttribute("mode-select"),this.mode=this.getAttribute("mode")||"leiden_plus",this.placeholder=this.getAttribute("placeholder")||"",this.showLeiden=this.hasAttribute("show-leiden"),this.shadowRoot.innerHTML=`\n <style>\n ${c}\n </style>\n <jinn-codemirror id="leiden-editor" class="${this.showLeiden?"":"hidden"}" \n mode="${this.mode}" ignore-blur>\n <div slot="header"><slot name="leiden-header"></slot></div>\n <div slot="toolbar">\n ${this.modeSelect?p(this.mode):""}\n <slot name="leiden-toolbar"></slot>\n <button part="button" id="close-leiden">Close</button>\n </div>\n </jinn-codemirror>\n <jinn-xml-editor id="xml-editor" ${this.unwrap?"unwrap":""} schema="${this.schema}"\n schema-root="${this.schemaRoot}" placeholder="${this.placeholder}" ignore-blur\n namespace="http://www.tei-c.org/ns/1.0">\n <div slot="header"><slot name="xml-header"></slot></div>\n <div slot="toolbar">\n <slot name="open-leiden" id="import" class="${this.showLeiden?"hidden":""}">\n <button part="button" title="Import from Leiden markup">Leiden Editor</button>\n </slot>\n <slot name="xml-toolbar"></slot>\n </div>\n </jinn-xml-editor>\n `,this.xmlEditor=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector("#xml-editor");const n=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector("#leiden-editor"),s=null===(i=this.shadowRoot)||void 0===i?void 0:i.querySelector("#import"),r=null===(o=this.shadowRoot)||void 0===o?void 0:o.querySelector("#close-leiden");if(!(this.xmlEditor&&n&&s&&r))throw new Error("One or more components were not initialized");let l=!0,a=this.showLeiden;n.addEventListener("update",e=>{e.stopPropagation(),this.showLeiden=!1,l&&(this.xmlEditor.content=e.detail.content),l=!0}),this.xmlEditor.addEventListener("keyup",e=>{if(a){if(u.indexOf(e.key)>-1)return;h()}});const d=()=>{s.classList.add("hidden"),n.classList.remove("hidden"),a=!0,n.focus()},h=()=>{var e;n.classList.add("hidden"),s.classList.remove("hidden"),a=!1,null===(e=this.xmlEditor)||void 0===e||e.focus(),l=!1,null==n||n.clear()},m=()=>{if(n.classList.contains("hidden")||this.showLeiden)if(this.xmlEditor.content.length>0){var e;if(!this.valid)return void alert("The XML contains errors. Cannot convert to Leiden+");const t=null===(e=this.xmlEditor)||void 0===e?void 0:e.value;l=!1,n.setMode("leiden_plus",!1);try{this.unwrap&&t instanceof Element?n.value=t.childNodes:n.value=t,this.xmlEditor.status="",d()}catch(e){this.xmlEditor.status=e.message,h()}}else d(),n.value="";else h()};s.addEventListener("click",()=>{m()}),r.addEventListener("click",()=>{h()}),this.xmlEditor.addEventListener("invalid",e=>{e.stopPropagation(),this.valid=!1,this.setAttribute("valid",this.valid.toString()),this.dispatchEvent(new CustomEvent("invalid",{detail:e.detail,composed:!0,bubbles:!0}))}),this.xmlEditor.addEventListener("valid",e=>{e.stopPropagation(),this.valid=!0,this.setAttribute("valid",this.valid.toString()),this.dispatchEvent(new CustomEvent("valid",{detail:e.detail,composed:!0,bubbles:!0}))}),this.xmlEditor.addEventListener("update",()=>{this.showLeiden&&m(),this.showLeiden=!1},{once:!0}),this.addEventListener("blur",e=>{e.relatedTarget&&!this.contains(e.relatedTarget)&&this.dispatchEvent(new CustomEvent("leave",{composed:!0,bubbles:!0}))})}}customElements.get("jinn-epidoc-editor")||window.customElements.define("jinn-epidoc-editor",v);class b extends(e(o)){static get properties(){return Object.assign(Object.assign({},super.properties),{},{code:{type:String,reflect:!0},mode:{type:String},label:{type:String},placeholder:{type:String},tabSize:{type:Number},linter:{attribute:!0}})}constructor(){super(),this.code="",this.mode="xml",this.placeholder="odd.editor.model.empty",this.tabSize=2,this.label="",this.linter="",this._editor=null}connectedCallback(){super.connectedCallback()}firstUpdated(){super.firstUpdated(),this._editor=this.shadowRoot.getElementById("editor")}render(){return t` <div class="label">${this.label}</div> <jinn-codemirror id="editor" mode="${this.mode}" code="${this.code}" placeholder="${r(this.placeholder)}" ></jinn-codemirror> `}getSource(){return this._editor?this._editor.value:""}_setCode(){this.dispatchEvent(new CustomEvent("code-changed",{composed:!0,bubbles:!0,detail:{code:this.getSource()}}))}refresh(){}static get styles(){return i` :host { display: block; width: 100%; margin: 0; position: relative; color: inherit; } #editor { width: 100%; height: auto; } .label { color: var(--paper-grey-500); margin-bottom: 5px; } `}}customElements.define("pb-code-editor",b);export{b as PbCodeEditor};