@webcoder49/code-input 2.6.5 → 2.6.7
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/SECURITY.md +1 -2
- package/code-input.js +75 -17
- package/code-input.min.js +1 -1
- package/docs/_index.md +5 -4
- package/esm/code-input.mjs +75 -17
- package/package.json +1 -1
package/SECURITY.md
CHANGED
|
@@ -3,5 +3,4 @@ If you find a sensitive security vulnerability
|
|
|
3
3
|
in the code-input.js library, please
|
|
4
4
|
contact the maintainer Oliver Geer at
|
|
5
5
|
[security@webcoder49.dev](mailto:security@webcoder49.dev),
|
|
6
|
-
|
|
7
|
-
if you know how to do so.
|
|
6
|
+
after reading [this page with an encryption key](https://oliver.geer.im#email).
|
package/code-input.js
CHANGED
|
@@ -716,7 +716,8 @@ var codeInput = {
|
|
|
716
716
|
// Synchronise attributes to textarea
|
|
717
717
|
for(let i = 0; i < this.attributes.length; i++) {
|
|
718
718
|
let attribute = this.attributes[i].name;
|
|
719
|
-
if (codeInput.textareaSyncAttributes.includes(attribute)
|
|
719
|
+
if (codeInput.textareaSyncAttributes.includes(attribute)
|
|
720
|
+
|| attribute.substring(0, 5) == "aria-") {
|
|
720
721
|
textarea.setAttribute(attribute, this.getAttribute(attribute));
|
|
721
722
|
}
|
|
722
723
|
}
|
|
@@ -726,6 +727,7 @@ var codeInput = {
|
|
|
726
727
|
// Save element internally
|
|
727
728
|
this.textareaElement = textarea;
|
|
728
729
|
this.append(textarea);
|
|
730
|
+
this.setupTextareaSyncEvents(this.textareaElement);
|
|
729
731
|
|
|
730
732
|
// Create result element
|
|
731
733
|
let code = document.createElement("code");
|
|
@@ -831,9 +833,30 @@ var codeInput = {
|
|
|
831
833
|
if (this.templateObject != undefined) {
|
|
832
834
|
// Template registered before loading
|
|
833
835
|
this.classList.add("code-input_registered");
|
|
836
|
+
if (document.readyState === 'loading') {
|
|
837
|
+
// Children not yet present - wait until they are
|
|
838
|
+
window.addEventListener("DOMContentLoaded", this.setup.bind(this))
|
|
839
|
+
} else {
|
|
840
|
+
this.setup();
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// Graceful degradation: make events still work without template being
|
|
845
|
+
// registered
|
|
846
|
+
if (document.readyState === 'loading') {
|
|
834
847
|
// Children not yet present - wait until they are
|
|
835
|
-
window.addEventListener("DOMContentLoaded",
|
|
836
|
-
|
|
848
|
+
window.addEventListener("DOMContentLoaded", () => {
|
|
849
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
850
|
+
if(fallbackTextarea) {
|
|
851
|
+
this.setupTextareaSyncEvents(fallbackTextarea);
|
|
852
|
+
}
|
|
853
|
+
})
|
|
854
|
+
} else {
|
|
855
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
856
|
+
if(fallbackTextarea) {
|
|
857
|
+
this.setupTextareaSyncEvents(fallbackTextarea);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
837
860
|
}
|
|
838
861
|
|
|
839
862
|
mutationObserverCallback(mutationList, observer) {
|
|
@@ -851,7 +874,7 @@ var codeInput = {
|
|
|
851
874
|
if (mutation.attributeName == codeInput.textareaSyncAttributes[i]) {
|
|
852
875
|
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
|
|
853
876
|
}
|
|
854
|
-
|
|
877
|
+
}
|
|
855
878
|
if (mutation.attributeName.substring(0, 5) == "aria-") {
|
|
856
879
|
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
|
|
857
880
|
}
|
|
@@ -859,7 +882,9 @@ var codeInput = {
|
|
|
859
882
|
}
|
|
860
883
|
|
|
861
884
|
disconnectedCallback() {
|
|
862
|
-
this.mutationObserver
|
|
885
|
+
if (this.mutationObserver) {
|
|
886
|
+
this.mutationObserver.disconnect();
|
|
887
|
+
}
|
|
863
888
|
}
|
|
864
889
|
|
|
865
890
|
/**
|
|
@@ -943,12 +968,31 @@ var codeInput = {
|
|
|
943
968
|
|
|
944
969
|
}
|
|
945
970
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
971
|
+
//-------------------------------------------
|
|
972
|
+
//----------- Textarea interface ------------
|
|
973
|
+
//-------------------------------------------
|
|
974
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
|
|
975
|
+
// Attributes defined at codeInput.textareaSyncAttributes
|
|
976
|
+
// Event listener added to pass to code-input element
|
|
951
977
|
|
|
978
|
+
/**
|
|
979
|
+
* Capture all events from textareaSyncEvents triggered on the given textarea
|
|
980
|
+
* element and pass them to the code-input element.
|
|
981
|
+
*/
|
|
982
|
+
setupTextareaSyncEvents(textarea) {
|
|
983
|
+
for(let i = 0; i < codeInput.textareaSyncEvents.length; i++) {
|
|
984
|
+
const evtName = codeInput.textareaSyncEvents[i];
|
|
985
|
+
textarea.addEventListener(evtName, (evt) => {
|
|
986
|
+
if(!evt.bubbles) { // Don't duplicate the callback
|
|
987
|
+
this.dispatchEvent(new evt.constructor(evt.type, evt)); // Thanks to
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// addEventListener and removeEventListener overrides are still used
|
|
994
|
+
// for backwards compatibility - unlike the solution above, they keep
|
|
995
|
+
// the event's isTrusted as true.
|
|
952
996
|
/**
|
|
953
997
|
* @override
|
|
954
998
|
*/
|
|
@@ -969,12 +1013,22 @@ var codeInput = {
|
|
|
969
1013
|
|
|
970
1014
|
if (options === undefined) {
|
|
971
1015
|
if(this.textareaElement == null) {
|
|
1016
|
+
// Unregistered
|
|
1017
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1018
|
+
if(fallbackTextarea) {
|
|
1019
|
+
fallbackTextarea.addEventListener(type, boundCallback);
|
|
1020
|
+
}
|
|
972
1021
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback); });
|
|
973
1022
|
} else {
|
|
974
1023
|
this.textareaElement.addEventListener(type, boundCallback);
|
|
975
1024
|
}
|
|
976
1025
|
} else {
|
|
977
1026
|
if(this.textareaElement == null) {
|
|
1027
|
+
// Unregistered
|
|
1028
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1029
|
+
if(fallbackTextarea) {
|
|
1030
|
+
fallbackTextarea.addEventListener(type, boundCallback, options);
|
|
1031
|
+
}
|
|
978
1032
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback, options); });
|
|
979
1033
|
} else {
|
|
980
1034
|
this.textareaElement.addEventListener(type, boundCallback, options);
|
|
@@ -994,19 +1048,29 @@ var codeInput = {
|
|
|
994
1048
|
* @override
|
|
995
1049
|
*/
|
|
996
1050
|
removeEventListener(type, listener, options = undefined) {
|
|
997
|
-
// Save a copy of the callback where `this` refers to the code-input element
|
|
1051
|
+
// Save a copy of the callback where `this` refers to the code-input element
|
|
998
1052
|
let boundCallback = this.boundEventCallbacks[listener];
|
|
999
1053
|
|
|
1000
1054
|
if (codeInput.textareaSyncEvents.includes(type)) {
|
|
1001
1055
|
// Synchronise with textarea
|
|
1002
1056
|
if (options === undefined) {
|
|
1003
1057
|
if(this.textareaElement == null) {
|
|
1058
|
+
// Unregistered
|
|
1059
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1060
|
+
if(fallbackTextarea) {
|
|
1061
|
+
fallbackTextarea.removeEventListener(type, boundCallback);
|
|
1062
|
+
}
|
|
1004
1063
|
this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback); });
|
|
1005
1064
|
} else {
|
|
1006
1065
|
this.textareaElement.removeEventListener(type, boundCallback);
|
|
1007
1066
|
}
|
|
1008
1067
|
} else {
|
|
1009
1068
|
if(this.textareaElement == null) {
|
|
1069
|
+
// Unregistered
|
|
1070
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1071
|
+
if(fallbackTextarea) {
|
|
1072
|
+
fallbackTextarea.removeEventListener(type, boundCallback, options);
|
|
1073
|
+
}
|
|
1010
1074
|
this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback, options); });
|
|
1011
1075
|
} else {
|
|
1012
1076
|
this.textareaElement.removeEventListener(type, boundCallback, options);
|
|
@@ -1022,12 +1086,6 @@ var codeInput = {
|
|
|
1022
1086
|
}
|
|
1023
1087
|
}
|
|
1024
1088
|
|
|
1025
|
-
//-------------------------------------------
|
|
1026
|
-
//----------- Textarea interface ------------
|
|
1027
|
-
//-------------------------------------------
|
|
1028
|
-
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
|
|
1029
|
-
// Attributes defined at codeInput.textareaSyncAttributes
|
|
1030
|
-
|
|
1031
1089
|
/**
|
|
1032
1090
|
* Get the JavaScript property from the internal textarea
|
|
1033
1091
|
* element, given its name and a defaultValue to return
|
package/code-input.min.js
CHANGED
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
* @license MIT
|
|
10
10
|
*
|
|
11
11
|
* **<https://code-input-js.org>**
|
|
12
|
-
*/"use strict";var codeInput={observedAttributes:["value","placeholder","language","lang","template"],textareaSyncAttributes:["value","min","max","type","pattern","autocomplete","autocorrect","autofocus","cols","dirname","disabled","form","maxlength","minlength","name","placeholder","readonly","required","rows","spellcheck","wrap"],textareaSyncEvents:["change","selectionchange","invalid","input","focus","blur","focusin","focusout"],usedTemplates:{},defaultTemplate:void 0,templateNotYetRegisteredQueue:{},registerTemplate:function(a,b){if(!("string"==typeof a||a instanceof String))throw TypeError(`code-input: Name of template "${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]){const d=codeInput.templateNotYetRegisteredQueue[a][c];d.templateObject=b,d.setup()}if(null==codeInput.defaultTemplate&&(codeInput.defaultTemplate=a,void 0 in codeInput.templateNotYetRegisteredQueue))for(let a in codeInput.templateNotYetRegisteredQueue[void 0]){const c=codeInput.templateNotYetRegisteredQueue[void 0][a];c.templateObject=b,c.setup()}},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 new codeInput.templates.Prism(a,b)},hljs(a,b=[]){return new codeInput.templates.Hljs(a,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){a.forEach(a=>{codeInput.observedAttributes.push(a)})}addTranslations(a,b){for(const c in b)a[c]=b[c]}beforeHighlight(){}afterHighlight(){}beforeElementsAdded(){}afterElementsAdded(){}attributeChanged(){}},CodeInput:class extends HTMLElement{constructor(){super()}templateObject=null;textareaElement=null;preElement=null;codeElement=null;dialogContainerElement=null;static formAssociated=!0;boundEventCallbacks={};pluginEvt(a,b){for(let c in this.templateObject.plugins){let d=this.templateObject.plugins[c];a in d&&(b===void 0?d[a](this):d[a](this,...b))}}needsHighlight=!1;originalAriaDescription;scheduleHighlight(){this.needsHighlight=!0}animateFrame(){this.needsHighlight&&(this.update(),this.needsHighlight=!1),window.requestAnimationFrame(this.animateFrame.bind(this))}update(){let a=this.codeElement,b=this.value;b+="\n",a.innerHTML=this.escapeHtml(b),this.pluginEvt("beforeHighlight"),this.templateObject.includeCodeInputInHighlightFunc?this.templateObject.highlight(a,this):this.templateObject.highlight(a),this.syncSize(),this.pluginEvt("afterHighlight")}syncSize(){this.templateObject.preElementStyled?(this.style.backgroundColor=getComputedStyle(this.preElement).backgroundColor,this.textareaElement.style.height=getComputedStyle(this.preElement).height,this.textareaElement.style.width=getComputedStyle(this.preElement).width):(this.style.backgroundColor=getComputedStyle(this.codeElement).backgroundColor,this.textareaElement.style.height=getComputedStyle(this.codeElement).height,this.textareaElement.style.width=getComputedStyle(this.codeElement).width)}setKeyboardNavInstructions(a,b){this.dialogContainerElement.querySelector(".code-input_keyboard-navigation-instructions").innerText=a,b?this.textareaElement.setAttribute("aria-description",this.originalAriaDescription+". "+a):this.textareaElement.setAttribute("aria-description",a)}escapeHtml(a){return a.replace(/&/g,"&").replace(/</g,"<")}unescapeHtml(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/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.mutationObserver=new MutationObserver(this.mutationObserverCallback.bind(this)),this.mutationObserver.observe(this,{attributes:!0,attributeOldValue:!0}),this.classList.add("code-input_registered"),this.templateObject.preElementStyled&&this.classList.add("code-input_pre-element-styled");const a=this.querySelector("textarea[data-code-input-fallback]");let b,c,d,e,f,g=!1;a&&(a===document.activeElement&&(g=!0),b=a.selectionStart,c=a.selectionEnd,d=a.selectionDirection,e=a.scrollLeft,f=a.scrollTop);let h;if(a){let b=a.getAttributeNames();for(let c=0;c<b.length;c++){const d=b[c];"data-code-input-fallback"!=d&&(this.hasAttribute(d)||this.setAttribute(d,a.getAttribute(d)))}h=a.value,this.innerHTML=this.escapeHtml(h)}else h=this.unescapeHtml(this.innerHTML);h=h||this.getAttribute("value")||"",this.pluginEvt("beforeElementsAdded");const i=this.getAttribute("language")||this.getAttribute("lang"),j=this.getAttribute("placeholder")||i||"";this.initialValue=h;const k=document.createElement("textarea");k.placeholder=j,""!=h&&(k.value=h),k.innerHTML=this.innerHTML,this.hasAttribute("spellcheck")||k.setAttribute("spellcheck","false"),k.setAttribute("tabindex",this.getAttribute("tabindex")||0),this.setAttribute("tabindex",-1),this.originalAriaDescription=this.getAttribute("aria-description")||"Code input field",this.addEventListener("mousedown",()=>{this.classList.add("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("blur",()=>{this.classList.remove("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("focus",()=>{window.setTimeout(()=>{this.syncSize()},0)}),this.innerHTML="";for(let a,b=0;b<this.attributes.length;b++)a=this.attributes[b].name,(codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5))&&k.setAttribute(a,this.getAttribute(a));k.addEventListener("input",()=>{this.value=this.textareaElement.value}),this.textareaElement=k,this.append(k);let l=document.createElement("code"),m=document.createElement("pre");m.setAttribute("aria-hidden","true"),m.setAttribute("tabindex","-1"),m.setAttribute("inert",!0),this.preElement=m,this.codeElement=l,m.append(l),this.append(m),this.templateObject.isCode&&i!=null&&""!=i&&l.classList.add("language-"+i.toLowerCase());let n=document.createElement("div");n.classList.add("code-input_dialog-container"),this.append(n),this.dialogContainerElement=n;let o=document.createElement("div");o.classList.add("code-input_keyboard-navigation-instructions"),n.append(o),this.pluginEvt("afterElementsAdded"),this.dispatchEvent(new CustomEvent("code-input_load")),this.value=h,b!==void 0&&(console.log("sel",b,c,d,"scr",f,e,"foc",g),k.setSelectionRange(b,c,d),k.scrollTo(f,e)),g&&k.focus(),this.animateFrame();const p=new ResizeObserver(()=>{this.syncSize()});p.observe(this.textareaElement),this.classList.add("code-input_loaded")}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}get template(){return this.templateObject}set template(a){}connectedCallback(){this.templateObject=this.getTemplate(),this.templateObject!=null&&(this.classList.add("code-input_registered"),window.addEventListener("DOMContentLoaded",this.setup.bind(this)))}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.textareaSyncAttributes.length;a++)if(b.attributeName==codeInput.textareaSyncAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));if("aria-"==b.attributeName.substring(0,5))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"template":this.templateObject=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.templateObject.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.scheduleHighlight();break;case"lang":case"language":let d=this.codeElement,e=this.textareaElement;if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;null!==b&&(b=b.toLowerCase(),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),e.placeholder==b&&(e.placeholder=c),this.scheduleHighlight();break;default:codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5)?null==c||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=function(a){"function"==typeof b?b(a):b&&b.handleEvent&&b.handleEvent(a)}.bind(this);this.boundEventCallbacks[b]=d,codeInput.textareaSyncEvents.includes(a)?(this.boundEventCallbacks[b]=d,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=void 0){let d=this.boundEventCallbacks[b];codeInput.textareaSyncEvents.includes(a)?c===void 0?null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d)}):this.textareaElement.removeEventListener(a,d):null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d,c)}):this.textareaElement.removeEventListener(a,d,c):c===void 0?super.removeEventListener(a,d):super.removeEventListener(a,d,c)}getTextareaProperty(a,b=void 0){if(this.textareaElement)return this.textareaElement[a];else{const c=this.querySelector("textarea[data-code-input-fallback]");if(c)return c[a];if(void 0===b)throw new Error("Cannot get "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.");return b}}setTextareaProperty(a,b,c=!0){if(this.textareaElement)this.textareaElement[a]=b;else{const d=this.querySelector("textarea[data-code-input-fallback]");if(d)d[a]=b;else{if(!c)return(!1);throw new Error("Cannot set "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.")}}return(!0)}get autocomplete(){return this.getAttribute("autocomplete")}set autocomplete(a){return this.setAttribute("autocomplete",a)}get cols(){return this.getTextareaProperty("cols",+this.getAttribute("cols"))}set cols(a){this.setAttribute("cols",a)}get defaultValue(){return this.initialValue}set defaultValue(a){this.initialValue=a}get textContent(){return this.initialValue}set textContent(a){this.initialValue=a}get dirName(){return this.getAttribute("dirName")||""}set dirName(a){this.setAttribute("dirname",a)}get disabled(){return this.hasAttribute("disabled")}set disabled(a){a?this.setAttribute("disabled",!0):this.removeAttribute("disabled")}get form(){return this.getTextareaProperty("form")}get labels(){return this.getTextareaProperty("labels")}get maxLength(){const a=+this.getAttribute("maxlength");return isNaN(a)?-1:a}set maxLength(a){-1==a?this.removeAttribute("maxlength"):this.setAttribute("maxlength",a)}get minLength(){const a=+this.getAttribute("minlength");return isNaN(a)?-1:a}set minLength(a){-1==a?this.removeAttribute("minlength"):this.setAttribute("minlength",a)}get name(){return this.getAttribute("name")||""}set name(a){this.setAttribute("name",a)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(a){this.setAttribute("placeholder",a)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get required(){return this.hasAttribute("readonly")}set required(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get rows(){return this.getTextareaProperty("rows",+this.getAttribute("rows"))}set rows(a){this.setAttribute("rows",a)}get selectionDirection(){return this.getTextareaProperty("selectionDirection")}set selectionDirection(a){this.setTextareaProperty("selectionDirection",a)}get selectionEnd(){return this.getTextareaProperty("selectionEnd")}set selectionEnd(a){this.setTextareaProperty("selectionEnd",a)}get selectionStart(){return this.getTextareaProperty("selectionStart")}set selectionStart(a){this.setTextareaProperty("selectionStart",a)}get textLength(){return this.value.length}get type(){return"textarea"}get validationMessage(){return this.getTextareaProperty("validationMessage")}get validity(){return this.getTextareaProperty("validationMessage")}get value(){return this.getTextareaProperty("value",this.getAttribute("value")||this.innerHTML)}set value(a){a=a||"",this.setTextareaProperty("value",a,!1)?this.textareaElement&&this.scheduleHighlight():this.innerHTML=a}get willValidate(){return this.getTextareaProperty("willValidate",this.disabled||this.readOnly)}get wrap(){return this.getAttribute("wrap")||""}set wrap(a){this.setAttribute("wrap",a)}getTextareaMethod(a){if(this.textareaElement)return this.textareaElement[a].bind(this.textareaElement);else{const b=this.querySelector("textarea[data-code-input-fallback]");if(b)return b[a].bind(b);throw new Error("Cannot call "+a+" on an unregistered code-input element without a data-code-input-fallback textarea.")}}blur(a={}){this.getTextareaMethod("blur")(a)}checkValidity(){return this.getTextareaMethod("checkValidity")()}focus(a={}){this.getTextareaMethod("focus")(a)}reportValidity(){return this.getTextareaMethod("reportValidity")()}setCustomValidity(a){this.getTextareaMethod("setCustomValidity")(a)}setRangeText(a,b=this.selectionStart,c=this.selectionEnd,d="preserve"){this.getTextareaMethod("setRangeText")(a,b,c,d),this.textareaElement&&this.scheduleHighlight()}setSelectionRange(a,b,c="none"){this.getTextareaMethod("setSelectionRange")(a,b,c)}pluginData={};formResetCallback(){this.value=this.initialValue}}};{class a extends codeInput.Template{constructor(a,b=[],c=!0){super(a.highlightElement,c,!0,!1,b)}}codeInput.templates.Prism=a;class b extends codeInput.Template{constructor(a,b=[],c=!1){super(function(b){b.removeAttribute("data-highlighted"),a.highlightElement(b)},c,!0,!1,b)}}codeInput.templates.Hljs=b}customElements.define("code-input",codeInput.CodeInput);
|
|
12
|
+
*/"use strict";var codeInput={observedAttributes:["value","placeholder","language","lang","template"],textareaSyncAttributes:["value","min","max","type","pattern","autocomplete","autocorrect","autofocus","cols","dirname","disabled","form","maxlength","minlength","name","placeholder","readonly","required","rows","spellcheck","wrap"],textareaSyncEvents:["change","selectionchange","invalid","input","focus","blur","focusin","focusout"],usedTemplates:{},defaultTemplate:void 0,templateNotYetRegisteredQueue:{},registerTemplate:function(a,b){if(!("string"==typeof a||a instanceof String))throw TypeError(`code-input: Name of template "${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]){const d=codeInput.templateNotYetRegisteredQueue[a][c];d.templateObject=b,d.setup()}if(null==codeInput.defaultTemplate&&(codeInput.defaultTemplate=a,void 0 in codeInput.templateNotYetRegisteredQueue))for(let a in codeInput.templateNotYetRegisteredQueue[void 0]){const c=codeInput.templateNotYetRegisteredQueue[void 0][a];c.templateObject=b,c.setup()}},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 new codeInput.templates.Prism(a,b)},hljs(a,b=[]){return new codeInput.templates.Hljs(a,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){a.forEach(a=>{codeInput.observedAttributes.push(a)})}addTranslations(a,b){for(const c in b)a[c]=b[c]}beforeHighlight(){}afterHighlight(){}beforeElementsAdded(){}afterElementsAdded(){}attributeChanged(){}},CodeInput:class extends HTMLElement{constructor(){super()}templateObject=null;textareaElement=null;preElement=null;codeElement=null;dialogContainerElement=null;static formAssociated=!0;boundEventCallbacks={};pluginEvt(a,b){for(let c in this.templateObject.plugins){let d=this.templateObject.plugins[c];a in d&&(b===void 0?d[a](this):d[a](this,...b))}}needsHighlight=!1;originalAriaDescription;scheduleHighlight(){this.needsHighlight=!0}animateFrame(){this.needsHighlight&&(this.update(),this.needsHighlight=!1),window.requestAnimationFrame(this.animateFrame.bind(this))}update(){let a=this.codeElement,b=this.value;b+="\n",a.innerHTML=this.escapeHtml(b),this.pluginEvt("beforeHighlight"),this.templateObject.includeCodeInputInHighlightFunc?this.templateObject.highlight(a,this):this.templateObject.highlight(a),this.syncSize(),this.pluginEvt("afterHighlight")}syncSize(){this.templateObject.preElementStyled?(this.style.backgroundColor=getComputedStyle(this.preElement).backgroundColor,this.textareaElement.style.height=getComputedStyle(this.preElement).height,this.textareaElement.style.width=getComputedStyle(this.preElement).width):(this.style.backgroundColor=getComputedStyle(this.codeElement).backgroundColor,this.textareaElement.style.height=getComputedStyle(this.codeElement).height,this.textareaElement.style.width=getComputedStyle(this.codeElement).width)}setKeyboardNavInstructions(a,b){this.dialogContainerElement.querySelector(".code-input_keyboard-navigation-instructions").innerText=a,b?this.textareaElement.setAttribute("aria-description",this.originalAriaDescription+". "+a):this.textareaElement.setAttribute("aria-description",a)}escapeHtml(a){return a.replace(/&/g,"&").replace(/</g,"<")}unescapeHtml(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/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.mutationObserver=new MutationObserver(this.mutationObserverCallback.bind(this)),this.mutationObserver.observe(this,{attributes:!0,attributeOldValue:!0}),this.classList.add("code-input_registered"),this.templateObject.preElementStyled&&this.classList.add("code-input_pre-element-styled");const a=this.querySelector("textarea[data-code-input-fallback]");let b,c,d,e,f,g=!1;a&&(a===document.activeElement&&(g=!0),b=a.selectionStart,c=a.selectionEnd,d=a.selectionDirection,e=a.scrollLeft,f=a.scrollTop);let h;if(a){let b=a.getAttributeNames();for(let c=0;c<b.length;c++){const d=b[c];"data-code-input-fallback"!=d&&(this.hasAttribute(d)||this.setAttribute(d,a.getAttribute(d)))}h=a.value,this.innerHTML=this.escapeHtml(h)}else h=this.unescapeHtml(this.innerHTML);h=h||this.getAttribute("value")||"",this.pluginEvt("beforeElementsAdded");const i=this.getAttribute("language")||this.getAttribute("lang"),j=this.getAttribute("placeholder")||i||"";this.initialValue=h;const k=document.createElement("textarea");k.placeholder=j,""!=h&&(k.value=h),k.innerHTML=this.innerHTML,this.hasAttribute("spellcheck")||k.setAttribute("spellcheck","false"),k.setAttribute("tabindex",this.getAttribute("tabindex")||0),this.setAttribute("tabindex",-1),this.originalAriaDescription=this.getAttribute("aria-description")||"Code input field",this.addEventListener("mousedown",()=>{this.classList.add("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("blur",()=>{this.classList.remove("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("focus",()=>{window.setTimeout(()=>{this.syncSize()},0)}),this.innerHTML="";for(let a,b=0;b<this.attributes.length;b++)a=this.attributes[b].name,(codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5))&&k.setAttribute(a,this.getAttribute(a));k.addEventListener("input",()=>{this.value=this.textareaElement.value}),this.textareaElement=k,this.append(k),this.setupTextareaSyncEvents(this.textareaElement);let l=document.createElement("code"),m=document.createElement("pre");m.setAttribute("aria-hidden","true"),m.setAttribute("tabindex","-1"),m.setAttribute("inert",!0),this.preElement=m,this.codeElement=l,m.append(l),this.append(m),this.templateObject.isCode&&i!=null&&""!=i&&l.classList.add("language-"+i.toLowerCase());let n=document.createElement("div");n.classList.add("code-input_dialog-container"),this.append(n),this.dialogContainerElement=n;let o=document.createElement("div");o.classList.add("code-input_keyboard-navigation-instructions"),n.append(o),this.pluginEvt("afterElementsAdded"),this.dispatchEvent(new CustomEvent("code-input_load")),this.value=h,b!==void 0&&(console.log("sel",b,c,d,"scr",f,e,"foc",g),k.setSelectionRange(b,c,d),k.scrollTo(f,e)),g&&k.focus(),this.animateFrame();const p=new ResizeObserver(()=>{this.syncSize()});p.observe(this.textareaElement),this.classList.add("code-input_loaded")}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}get template(){return this.templateObject}set template(a){}connectedCallback(){if(this.templateObject=this.getTemplate(),null!=this.templateObject&&(this.classList.add("code-input_registered"),"loading"===document.readyState?window.addEventListener("DOMContentLoaded",this.setup.bind(this)):this.setup()),"loading"===document.readyState)window.addEventListener("DOMContentLoaded",()=>{const a=this.querySelector("textarea[data-code-input-fallback]");a&&this.setupTextareaSyncEvents(a)});else{const a=this.querySelector("textarea[data-code-input-fallback]");a&&this.setupTextareaSyncEvents(a)}}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.textareaSyncAttributes.length;a++)if(b.attributeName==codeInput.textareaSyncAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));if("aria-"==b.attributeName.substring(0,5))return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName))}}disconnectedCallback(){this.mutationObserver&&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"template":this.templateObject=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.templateObject.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.scheduleHighlight();break;case"lang":case"language":let d=this.codeElement,e=this.textareaElement;if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;null!==b&&(b=b.toLowerCase(),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),e.placeholder==b&&(e.placeholder=c),this.scheduleHighlight();break;default:codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5)?null==c||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))})}}setupTextareaSyncEvents(a){for(let b=0;b<codeInput.textareaSyncEvents.length;b++){const c=codeInput.textareaSyncEvents[b];a.addEventListener(c,a=>{a.bubbles||this.dispatchEvent(new a.constructor(a.type,a))})}}addEventListener(a,b,c=void 0){let d=function(a){"function"==typeof b?b(a):b&&b.handleEvent&&b.handleEvent(a)}.bind(this);if(this.boundEventCallbacks[b]=d,!codeInput.textareaSyncEvents.includes(a))void 0===c?super.addEventListener(a,d):super.addEventListener(a,d,c);else if(this.boundEventCallbacks[b]=d,void 0===c){if(null==this.textareaElement){const b=this.querySelector("textarea[data-code-input-fallback]");b&&b.addEventListener(a,d),this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d)})}else this.textareaElement.addEventListener(a,d);}else if(null==this.textareaElement){const b=this.querySelector("textarea[data-code-input-fallback]");b&&b.addEventListener(a,d,c),this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d,c)})}else this.textareaElement.addEventListener(a,d,c)}removeEventListener(a,b,c=void 0){let d=this.boundEventCallbacks[b];if(!codeInput.textareaSyncEvents.includes(a))void 0===c?super.removeEventListener(a,d):super.removeEventListener(a,d,c);else if(void 0===c){if(null==this.textareaElement){const b=this.querySelector("textarea[data-code-input-fallback]");b&&b.removeEventListener(a,d),this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d)})}else this.textareaElement.removeEventListener(a,d);}else if(null==this.textareaElement){const b=this.querySelector("textarea[data-code-input-fallback]");b&&b.removeEventListener(a,d,c),this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d,c)})}else this.textareaElement.removeEventListener(a,d,c)}getTextareaProperty(a,b=void 0){if(this.textareaElement)return this.textareaElement[a];else{const c=this.querySelector("textarea[data-code-input-fallback]");if(c)return c[a];if(void 0===b)throw new Error("Cannot get "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.");return b}}setTextareaProperty(a,b,c=!0){if(this.textareaElement)this.textareaElement[a]=b;else{const d=this.querySelector("textarea[data-code-input-fallback]");if(d)d[a]=b;else{if(!c)return(!1);throw new Error("Cannot set "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.")}}return(!0)}get autocomplete(){return this.getAttribute("autocomplete")}set autocomplete(a){return this.setAttribute("autocomplete",a)}get cols(){return this.getTextareaProperty("cols",+this.getAttribute("cols"))}set cols(a){this.setAttribute("cols",a)}get defaultValue(){return this.initialValue}set defaultValue(a){this.initialValue=a}get textContent(){return this.initialValue}set textContent(a){this.initialValue=a}get dirName(){return this.getAttribute("dirName")||""}set dirName(a){this.setAttribute("dirname",a)}get disabled(){return this.hasAttribute("disabled")}set disabled(a){a?this.setAttribute("disabled",!0):this.removeAttribute("disabled")}get form(){return this.getTextareaProperty("form")}get labels(){return this.getTextareaProperty("labels")}get maxLength(){const a=+this.getAttribute("maxlength");return isNaN(a)?-1:a}set maxLength(a){-1==a?this.removeAttribute("maxlength"):this.setAttribute("maxlength",a)}get minLength(){const a=+this.getAttribute("minlength");return isNaN(a)?-1:a}set minLength(a){-1==a?this.removeAttribute("minlength"):this.setAttribute("minlength",a)}get name(){return this.getAttribute("name")||""}set name(a){this.setAttribute("name",a)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(a){this.setAttribute("placeholder",a)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get required(){return this.hasAttribute("readonly")}set required(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get rows(){return this.getTextareaProperty("rows",+this.getAttribute("rows"))}set rows(a){this.setAttribute("rows",a)}get selectionDirection(){return this.getTextareaProperty("selectionDirection")}set selectionDirection(a){this.setTextareaProperty("selectionDirection",a)}get selectionEnd(){return this.getTextareaProperty("selectionEnd")}set selectionEnd(a){this.setTextareaProperty("selectionEnd",a)}get selectionStart(){return this.getTextareaProperty("selectionStart")}set selectionStart(a){this.setTextareaProperty("selectionStart",a)}get textLength(){return this.value.length}get type(){return"textarea"}get validationMessage(){return this.getTextareaProperty("validationMessage")}get validity(){return this.getTextareaProperty("validationMessage")}get value(){return this.getTextareaProperty("value",this.getAttribute("value")||this.innerHTML)}set value(a){a=a||"",this.setTextareaProperty("value",a,!1)?this.textareaElement&&this.scheduleHighlight():this.innerHTML=a}get willValidate(){return this.getTextareaProperty("willValidate",this.disabled||this.readOnly)}get wrap(){return this.getAttribute("wrap")||""}set wrap(a){this.setAttribute("wrap",a)}getTextareaMethod(a){if(this.textareaElement)return this.textareaElement[a].bind(this.textareaElement);else{const b=this.querySelector("textarea[data-code-input-fallback]");if(b)return b[a].bind(b);throw new Error("Cannot call "+a+" on an unregistered code-input element without a data-code-input-fallback textarea.")}}blur(a={}){this.getTextareaMethod("blur")(a)}checkValidity(){return this.getTextareaMethod("checkValidity")()}focus(a={}){this.getTextareaMethod("focus")(a)}reportValidity(){return this.getTextareaMethod("reportValidity")()}setCustomValidity(a){this.getTextareaMethod("setCustomValidity")(a)}setRangeText(a,b=this.selectionStart,c=this.selectionEnd,d="preserve"){this.getTextareaMethod("setRangeText")(a,b,c,d),this.textareaElement&&this.scheduleHighlight()}setSelectionRange(a,b,c="none"){this.getTextareaMethod("setSelectionRange")(a,b,c)}pluginData={};formResetCallback(){this.value=this.initialValue}}};{class a extends codeInput.Template{constructor(a,b=[],c=!0){super(a.highlightElement,c,!0,!1,b)}}codeInput.templates.Prism=a;class b extends codeInput.Template{constructor(a,b=[],c=!1){super(function(b){b.removeAttribute("data-highlighted"),a.highlightElement(b)},c,!0,!1,b)}}codeInput.templates.Hljs=b}customElements.define("code-input",codeInput.CodeInput);
|
package/docs/_index.md
CHANGED
|
@@ -5,12 +5,13 @@ title = 'Flexible Syntax Highlighted Editable Textareas'
|
|
|
5
5
|
# An <mark>editable</mark> `<textarea>` that supports *any* <mark>syntax highlighting</mark> algorithm, for code or something else. [Also, added plugins.](plugins)
|
|
6
6
|
|
|
7
7
|
Aiming to be [more <mark>flexible</mark>, <mark>lightweight</mark>,
|
|
8
|
-
<mark>modular</mark>,
|
|
9
|
-
<mark>
|
|
8
|
+
<mark>modular</mark>,
|
|
9
|
+
<mark>accessible</mark>, <mark>progressively enhanced</mark> and
|
|
10
|
+
<mark>standards-based</mark> than the alternatives](#features), we support
|
|
10
11
|
[HTML forms](interface/forms), the [`<textarea>` JavaScript interface](interface/js), more languages and
|
|
11
12
|
more use cases.
|
|
12
13
|
|
|
13
|
-
*code-input.js is free, libre, open source software under the MIT (AKA Expat) license.* **Download it [from the Git repository](https://github.com/WebCoder49/code-input/tree/v2.6.
|
|
14
|
+
*code-input.js is free, libre, open source software under the MIT (AKA Expat) license.* **Download it [from the Git repository](https://github.com/WebCoder49/code-input/tree/v2.6.7), [in a ZIP archive](/release/code-input-js-v2.6.7.zip), [in a TAR.GZ archive](/release/code-input-js-v2.6.7.tar.gz), or from `@webcoder49/code-input` on the NPM registry ([Yarn](https://yarnpkg.com/package?name=@webcoder49/code-input), [NPM](https://npmjs.com/package/@webcoder49/code-input), etc.).**
|
|
14
15
|
|
|
15
16
|
## Get Started with a Demo
|
|
16
17
|
|
|
@@ -312,6 +313,6 @@ something like [CodeMirror](https://codemirror.net/),
|
|
|
312
313
|
|
|
313
314
|
## Contribute Bug Reports / Code / Docs {#contributing}
|
|
314
315
|
|
|
315
|
-
🎉 code-input.js is collaboratively developed by many people, which is what keeps it going strong.
|
|
316
|
+
🎉 code-input.js is collaboratively developed by many people, which is what keeps it going strong. Many have reported bugs and suggestions, and [10 people (see them on GitHub)](https://github.com/WebCoder49/code-input/graphs/contributors) have contributed code or documentation directly. If you have found a bug, would like to help with the code or documentation, or have additional suggestions, for plugins or core functionality, [please look at GitHub](https://github.com/WebCoder49/code-input/tree/main/CONTRIBUTING.md) or [get in touch via email so I can add it for you](mailto:code-input-js@webcoder49.dev). **Found a security vulnerability? [Please use this email address](mailto:security@webcoder49.dev), after reading ([this page with an encryption key](https://oliver.geer.im/#email)).**
|
|
316
317
|
|
|
317
318
|
*I'm looking into mirroring code-input.js onto Codeberg as well as GitHub for more flexibility and freedom - if you have ideas for this please get in touch!*
|
package/esm/code-input.mjs
CHANGED
|
@@ -614,7 +614,8 @@ var codeInput = {
|
|
|
614
614
|
// Synchronise attributes to textarea
|
|
615
615
|
for(let i = 0; i < this.attributes.length; i++) {
|
|
616
616
|
let attribute = this.attributes[i].name;
|
|
617
|
-
if (codeInput.textareaSyncAttributes.includes(attribute)
|
|
617
|
+
if (codeInput.textareaSyncAttributes.includes(attribute)
|
|
618
|
+
|| attribute.substring(0, 5) == "aria-") {
|
|
618
619
|
textarea.setAttribute(attribute, this.getAttribute(attribute));
|
|
619
620
|
}
|
|
620
621
|
}
|
|
@@ -624,6 +625,7 @@ var codeInput = {
|
|
|
624
625
|
// Save element internally
|
|
625
626
|
this.textareaElement = textarea;
|
|
626
627
|
this.append(textarea);
|
|
628
|
+
this.setupTextareaSyncEvents(this.textareaElement);
|
|
627
629
|
|
|
628
630
|
// Create result element
|
|
629
631
|
let code = document.createElement("code");
|
|
@@ -729,9 +731,30 @@ var codeInput = {
|
|
|
729
731
|
if (this.templateObject != undefined) {
|
|
730
732
|
// Template registered before loading
|
|
731
733
|
this.classList.add("code-input_registered");
|
|
734
|
+
if (document.readyState === 'loading') {
|
|
735
|
+
// Children not yet present - wait until they are
|
|
736
|
+
window.addEventListener("DOMContentLoaded", this.setup.bind(this))
|
|
737
|
+
} else {
|
|
738
|
+
this.setup();
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Graceful degradation: make events still work without template being
|
|
743
|
+
// registered
|
|
744
|
+
if (document.readyState === 'loading') {
|
|
732
745
|
// Children not yet present - wait until they are
|
|
733
|
-
window.addEventListener("DOMContentLoaded",
|
|
734
|
-
|
|
746
|
+
window.addEventListener("DOMContentLoaded", () => {
|
|
747
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
748
|
+
if(fallbackTextarea) {
|
|
749
|
+
this.setupTextareaSyncEvents(fallbackTextarea);
|
|
750
|
+
}
|
|
751
|
+
})
|
|
752
|
+
} else {
|
|
753
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
754
|
+
if(fallbackTextarea) {
|
|
755
|
+
this.setupTextareaSyncEvents(fallbackTextarea);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
735
758
|
}
|
|
736
759
|
|
|
737
760
|
mutationObserverCallback(mutationList, observer) {
|
|
@@ -749,7 +772,7 @@ var codeInput = {
|
|
|
749
772
|
if (mutation.attributeName == codeInput.textareaSyncAttributes[i]) {
|
|
750
773
|
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
|
|
751
774
|
}
|
|
752
|
-
|
|
775
|
+
}
|
|
753
776
|
if (mutation.attributeName.substring(0, 5) == "aria-") {
|
|
754
777
|
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
|
|
755
778
|
}
|
|
@@ -757,7 +780,9 @@ var codeInput = {
|
|
|
757
780
|
}
|
|
758
781
|
|
|
759
782
|
disconnectedCallback() {
|
|
760
|
-
this.mutationObserver
|
|
783
|
+
if (this.mutationObserver) {
|
|
784
|
+
this.mutationObserver.disconnect();
|
|
785
|
+
}
|
|
761
786
|
}
|
|
762
787
|
|
|
763
788
|
/**
|
|
@@ -841,12 +866,31 @@ var codeInput = {
|
|
|
841
866
|
|
|
842
867
|
}
|
|
843
868
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
869
|
+
//-------------------------------------------
|
|
870
|
+
//----------- Textarea interface ------------
|
|
871
|
+
//-------------------------------------------
|
|
872
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
|
|
873
|
+
// Attributes defined at codeInput.textareaSyncAttributes
|
|
874
|
+
// Event listener added to pass to code-input element
|
|
849
875
|
|
|
876
|
+
/**
|
|
877
|
+
* Capture all events from textareaSyncEvents triggered on the given textarea
|
|
878
|
+
* element and pass them to the code-input element.
|
|
879
|
+
*/
|
|
880
|
+
setupTextareaSyncEvents(textarea) {
|
|
881
|
+
for(let i = 0; i < codeInput.textareaSyncEvents.length; i++) {
|
|
882
|
+
const evtName = codeInput.textareaSyncEvents[i];
|
|
883
|
+
textarea.addEventListener(evtName, (evt) => {
|
|
884
|
+
if(!evt.bubbles) { // Don't duplicate the callback
|
|
885
|
+
this.dispatchEvent(new evt.constructor(evt.type, evt)); // Thanks to
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// addEventListener and removeEventListener overrides are still used
|
|
892
|
+
// for backwards compatibility - unlike the solution above, they keep
|
|
893
|
+
// the event's isTrusted as true.
|
|
850
894
|
/**
|
|
851
895
|
* @override
|
|
852
896
|
*/
|
|
@@ -867,12 +911,22 @@ var codeInput = {
|
|
|
867
911
|
|
|
868
912
|
if (options === undefined) {
|
|
869
913
|
if(this.textareaElement == null) {
|
|
914
|
+
// Unregistered
|
|
915
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
916
|
+
if(fallbackTextarea) {
|
|
917
|
+
fallbackTextarea.addEventListener(type, boundCallback);
|
|
918
|
+
}
|
|
870
919
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback); });
|
|
871
920
|
} else {
|
|
872
921
|
this.textareaElement.addEventListener(type, boundCallback);
|
|
873
922
|
}
|
|
874
923
|
} else {
|
|
875
924
|
if(this.textareaElement == null) {
|
|
925
|
+
// Unregistered
|
|
926
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
927
|
+
if(fallbackTextarea) {
|
|
928
|
+
fallbackTextarea.addEventListener(type, boundCallback, options);
|
|
929
|
+
}
|
|
876
930
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback, options); });
|
|
877
931
|
} else {
|
|
878
932
|
this.textareaElement.addEventListener(type, boundCallback, options);
|
|
@@ -892,19 +946,29 @@ var codeInput = {
|
|
|
892
946
|
* @override
|
|
893
947
|
*/
|
|
894
948
|
removeEventListener(type, listener, options = undefined) {
|
|
895
|
-
// Save a copy of the callback where `this` refers to the code-input element
|
|
949
|
+
// Save a copy of the callback where `this` refers to the code-input element
|
|
896
950
|
let boundCallback = this.boundEventCallbacks[listener];
|
|
897
951
|
|
|
898
952
|
if (codeInput.textareaSyncEvents.includes(type)) {
|
|
899
953
|
// Synchronise with textarea
|
|
900
954
|
if (options === undefined) {
|
|
901
955
|
if(this.textareaElement == null) {
|
|
956
|
+
// Unregistered
|
|
957
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
958
|
+
if(fallbackTextarea) {
|
|
959
|
+
fallbackTextarea.removeEventListener(type, boundCallback);
|
|
960
|
+
}
|
|
902
961
|
this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback); });
|
|
903
962
|
} else {
|
|
904
963
|
this.textareaElement.removeEventListener(type, boundCallback);
|
|
905
964
|
}
|
|
906
965
|
} else {
|
|
907
966
|
if(this.textareaElement == null) {
|
|
967
|
+
// Unregistered
|
|
968
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
969
|
+
if(fallbackTextarea) {
|
|
970
|
+
fallbackTextarea.removeEventListener(type, boundCallback, options);
|
|
971
|
+
}
|
|
908
972
|
this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback, options); });
|
|
909
973
|
} else {
|
|
910
974
|
this.textareaElement.removeEventListener(type, boundCallback, options);
|
|
@@ -920,12 +984,6 @@ var codeInput = {
|
|
|
920
984
|
}
|
|
921
985
|
}
|
|
922
986
|
|
|
923
|
-
//-------------------------------------------
|
|
924
|
-
//----------- Textarea interface ------------
|
|
925
|
-
//-------------------------------------------
|
|
926
|
-
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
|
|
927
|
-
// Attributes defined at codeInput.textareaSyncAttributes
|
|
928
|
-
|
|
929
987
|
/**
|
|
930
988
|
* Get the JavaScript property from the internal textarea
|
|
931
989
|
* element, given its name and a defaultValue to return
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webcoder49/code-input",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.7",
|
|
4
4
|
"description": "An editable <textarea> that supports *any* syntax highlighting algorithm, for code or something else. Also, added plugins.",
|
|
5
5
|
"browser": "code-input.js",
|
|
6
6
|
"exports": {
|