@webcoder49/code-input 1.5.1 → 2.0.1

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 +1 @@
1
- code-input{position:relative;top:0;left:0;display:block;overflow:hidden;padding:8px;margin:0!important;width:calc(100% - 16px);height:250px;font-size:normal;font-family:monospace;line-height:1.5;tab-size:2;caret-color:#a9a9a9;white-space:pre}code-input textarea,code-input.code-input_pre-element-styled pre,code-input:not(.code-input_pre-element-styled) pre code{margin:0!important;padding:var(--padding,16px)!important;border:0;width:calc(100% - var(--padding,16px) * 2);height:calc(100% - var(--padding,16px) * 2)}code-input.code-input_pre-element-styled pre code,code-input:not(.code-input_pre-element-styled) pre{margin:0!important;padding:0!important;width:100%;height:100%}code-input pre,code-input pre *,code-input textarea{font-size:inherit!important;font-family:inherit!important;line-height:inherit!important;tab-size:inherit!important}code-input pre,code-input textarea{position:absolute;top:0;left:0}code-input textarea{z-index:1}code-input pre{z-index:0}code-input textarea{color:transparent;background:0 0;caret-color:inherit!important}code-input pre,code-input textarea{overflow:auto!important;white-space:inherit;word-spacing:normal;word-break:normal;word-wrap:normal}code-input textarea{resize:none;outline:0!important}code-input:not(.code-input_registered)::before{content:"Use codeInput.registerTemplate to set up.";display:block;color:grey}
1
+ code-input{position:relative;top:0;left:0;display:block;overflow:hidden;margin:8px;--padding:16px;height:250px;font-size:normal;font-family:monospace;line-height:1.5;tab-size:2;caret-color:#a9a9a9;white-space:pre;padding:0!important}code-input textarea,code-input.code-input_pre-element-styled pre,code-input:not(.code-input_pre-element-styled) pre code{margin:0!important;padding:var(--padding,16px)!important;border:0;width:calc(100% - var(--padding,16px) * 2);height:calc(100% - var(--padding,16px) * 2)}code-input:not(.code-input_loaded){margin:0!important;margin-bottom:calc(-1 * var(--padding,16px))!important;padding:var(--padding,16px)!important;border:0}code-input.code-input_pre-element-styled pre code,code-input:not(.code-input_pre-element-styled) pre{margin:0!important;padding:0!important;width:100%;height:100%}code-input pre,code-input pre *,code-input textarea{font-size:inherit!important;font-family:inherit!important;line-height:inherit!important;tab-size:inherit!important}code-input pre,code-input textarea{position:absolute;top:0;left:0}code-input textarea{z-index:1}code-input pre{z-index:0}code-input:not(.code-input_loaded) pre,code-input:not(.code-input_loaded) textarea{opacity:0}code-input:not(.code-input_loaded)::after{color:#ccc}code-input textarea{color:transparent;background:0 0;caret-color:inherit!important}code-input pre,code-input textarea{overflow:auto!important;white-space:inherit;word-spacing:normal;word-break:normal;word-wrap:normal}code-input textarea{resize:none;outline:0!important}code-input:not(.code-input_registered)::after{content:"Use codeInput.registerTemplate to set up.";display:block;color:grey}
package/code-input.min.js CHANGED
@@ -1 +1 @@
1
- var codeInput={observedAttributes:["value","placeholder","lang","template"],textareaSyncAttributes:["value","name","required","minlength","maxlength","min","max","type","pattern"],textareaSyncEvents:["change","selectionchange","invalid","input"],usedTemplates:{},defaultTemplate:void 0,templateNotYetRegisteredQueue:{},registerTemplate:function(a,b){if(!("string"==typeof a||a instanceof String))throw TypeError(`Template for "${a}" must be a string.`);if(!("function"==typeof b.highlight||b.highlight instanceof Function))throw TypeError(`Template for "${a}" invalid, because the highlight function provided is not a function; it is "${b.highlight}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.includeCodeInputInHighlightFunc||b.includeCodeInputInHighlightFunc instanceof Boolean))throw TypeError(`Template for "${a}" invalid, because the includeCodeInputInHighlightFunc value provided is not a true or false; it is "${b.includeCodeInputInHighlightFunc}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.preElementStyled||b.preElementStyled instanceof Boolean))throw TypeError(`Template for "${a}" invalid, because the preElementStyled value provided is not a true or false; it is "${b.preElementStyled}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.isCode||b.isCode instanceof Boolean))throw TypeError(`Template for "${a}" invalid, because the isCode value provided is not a true or false; it is "${b.isCode}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!Array.isArray(b.plugins))throw TypeError(`Template for "${a}" invalid, because the plugin array provided is not an array; it is "${b.plugins}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(b.plugins.forEach((c,d)=>{if(!(c instanceof codeInput.Plugin))throw TypeError(`Template for "${a}" invalid, because the plugin provided at index ${d} is not valid; it is "${b.plugins[d]}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`)}),codeInput.usedTemplates[a]=b,a in codeInput.templateNotYetRegisteredQueue){for(let c in codeInput.templateNotYetRegisteredQueue[a])elem=codeInput.templateNotYetRegisteredQueue[a][c],elem.template=b,elem.setup();console.log(`code-input: template: Added existing elements with template ${a}`)}if(null==codeInput.defaultTemplate){if(codeInput.defaultTemplate=a,void 0 in codeInput.templateNotYetRegisteredQueue)for(let a in codeInput.templateNotYetRegisteredQueue[void 0])elem=codeInput.templateNotYetRegisteredQueue[void 0][a],elem.template=b,elem.setup();console.log(`code-input: template: Set template ${a} as default`)}console.log(`code-input: template: Created template ${a}`)},templates:{custom(a=function(){},b=!0,c=!0,d=!1,e=[]){return{highlight:a,includeCodeInputInHighlightFunc:d,preElementStyled:b,isCode:c,plugins:e}},prism(a,b=[]){return{includeCodeInputInHighlightFunc:!1,highlight:a.highlightElement,preElementStyled:!0,isCode:!0,plugins:b}},hljs(a,b=[]){return{includeCodeInputInHighlightFunc:!1,highlight:a.highlightElement,preElementStyled:!1,isCode:!0,plugins:b}},characterLimit(a){return{highlight:function(a,b,c=[]){let d=+b.getAttribute("data-character-limit"),e=b.escapeHtml(b.value.slice(0,d)),f=b.escapeHtml(b.value.slice(d));a.innerHTML=`${e}<mark class="overflow">${f}</mark>`,0<f.length&&(a.innerHTML+=` <mark class="overflow-msg">${b.getAttribute("data-overflow-msg")||"(Character limit reached)"}</mark>`)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,plugins:a}},rainbowText(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return{highlight:function(a,b){let c=[],d=b.value.split(b.template.delimiter);for(let e=0;e<d.length;e++)c.push(`<span style="color: ${b.template.rainbowColors[e%b.template.rainbowColors.length]}">${b.escapeHtml(d[e])}</span>`);a.innerHTML=c.join(b.template.delimiter)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,rainbowColors:a,delimiter:b,plugins:c}},character_limit(){return this.characterLimit([])},rainbow_text(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return this.rainbowText(a,b,c)}},plugins:{},Plugin:class{constructor(){console.log("code-input: plugin: Created plugin"),codeInput.observedAttributes=codeInput.observedAttributes.concat(self.observedAttributes)}beforeHighlight(){}afterHighlight(){}beforeElementsAdded(){}afterElementsAdded(){}attributeChanged(){}observedAttributes=[]},CodeInput:class extends HTMLElement{constructor(){super()}boundEventCallbacks={};pluginEvt(a,b){for(let c in this.template.plugins){let d=this.template.plugins[c];a in d&&(b===void 0?d[a](this):d[a](this,...b))}}update(a){if(!this.ignoreValueUpdate){this.ignoreValueUpdate=!0,this.value=a,this.ignoreValueUpdate=!1,this.querySelector("textarea").value!=a&&(this.querySelector("textarea").value=a);let b=this.querySelector("pre code");"\n"==a[a.length-1]&&(a+=" "),b.innerHTML=this.escapeHtml(a),this.pluginEvt("beforeHighlight"),this.template.includeCodeInputInHighlightFunc?this.template.highlight(b,this):this.template.highlight(b),this.pluginEvt("afterHighlight")}}syncScroll(){let a=this.querySelector("textarea"),b=this.template.preElementStyled?this.querySelector("pre"):this.querySelector("pre code");b.scrollTop=a.scrollTop,b.scrollLeft=a.scrollLeft}escapeHtml(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;")}getTemplate(){let a;return a=null==this.getAttribute("template")?codeInput.defaultTemplate:this.getAttribute("template"),a in codeInput.usedTemplates?codeInput.usedTemplates[a]:(a in codeInput.templateNotYetRegisteredQueue||(codeInput.templateNotYetRegisteredQueue[a]=[]),void codeInput.templateNotYetRegisteredQueue[a].push(this))}setup(){this.classList.add("code-input_registered"),this.template.preElementStyled&&this.classList.add("code-input_pre-element-styled"),this.pluginEvt("beforeElementsAdded");let a=this.getAttribute("lang"),b=this.getAttribute("placeholder")||this.getAttribute("lang")||"",c=this.value||this.innerHTML||"";this.innerHTML="";let d=document.createElement("textarea");d.placeholder=b,d.value=c,d.setAttribute("spellcheck","false"),codeInput.textareaSyncAttributes.forEach(a=>{this.hasAttribute(a)&&d.setAttribute(a,this.getAttribute(a))}),d.addEventListener("input",()=>{d.parentElement.update(d.value),d.parentElement.sync_scroll()}),d.addEventListener("scroll",()=>d.parentElement.sync_scroll()),this.append(d);let e=document.createElement("code"),f=document.createElement("pre");f.setAttribute("aria-hidden","true"),f.append(e),this.append(f),this.template.isCode&&a!=null&&""!=a&&e.classList.add("language-"+a),this.pluginEvt("afterElementsAdded"),this.update(c)}sync_scroll(){this.syncScroll()}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}connectedCallback(){this.template=this.getTemplate(),this.template!=null&&this.setup()}static get observedAttributes(){return codeInput.observedAttributes.concat(codeInput.textareaSyncAttributes)}attributeChangedCallback(a,b,c){if(this.isConnected)switch(this.pluginEvt("attributeChanged",[a,b,c]),a){case"value":this.update(c);break;case"placeholder":this.querySelector("textarea").placeholder=c;break;case"template":this.template=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.template.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.update(this.value);break;case"lang":let d=this.querySelector("pre code"),e=this.querySelector("textarea");if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;b=b.toLowerCase(),console.log("code-input: Language: REMOVE","language-"+b),d.classList.remove("language-"+b),d.parentElement.classList.remove("language-"+b),d.classList.remove("language-none"),d.parentElement.classList.remove("language-none"),null!=c&&""!=c&&(d.classList.add("language-"+c),console.log("code-input: Language:ADD","language-"+c)),e.placeholder==b&&(e.placeholder=c),this.update(this.value);break;default:codeInput.textareaSyncAttributes.includes(a)&&this.querySelector("textarea").setAttribute(a,c)}}addEventListener(a,b,c=void 0){let d=b.bind(this);this.boundEventCallbacks[b]=d,codeInput.textareaSyncEvents.includes(a)?c===void 0?this.querySelector("textarea").addEventListener(a,d):this.querySelector("textarea").addEventListener(a,d,c):c===void 0?super.addEventListener(a,d):super.addEventListener(a,d,c)}removeEventListener(a,b,c=null){let d=this.boundEventCallbacks[b];"change"==a?null===c?this.querySelector("textarea").removeEventListener("change",d):this.querySelector("textarea").removeEventListener("change",d,c):"selectionchange"==a?null===c?this.querySelector("textarea").removeEventListener("selectionchange",d):this.querySelector("textarea").removeEventListener("selectionchange",d,c):super.removeEventListener(a,b,c)}get value(){return this.getAttribute("value")}set value(a){return this.setAttribute("value",a)}get placeholder(){return this.getAttribute("placeholder")}set placeholder(a){return this.setAttribute("placeholder",a)}get validity(){return this.querySelector("textarea").validity}get validationMessage(){return this.querySelector("textarea").validationMessage}setCustomValidity(a){return this.querySelector("textarea").setCustomValidity(a)}checkValidity(){return this.querySelector("textarea").checkValidity()}reportValidity(){return this.querySelector("textarea").reportValidity()}setAttribute(a,b){super.setAttribute(a,b),this.querySelector("textarea").setAttribute(a,b)}getAttribute(a){return null==this.querySelector("textarea")?super.getAttribute(a):this.querySelector("textarea").getAttribute(a)}pluginData={}}};customElements.define("code-input",codeInput.CodeInput);
1
+ var codeInput={observedAttributes:["value","placeholder","lang","template"],textareaSyncAttributes:["aria-*","value","name","required","minlength","maxlength","min","max","type","pattern"],textareaSyncEvents:["change","selectionchange","invalid","input"],usedTemplates:{},defaultTemplate:void 0,templateNotYetRegisteredQueue:{},registerTemplate:function(a,b){if(!("string"==typeof a||a instanceof String))throw TypeError(`code-input: Template for "${a}" must be a string.`);if(!("function"==typeof b.highlight||b.highlight instanceof Function))throw TypeError(`code-input: Template for "${a}" invalid, because the highlight function provided is not a function; it is "${b.highlight}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.includeCodeInputInHighlightFunc||b.includeCodeInputInHighlightFunc instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the includeCodeInputInHighlightFunc value provided is not a true or false; it is "${b.includeCodeInputInHighlightFunc}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.preElementStyled||b.preElementStyled instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the preElementStyled value provided is not a true or false; it is "${b.preElementStyled}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.isCode||b.isCode instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the isCode value provided is not a true or false; it is "${b.isCode}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!Array.isArray(b.plugins))throw TypeError(`code-input: Template for "${a}" invalid, because the plugin array provided is not an array; it is "${b.plugins}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(b.plugins.forEach((c,d)=>{if(!(c instanceof codeInput.Plugin))throw TypeError(`code-input: Template for "${a}" invalid, because the plugin provided at index ${d} is not valid; it is "${b.plugins[d]}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`)}),codeInput.usedTemplates[a]=b,a in codeInput.templateNotYetRegisteredQueue){for(let c in codeInput.templateNotYetRegisteredQueue[a])elem=codeInput.templateNotYetRegisteredQueue[a][c],elem.template=b,codeInput.runOnceWindowLoaded(function(a){a.connectedCallback()}.bind(null,elem),elem);console.log(`code-input: template: Added existing elements with template ${a}`)}if(null==codeInput.defaultTemplate){if(codeInput.defaultTemplate=a,void 0 in codeInput.templateNotYetRegisteredQueue)for(let a in codeInput.templateNotYetRegisteredQueue[void 0])elem=codeInput.templateNotYetRegisteredQueue[void 0][a],elem.template=b,codeInput.runOnceWindowLoaded(function(a){a.connectedCallback()}.bind(null,elem),elem);console.log(`code-input: template: Set template ${a} as default`)}console.log(`code-input: template: Created template ${a}`)},Template:class{constructor(a=function(){},b=!0,c=!0,d=!1,e=[]){this.highlight=a,this.preElementStyled=b,this.isCode=c,this.includeCodeInputInHighlightFunc=d,this.plugins=e}highlight=function(){};preElementStyled=!0;isCode=!0;includeCodeInputInHighlightFunc=!1;plugins=[]},templates:{prism(a,b=[]){return{includeCodeInputInHighlightFunc:!1,highlight:a.highlightElement,preElementStyled:!0,isCode:!0,plugins:b}},hljs(a,b=[]){return{includeCodeInputInHighlightFunc:!1,highlight:a.highlightElement,preElementStyled:!1,isCode:!0,plugins:b}},characterLimit(a){return{highlight:function(a,b,c=[]){let d=+b.getAttribute("data-character-limit"),e=b.escapeHtml(b.value.slice(0,d)),f=b.escapeHtml(b.value.slice(d));a.innerHTML=`${e}<mark class="overflow">${f}</mark>`,0<f.length&&(a.innerHTML+=` <mark class="overflow-msg">${b.getAttribute("data-overflow-msg")||"(Character limit reached)"}</mark>`)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,plugins:a}},rainbowText(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return{highlight:function(a,b){let c=[],d=b.value.split(b.template.delimiter);for(let e=0;e<d.length;e++)c.push(`<span style="color: ${b.template.rainbowColors[e%b.template.rainbowColors.length]}">${b.escapeHtml(d[e])}</span>`);a.innerHTML=c.join(b.template.delimiter)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,rainbowColors:a,delimiter:b,plugins:c}},character_limit(){return this.characterLimit([])},rainbow_text(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return this.rainbowText(a,b,c)},custom(a=function(){},b=!0,c=!0,d=!1,e=[]){return{highlight:a,includeCodeInputInHighlightFunc:d,preElementStyled:b,isCode:c,plugins:e}}},plugins:new Proxy({},{get(a,b){if(a[b]==null)throw ReferenceError(`code-input: Plugin '${b}' is not defined. Please ensure you import the necessary files from the plugins folder in the WebCoder49/code-input repository, in the <head> of your HTML, before the plugin is instatiated.`);return a[b]}}),Plugin:class{constructor(a){console.log("code-input: plugin: Created plugin"),a.forEach(a=>{let b=codeInput.wildcard2regex(a);null==b?codeInput.observedAttributes.push(a):codeInput.observedAttributes.regexp.push(b)})}beforeHighlight(){}afterHighlight(){}beforeElementsAdded(){}afterElementsAdded(){}attributeChanged(){}},CodeInput:class extends HTMLElement{constructor(){super()}_value="";textareaElement=null;preElement=null;codeElement=null;static formAssociated=!0;boundEventCallbacks={};pluginEvt(a,b){for(let c in this.template.plugins){let d=this.template.plugins[c];a in d&&(b===void 0?d[a](this):d[a](this,...b))}}update(a){if(!this.ignoreValueUpdate){if(null==this.textareaElement)return void this.addEventListener("code-input_load",()=>{this.update(a)});this.ignoreValueUpdate=!0,this.value=a,this.ignoreValueUpdate=!1,this.textareaElement.value!=a&&(this.textareaElement.value=a);let b=this.codeElement;"\n"==a[a.length-1]&&(a+=" "),b.innerHTML=this.escapeHtml(a),this.pluginEvt("beforeHighlight"),this.template.includeCodeInputInHighlightFunc?this.template.highlight(b,this):this.template.highlight(b),this.pluginEvt("afterHighlight")}}syncScroll(){let a=this.textareaElement,b=this.template.preElementStyled?this.preElement:this.codeElement;b.scrollTop=a.scrollTop,b.scrollLeft=a.scrollLeft}escapeHtml(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;")}unescapeHtml(a){return a.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">")}getTemplate(){let a;return a=null==this.getAttribute("template")?codeInput.defaultTemplate:this.getAttribute("template"),a in codeInput.usedTemplates?codeInput.usedTemplates[a]:(a in codeInput.templateNotYetRegisteredQueue||(codeInput.templateNotYetRegisteredQueue[a]=[]),void codeInput.templateNotYetRegisteredQueue[a].push(this))}setup(){if(null!=this.textareaElement)return;this.classList.add("code-input_registered"),this.template.preElementStyled&&this.classList.add("code-input_pre-element-styled"),this.pluginEvt("beforeElementsAdded");let a=this.getAttribute("lang"),b=this.getAttribute("placeholder")||this.getAttribute("lang")||"",c=this.unescapeHtml(this.innerHTML)||this.getAttribute("value")||"";this.initialValue=c;let d=document.createElement("textarea");d.placeholder=b,""!=c&&(d.value=c),d.innerHTML=this.innerHTML,d.setAttribute("spellcheck","false"),this.innerHTML="",codeInput.textareaSyncAttributes.forEach(a=>{this.hasAttribute(a)&&d.setAttribute(a,this.getAttribute(a))}),codeInput.textareaSyncAttributes.regexp.forEach(a=>{for(const b of this.attributes)b.nodeName.match(a)&&d.setAttribute(b.nodeName,b.nodeValue)}),d.addEventListener("input",()=>{d.parentElement.update(d.value),d.parentElement.sync_scroll()}),d.addEventListener("scroll",()=>d.parentElement.sync_scroll()),this.textareaElement=d,this.append(d);let e=document.createElement("code"),f=document.createElement("pre");f.setAttribute("aria-hidden","true"),this.preElement=f,this.codeElement=e,f.append(e),this.append(f),this.template.isCode&&a!=null&&""!=a&&e.classList.add("language-"+a),this.pluginEvt("afterElementsAdded"),this.update(c),this.dispatchEvent(new CustomEvent("code-input_load"))}sync_scroll(){this.syncScroll()}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}connectedCallback(){this.template=this.getTemplate(),this.template!=null&&(this.classList.add("code-input_registered"),codeInput.runOnceWindowLoaded(()=>{this.setup(),this.classList.add("code-input_loaded")},this)),this.mutationObserver=new MutationObserver(this.mutationObserverCallback.bind(this)),this.mutationObserver.observe(this,{attributes:!0,attributeOldValue:!0})}mutationObserverCallback(a){for(const b of a)if("attributes"===b.type){for(let a=0;a<codeInput.observedAttributes.length;a++)if(b.attributeName==codeInput.observedAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));for(let a=0;a<codeInput.observedAttributes.regexp.length;a++){const c=codeInput.observedAttributes.regexp[a];if(b.attributeName.match(c))return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName))}}}disconnectedCallback(){this.mutationObserver.disconnect()}attributeChangedCallback(a,b,c){if(this.isConnected)switch(this.pluginEvt("attributeChanged",[a,b,c]),a){case"value":this.value=c;break;case"placeholder":this.textareaElement.placeholder=c;break;case"template":this.template=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.template.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.update(this.value);break;case"lang":let d=this.codeElement,e=this.textareaElement;if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;b=b.toLowerCase(),console.log("code-input: Language: REMOVE","language-"+b),d.classList.remove("language-"+b),d.parentElement.classList.remove("language-"+b),d.classList.remove("language-none"),d.parentElement.classList.remove("language-none"),null!=c&&""!=c&&(d.classList.add("language-"+c),console.log("code-input: Language: ADD","language-"+c)),e.placeholder==b&&(e.placeholder=c),this.update(this.value);break;default:codeInput.textareaSyncAttributes.includes(a)?null==c?this.textareaElement.removeAttribute(a):this.textareaElement.setAttribute(a,c):codeInput.textareaSyncAttributes.regexp.forEach(b=>{a.match(b)&&(null==c?this.textareaElement.removeAttribute(a):this.textareaElement.setAttribute(a,c))})}}addEventListener(a,b,c=void 0){let d=b.bind(this);this.boundEventCallbacks[b]=d,codeInput.textareaSyncEvents.includes(a)?c===void 0?null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d)}):this.textareaElement.addEventListener(a,d):null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d,c)}):this.textareaElement.addEventListener(a,d,c):c===void 0?super.addEventListener(a,d):super.addEventListener(a,d,c)}removeEventListener(a,b,c=null){let d=this.boundEventCallbacks[b];"change"==a?null===c?this.textareaElement.removeEventListener("change",d):this.textareaElement.removeEventListener("change",d,c):"selectionchange"==a?null===c?this.textareaElement.removeEventListener("selectionchange",d):this.textareaElement.removeEventListener("selectionchange",d,c):super.removeEventListener(a,b,c)}get value(){return this._value}set value(a){return(null===a||void 0===a)&&(a=""),this._value=a,this.update(a),a}get placeholder(){return this.getAttribute("placeholder")}set placeholder(a){return this.setAttribute("placeholder",a)}get validity(){return this.textareaElement.validity}get validationMessage(){return this.textareaElement.validationMessage}setCustomValidity(a){return this.textareaElement.setCustomValidity(a)}checkValidity(){return this.textareaElement.checkValidity()}reportValidity(){return this.textareaElement.reportValidity()}setAttribute(a,b){super.setAttribute(a,b),null!=this.textareaElement&&this.textareaElement.setAttribute(a,b)}getAttribute(a){return null==this.textareaElement?super.getAttribute(a):this.textareaElement.getAttribute(a)}pluginData={};formResetCallback(){this.update(this.initialValue)}},arrayWildcards2regex(a){for(let b=0;b<a.length;b++){const c=a[b];0>c.indexOf("*")||(a.regexp.push(new RegExp("^"+c.replace(/[/\-\\^$+?.()|[\]{}]/g,"\\$&").replace("*",".*")+"$","i")),a.splice(b--,1))}},wildcard2regex(a){return 0>a.indexOf("*")?null:new RegExp("^"+a.replace(/[/\-\\^$+?.()|[\]{}]/g,"\\$&").replace("*",".*")+"$","i")},runOnceWindowLoaded(a){codeInput.windowLoaded?a():window.addEventListener("load",a)},windowLoaded:!1};window.addEventListener("load",function(){codeInput.windowLoaded=!0}),Object.defineProperty(codeInput.textareaSyncAttributes,"regexp",{value:[],writable:!1,enumerable:!1,configurable:!1}),codeInput.observedAttributes=codeInput.observedAttributes.concat(codeInput.textareaSyncAttributes),Object.defineProperty(codeInput.observedAttributes,"regexp",{value:[],writable:!1,enumerable:!1,configurable:!1}),codeInput.arrayWildcards2regex(codeInput.textareaSyncAttributes),codeInput.arrayWildcards2regex(codeInput.observedAttributes),customElements.define("code-input",codeInput.CodeInput);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webcoder49/code-input",
3
- "version": "1.5.1",
3
+ "version": "2.0.1",
4
4
  "description": "Fully customisable, editable syntax-highlighted textareas.",
5
5
  "browser": "code-input.js",
6
6
  "scripts": {
@@ -5,10 +5,10 @@
5
5
  codeInput.plugins.Autocomplete = class extends codeInput.Plugin {
6
6
  /**
7
7
  * Pass in a function to display the popup that takes in (popup element, textarea, textarea.selectionEnd).
8
- * @param {function} updatePopupCallback
8
+ * @param {function} updatePopupCallback a function to display the popup that takes in (popup element, textarea, textarea.selectionEnd).
9
9
  */
10
10
  constructor(updatePopupCallback) {
11
- super();
11
+ super([]); // No observed attributes
12
12
  this.updatePopupCallback = updatePopupCallback;
13
13
  }
14
14
  /* When a key is pressed, or scrolling occurs, update the autocomplete */
@@ -75,6 +75,5 @@ codeInput.plugins.Autocomplete = class extends codeInput.Plugin {
75
75
  }
76
76
  return {"top": afterSpan.offsetTop - textarea.scrollTop, "left": afterSpan.offsetLeft - textarea.scrollLeft};
77
77
  }
78
- observedAttributes = [];
79
78
  updatePopupCallback = function() {};
80
79
  }
@@ -1 +1 @@
1
- codeInput.plugins.Autocomplete=class extends codeInput.Plugin{constructor(a){super(),this.updatePopupCallback=a}updatePopup(a,b){let c=a.querySelector("textarea"),d=this.getCaretCoordinates(a,c,c.selectionEnd,b),e=a.querySelector(".code-input_autocomplete_popup");e.style.top=d.top+"px",e.style.left=d.left+"px",b||this.updatePopupCallback(e,c,c.selectionEnd)}afterElementsAdded(a){let b=document.createElement("div");b.classList.add("code-input_autocomplete_popup"),a.appendChild(b);let c=document.createElement("pre");c.classList.add("code-input_autocomplete_testpos"),a.appendChild(c);let d=a.querySelector("textarea");d.addEventListener("keyup",this.updatePopup.bind(this,a,!1)),d.addEventListener("click",this.updatePopup.bind(this,a,!1)),d.addEventListener("scroll",this.updatePopup.bind(this,a,!0))}getCaretCoordinates(a,b,c,d){let e;if(d){let d=a.querySelector(".code-input_autocomplete_testpos").querySelectorAll("span");if(2>d.length)return this.getCaretCoordinates(a,b,c,!1);e=d[1]}else{let d=a.querySelector(".code-input_autocomplete_testpos"),f=document.createElement("span");for(f.textContent=b.value.substring(0,c),e=document.createElement("span"),e.textContent=".";d.firstChild;)d.removeChild(d.firstChild);d.appendChild(f),d.appendChild(e)}return{top:e.offsetTop-b.scrollTop,left:e.offsetLeft-b.scrollLeft}}observedAttributes=[];updatePopupCallback=function(){}};
1
+ codeInput.plugins.Autocomplete=class extends codeInput.Plugin{constructor(a){super([]),this.updatePopupCallback=a}updatePopup(a,b){let c=a.querySelector("textarea"),d=this.getCaretCoordinates(a,c,c.selectionEnd,b),e=a.querySelector(".code-input_autocomplete_popup");e.style.top=d.top+"px",e.style.left=d.left+"px",b||this.updatePopupCallback(e,c,c.selectionEnd)}afterElementsAdded(a){let b=document.createElement("div");b.classList.add("code-input_autocomplete_popup"),a.appendChild(b);let c=document.createElement("pre");c.classList.add("code-input_autocomplete_testpos"),a.appendChild(c);let d=a.querySelector("textarea");d.addEventListener("keyup",this.updatePopup.bind(this,a,!1)),d.addEventListener("click",this.updatePopup.bind(this,a,!1)),d.addEventListener("scroll",this.updatePopup.bind(this,a,!0))}getCaretCoordinates(a,b,c,d){let e;if(d){let d=a.querySelector(".code-input_autocomplete_testpos").querySelectorAll("span");if(2>d.length)return this.getCaretCoordinates(a,b,c,!1);e=d[1]}else{let d=a.querySelector(".code-input_autocomplete_testpos"),f=document.createElement("span");for(f.textContent=b.value.substring(0,c),e=document.createElement("span"),e.textContent=".";d.firstChild;)d.removeChild(d.firstChild);d.appendChild(f),d.appendChild(e)}return{top:e.offsetTop-b.scrollTop,left:e.offsetLeft-b.scrollLeft}}updatePopupCallback=function(){}};
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Autodetect the language live and change the `lang` attribute using the syntax highlighter's
3
- * autodetect capabilities. Works with highlight.js.
3
+ * autodetect capabilities. Works with highlight.js only.
4
4
  * Files: autodetect.js
5
5
  */
6
6
  codeInput.plugins.Autodetect = class extends codeInput.Plugin {
7
7
  constructor() {
8
- super();
8
+ super([]); // No observed attributes
9
9
  }
10
10
  /* Remove previous language class */
11
11
  beforeHighlight(codeInput) {
@@ -25,5 +25,4 @@ codeInput.plugins.Autodetect = class extends codeInput.Plugin {
25
25
  codeInput.setAttribute("lang", lang);
26
26
  }
27
27
  }
28
- observedAttributes = []
29
28
  }
@@ -1 +1 @@
1
- codeInput.plugins.Autodetect=class extends codeInput.Plugin{constructor(){super()}beforeHighlight(a){let b=a.querySelector("pre code");b.className="",b.parentElement.className=""}afterHighlight(a){let b=a.querySelector("pre code"),c=b.className||b.parentElement.className,d=c.match(/lang(\w|-)*/i)[0];d=d.split("-")[1],"undefined"==d?a.removeAttribute("lang"):a.setAttribute("lang",d)}observedAttributes=[]};
1
+ codeInput.plugins.Autodetect=class extends codeInput.Plugin{constructor(){super([])}beforeHighlight(a){let b=a.querySelector("pre code");b.className="",b.parentElement.className=""}afterHighlight(a){let b=a.querySelector("pre code"),c=b.className||b.parentElement.className,d=c.match(/lang(\w|-)*/i)[0];d=d.split("-")[1],"undefined"==d?a.removeAttribute("lang"):a.setAttribute("lang",d)}};
@@ -9,7 +9,7 @@ codeInput.plugins.DebounceUpdate = class extends codeInput.Plugin {
9
9
  * @param {Number} delayMs Delay, in ms, to wait until updating the syntax highlighting
10
10
  */
11
11
  constructor(delayMs) {
12
- super();
12
+ super([]); // No observed attributes
13
13
  this.delayMs = delayMs;
14
14
  }
15
15
  /* Runs before elements are added into a `code-input`; Params: codeInput element) */
@@ -1 +1 @@
1
- codeInput.plugins.DebounceUpdate=class extends codeInput.Plugin{constructor(a){super(),this.delayMs=a}beforeElementsAdded(a){console.log(a,"before elements added"),this.update=a.update.bind(a),a.update=this.updateDebounced.bind(this,a)}updateDebounced(a,b){null!=this.debounceTimeout&&window.clearTimeout(this.debounceTimeout),this.debounceTimeout=window.setTimeout(()=>{this.update(b)},this.delayMs)}debounceTimeout=null;delayMs=0};
1
+ codeInput.plugins.DebounceUpdate=class extends codeInput.Plugin{constructor(a){super([]),this.delayMs=a}beforeElementsAdded(a){console.log(a,"before elements added"),this.update=a.update.bind(a),a.update=this.updateDebounced.bind(this,a)}updateDebounced(a,b){null!=this.debounceTimeout&&window.clearTimeout(this.debounceTimeout),this.debounceTimeout=window.setTimeout(()=>{this.update(b)},this.delayMs)}debounceTimeout=null;delayMs=0};
package/plugins/indent.js CHANGED
@@ -5,7 +5,7 @@
5
5
  */
6
6
  codeInput.plugins.Indent = class extends codeInput.Plugin {
7
7
  constructor() {
8
- super();
8
+ super([]); // No observed attributes
9
9
  }
10
10
 
11
11
  /* Add keystroke events */
@@ -1 +1 @@
1
- codeInput.plugins.Indent=class extends codeInput.Plugin{constructor(){super()}afterElementsAdded(a){let b=a.querySelector("textarea");b.addEventListener("keydown",b=>{this.check_tab(a,b),this.check_enter(a,b)})}check_tab(a,b){if("Tab"!=b.key)return;let c=a.querySelector("textarea"),d=c.value;if(b.preventDefault(),!b.shiftKey&&c.selectionStart==c.selectionEnd)document.execCommand("insertText",!1,"\t");else{let a=c.value.split("\n"),d=0,e=c.selectionStart,f=c.selectionEnd;for(let g=0;g<a.length;g++)(e<=d+a[g].length&&f>=d+1||e==f&&e<=d+a[g].length+1&&f>=d)&&(b.shiftKey?"\t"==a[g][0]&&(c.selectionStart=d,c.selectionEnd=d+1,document.execCommand("delete",!1,""),e>d&&e--,f--,d--):(c.selectionStart=d,c.selectionEnd=d,document.execCommand("insertText",!1,"\t"),e>d&&e++,f++,d++)),d+=a[g].length+1;c.selectionStart=e,c.selectionEnd=f}a.update(c.value)}check_enter(a,b){if("Enter"!=b.key)return;b.preventDefault();let c=a.querySelector("textarea"),d=c.value.split("\n"),e=0,f=d.length-1,g="",h=0;for(let g=0;g<d.length;g++)if(e+=d[g].length+1,c.selectionEnd<=e){f=g;break}let j=d[f].length-(e-c.selectionEnd)+1;for(let c=0;c<j&&"\t"==d[f][c];c++)h++;let k="";j!=d[f].length&&(k=d[f].substring(j),d[f]=d[f].substring(0,j));for(let c=0;c<h;c++)g+="\t";let l=c.selectionStart,m=c.selectionEnd;document.execCommand("insertText",!1,"\n"+g),c.selectionStart=l+h+1,c.selectionEnd=l+h+1,a.update(c.value),c.scrollLeft=0;let n=+getComputedStyle(c).lineHeight.split(0,-2);c.scrollTop+=n==NaN&&"px"==getComputedStyle(c).lineHeight.split(-2)?n:20}};
1
+ codeInput.plugins.Indent=class extends codeInput.Plugin{constructor(){super([])}afterElementsAdded(a){let b=a.querySelector("textarea");b.addEventListener("keydown",b=>{this.check_tab(a,b),this.check_enter(a,b)})}check_tab(a,b){if("Tab"!=b.key)return;let c=a.querySelector("textarea"),d=c.value;if(b.preventDefault(),!b.shiftKey&&c.selectionStart==c.selectionEnd)document.execCommand("insertText",!1,"\t");else{let a=c.value.split("\n"),d=0,e=c.selectionStart,f=c.selectionEnd;for(let g=0;g<a.length;g++)(e<=d+a[g].length&&f>=d+1||e==f&&e<=d+a[g].length+1&&f>=d)&&(b.shiftKey?"\t"==a[g][0]&&(c.selectionStart=d,c.selectionEnd=d+1,document.execCommand("delete",!1,""),e>d&&e--,f--,d--):(c.selectionStart=d,c.selectionEnd=d,document.execCommand("insertText",!1,"\t"),e>d&&e++,f++,d++)),d+=a[g].length+1;c.selectionStart=e,c.selectionEnd=f}a.update(c.value)}check_enter(a,b){if("Enter"!=b.key)return;b.preventDefault();let c=a.querySelector("textarea"),d=c.value.split("\n"),e=0,f=d.length-1,g="",h=0;for(let g=0;g<d.length;g++)if(e+=d[g].length+1,c.selectionEnd<=e){f=g;break}let j=d[f].length-(e-c.selectionEnd)+1;for(let c=0;c<j&&"\t"==d[f][c];c++)h++;let k="";j!=d[f].length&&(k=d[f].substring(j),d[f]=d[f].substring(0,j));for(let c=0;c<h;c++)g+="\t";let l=c.selectionStart,m=c.selectionEnd;document.execCommand("insertText",!1,"\n"+g),c.selectionStart=l+h+1,c.selectionEnd=l+h+1,a.update(c.value),c.scrollLeft=0;let n=+getComputedStyle(c).lineHeight.split(0,-2);c.scrollTop+=n==NaN&&"px"==getComputedStyle(c).lineHeight.split(-2)?n:20}};
@@ -3,8 +3,6 @@
3
3
  * Files: special-chars.js, special-chars.css
4
4
  */
5
5
 
6
- // INCOMPLETE: TODO Optimise regex - compile at start; Update CSS for character display; clean up + comment
7
-
8
6
  codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
9
7
  specialCharRegExp;
10
8
 
@@ -13,13 +11,14 @@ codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
13
11
  canvasContext;
14
12
 
15
13
  /**
16
- * Create a special characters plugin instance
14
+ * Create a special characters plugin instance.
15
+ * Default = covers many non-renderable ASCII characters.
17
16
  * @param {Boolean} colorInSpecialChars Whether or not to give special characters custom background colors based on their hex code
18
17
  * @param {Boolean} inheritTextColor If `colorInSpecialChars` is false, forces the color of the hex code to inherit from syntax highlighting. Otherwise, the base colour of the `pre code` element is used to give contrast to the small characters.
19
18
  * @param {RegExp} specialCharRegExp The regular expression which matches special characters
20
19
  */
21
20
  constructor(colorInSpecialChars = false, inheritTextColor = false, specialCharRegExp = /(?!\n)(?!\t)[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]|[\u{0200}-\u{FFFF}]/ug) { // By default, covers many non-renderable ASCII characters
22
- super();
21
+ super([]); // No observed attributes
23
22
 
24
23
  this.specialCharRegExp = specialCharRegExp;
25
24
  this.colorInSpecialChars = colorInSpecialChars;
@@ -153,7 +152,7 @@ codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
153
152
  }
154
153
  }
155
154
 
156
- getCharacterWidth(codeInput, char) { // TODO: Check StackOverflow question
155
+ getCharacterWidth(codeInput, char) {
157
156
  // Force zero-width characters
158
157
  if(new RegExp("\u00AD|\u02de|[\u0300-\u036F]|[\u0483-\u0489]|\u200b").test(char) ) { return 0 }
159
158
  // Non-renderable ASCII characters should all be rendered at same size
@@ -1 +1 @@
1
- codeInput.plugins.SpecialChars=class extends codeInput.Plugin{specialCharRegExp;cachedColors;cachedWidths;canvasContext;constructor(a=!1,b=!1,c=/(?!\n)(?!\t)[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]|[\u{0200}-\u{FFFF}]/ug){super(),this.specialCharRegExp=c,this.colorInSpecialChars=a,this.inheritTextColor=b,this.cachedColors={},this.cachedWidths={};let d=document.createElement("canvas");this.canvasContext=d.getContext("2d")}beforeElementsAdded(a){a.classList.add("code-input_special-char_container")}afterElementsAdded(a){setTimeout(()=>{a.update(a.value)},100)}afterHighlight(a){let b=a.querySelector("pre code");a.pluginData.specialChars={},a.pluginData.specialChars.textarea=a.getElementsByTagName("textarea")[0],a.pluginData.specialChars.contrastColor=window.getComputedStyle(b).color,this.recursivelyReplaceText(a,b),this.lastFont=window.getComputedStyle(a.pluginData.specialChars.textarea).font}recursivelyReplaceText(a,b){for(let c,d=0;d<b.childNodes.length;d++)if(c=b.childNodes[d],"#text"==c.nodeName&&""!=c.nodeValue){let b=c.nodeValue;this.specialCharRegExp.lastIndex=0;let d=this.specialCharRegExp.exec(b);if(null!=d){let b=d.index;if(c=c.splitText(b+1).previousSibling,0<b&&(c=c.splitText(b)),""!=c.textContent){let b=this.specialCharReplacer(a,c.textContent);c.parentNode.insertBefore(b,c),c.textContent=""}}}else 1==c.nodeType&&"code-input_special-char"!=c.className&&""!=c.nodeValue&&this.recursivelyReplaceText(a,c)}specialCharReplacer(a,b){let c,d=b.codePointAt(0);this.colorInSpecialChars&&(c=this.getCharacterColor(d)),d=d.toString(16),d=("0000"+d).substring(d.length),d=d.toUpperCase();let e=this.getCharacterWidth(a,b),f=document.createElement("span");return f.classList.add("code-input_special-char"),f.style.setProperty("--hex-0","var(--code-input_special-chars_"+d[0]+")"),f.style.setProperty("--hex-1","var(--code-input_special-chars_"+d[1]+")"),f.style.setProperty("--hex-2","var(--code-input_special-chars_"+d[2]+")"),f.style.setProperty("--hex-3","var(--code-input_special-chars_"+d[3]+")"),0==e?f.classList.add("code-input_special-char_zero-width"):f.style.width=e+"px",this.colorInSpecialChars?(f.style.backgroundColor="#"+c[0],f.style.setProperty("--code-input_special-char_color",c[1])):!this.inheritTextColor&&f.style.setProperty("--code-input_special-char_color",a.pluginData.specialChars.contrastColor),f}getCharacterColor(a){let b,c;if(!(a in this.cachedColors)){b=a^a<<3^a<<7^a<<14^a<<16,b^=2082343,b=b.toString(16),b=("000000"+b).substring(b.length);let d=0,e=[.299,.587,.114];for(let a=0;6>a;a+=2)d+=parseInt(b.substring(a,a+2),16)*e[a/2];return c=128>d?"white":"black",this.cachedColors[a]=[b,c],[b,c]}return this.cachedColors[a]}getCharacterWidth(a,b){if(/­|˞|[̀-ͯ]|[҃-҉]|​/.test(b))return 0;if("\x96"!=b&&/[\0-]|[-Ÿ]/g.test(b)){let a=this.getCharacterWidth("\x96");return a}let c=window.getComputedStyle(a.pluginData.specialChars.textarea).font;if(null==this.cachedWidths[c]&&(this.cachedWidths[c]={}),null!=this.cachedWidths[c][b])return this.cachedWidths[c][b];this.canvasContext.font=c;let d=this.canvasContext.measureText(b).width;if(d>+c.split("px")[0])d/=2;else if(0==d&&"\x96"!=b){let a=this.getCharacterWidth("\x96");return a}return this.cachedWidths[c][b]=d,d}};
1
+ codeInput.plugins.SpecialChars=class extends codeInput.Plugin{specialCharRegExp;cachedColors;cachedWidths;canvasContext;constructor(a=!1,b=!1,c=/(?!\n)(?!\t)[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]|[\u{0200}-\u{FFFF}]/ug){super([]),this.specialCharRegExp=c,this.colorInSpecialChars=a,this.inheritTextColor=b,this.cachedColors={},this.cachedWidths={};let d=document.createElement("canvas");this.canvasContext=d.getContext("2d")}beforeElementsAdded(a){a.classList.add("code-input_special-char_container")}afterElementsAdded(a){setTimeout(()=>{a.update(a.value)},100)}afterHighlight(a){let b=a.querySelector("pre code");a.pluginData.specialChars={},a.pluginData.specialChars.textarea=a.getElementsByTagName("textarea")[0],a.pluginData.specialChars.contrastColor=window.getComputedStyle(b).color,this.recursivelyReplaceText(a,b),this.lastFont=window.getComputedStyle(a.pluginData.specialChars.textarea).font}recursivelyReplaceText(a,b){for(let c,d=0;d<b.childNodes.length;d++)if(c=b.childNodes[d],"#text"==c.nodeName&&""!=c.nodeValue){let b=c.nodeValue;this.specialCharRegExp.lastIndex=0;let d=this.specialCharRegExp.exec(b);if(null!=d){let b=d.index;if(c=c.splitText(b+1).previousSibling,0<b&&(c=c.splitText(b)),""!=c.textContent){let b=this.specialCharReplacer(a,c.textContent);c.parentNode.insertBefore(b,c),c.textContent=""}}}else 1==c.nodeType&&"code-input_special-char"!=c.className&&""!=c.nodeValue&&this.recursivelyReplaceText(a,c)}specialCharReplacer(a,b){let c,d=b.codePointAt(0);this.colorInSpecialChars&&(c=this.getCharacterColor(d)),d=d.toString(16),d=("0000"+d).substring(d.length),d=d.toUpperCase();let e=this.getCharacterWidth(a,b),f=document.createElement("span");return f.classList.add("code-input_special-char"),f.style.setProperty("--hex-0","var(--code-input_special-chars_"+d[0]+")"),f.style.setProperty("--hex-1","var(--code-input_special-chars_"+d[1]+")"),f.style.setProperty("--hex-2","var(--code-input_special-chars_"+d[2]+")"),f.style.setProperty("--hex-3","var(--code-input_special-chars_"+d[3]+")"),0==e?f.classList.add("code-input_special-char_zero-width"):f.style.width=e+"px",this.colorInSpecialChars?(f.style.backgroundColor="#"+c[0],f.style.setProperty("--code-input_special-char_color",c[1])):!this.inheritTextColor&&f.style.setProperty("--code-input_special-char_color",a.pluginData.specialChars.contrastColor),f}getCharacterColor(a){let b,c;if(!(a in this.cachedColors)){b=a^a<<3^a<<7^a<<14^a<<16,b^=2082343,b=b.toString(16),b=("000000"+b).substring(b.length);let d=0,e=[.299,.587,.114];for(let a=0;6>a;a+=2)d+=parseInt(b.substring(a,a+2),16)*e[a/2];return c=128>d?"white":"black",this.cachedColors[a]=[b,c],[b,c]}return this.cachedColors[a]}getCharacterWidth(a,b){if(/­|˞|[̀-ͯ]|[҃-҉]|​/.test(b))return 0;if("\x96"!=b&&/[\0-]|[-Ÿ]/g.test(b)){let a=this.getCharacterWidth("\x96");return a}let c=window.getComputedStyle(a.pluginData.specialChars.textarea).font;if(null==this.cachedWidths[c]&&(this.cachedWidths[c]={}),null!=this.cachedWidths[c][b])return this.cachedWidths[c][b];this.canvasContext.font=c;let d=this.canvasContext.measureText(b).width;if(d>+c.split("px")[0])d/=2;else if(0==d&&"\x96"!=b){let a=this.getCharacterWidth("\x96");return a}return this.cachedWidths[c][b]=d,d}};
package/plugins/test.js CHANGED
@@ -10,7 +10,9 @@
10
10
  */
11
11
  codeInput.plugins.Test = class extends codeInput.Plugin {
12
12
  constructor() {
13
- super();
13
+ super(["testattr", "test-*"]);
14
+ // Array of observed attributes as parameter
15
+ // Wildcard "*" matches any text
14
16
  }
15
17
  /* Runs before code is highlighted; Params: codeInput element) */
16
18
  beforeHighlight(codeInput) {
@@ -28,11 +30,8 @@ codeInput.plugins.Test = class extends codeInput.Plugin {
28
30
  afterElementsAdded(codeInput) {
29
31
  console.log(codeInput, "after elements added");
30
32
  }
31
- /* Runs when an attribute of a `code-input` is changed (you must add the attribute name to observedAttributes); Params: codeInput element, name attribute name, oldValue previous value of attribute, newValue changed value of attribute) */
33
+ /* Runs when an observed attribute of a `code-input` is changed (you must add the attribute name in the constructor); Params: codeInput element, name attribute name, oldValue previous value of attribute, newValue changed value of attribute) */
32
34
  attributeChanged(codeInput, name, oldValue, newValue) {
33
- if(name == "testattr") {
34
- console.log(codeInput, "testattr:", oldValue, ">", newValue);
35
- }
35
+ console.log(codeInput, name, ":", oldValue, ">", newValue);
36
36
  }
37
- observedAttributes = ["testattr"]
38
37
  }
@@ -1 +1 @@
1
- codeInput.plugins.Test=class extends codeInput.Plugin{constructor(){super()}beforeHighlight(a){console.log(a,"before highlight")}afterHighlight(a){console.log(a,"after highlight")}beforeElementsAdded(a){console.log(a,"before elements added")}afterElementsAdded(a){console.log(a,"after elements added")}attributeChanged(a,b,c,d){"testattr"==b&&console.log(a,"testattr:",c,">",d)}observedAttributes=["testattr"]};
1
+ codeInput.plugins.Test=class extends codeInput.Plugin{constructor(){super(["testattr","test-*"])}beforeHighlight(a){console.log(a,"before highlight")}afterHighlight(a){console.log(a,"after highlight")}beforeElementsAdded(a){console.log(a,"before elements added")}afterElementsAdded(a){console.log(a,"after elements added")}attributeChanged(a,b,c,d){console.log(a,b,":",c,">",d)}};