@webcoder49/code-input 2.6.6 → 2.6.8
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.d.ts +1 -1
- package/code-input.js +67 -16
- package/code-input.min.js +1 -1
- package/docs/_index.md +2 -2
- package/esm/code-input.mjs +67 -16
- package/esm/plugins/indent.d.mts +1 -1
- 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.d.ts
CHANGED
|
@@ -214,7 +214,7 @@ export namespace plugins {
|
|
|
214
214
|
* @param {boolean} escTabToChangeFocus Whether pressing the Escape key before (Shift+)Tab should make this keypress focus on a different element (Tab's default behaviour). You should always either enable this or use this plugin's disableTabIndentation and enableTabIndentation methods linked to other keyboard shortcuts, for accessibility.
|
|
215
215
|
* @param {Object} instructionTranslations: user interface string keys mapped to translated versions for localisation. Look at the go-to-line.js source code for the English text.
|
|
216
216
|
*/
|
|
217
|
-
constructor(defaultSpaces?: boolean, numSpaces?: Number, bracketPairs?: Object, escTabToChangeFocus?: boolean,
|
|
217
|
+
constructor(defaultSpaces?: boolean, numSpaces?: Number, bracketPairs?: Object, escTabToChangeFocus?: boolean, instructionTranslations?: {
|
|
218
218
|
tabForIndentation?: string;
|
|
219
219
|
tabForNavigation?: string;
|
|
220
220
|
});
|
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");
|
|
@@ -765,7 +767,6 @@ var codeInput = {
|
|
|
765
767
|
// Update with fallback textarea's state so can keep editing
|
|
766
768
|
// if loaded slowly
|
|
767
769
|
if(fallbackSelectionStart !== undefined) {
|
|
768
|
-
console.log("sel", fallbackSelectionStart, fallbackSelectionEnd, fallbackSelectionDirection, "scr", fallbackScrollTop, fallbackScrollLeft, "foc", fallbackFocused);
|
|
769
770
|
textarea.setSelectionRange(fallbackSelectionStart, fallbackSelectionEnd, fallbackSelectionDirection);
|
|
770
771
|
textarea.scrollTo(fallbackScrollTop, fallbackScrollLeft);
|
|
771
772
|
}
|
|
@@ -837,7 +838,24 @@ var codeInput = {
|
|
|
837
838
|
} else {
|
|
838
839
|
this.setup();
|
|
839
840
|
}
|
|
840
|
-
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// Graceful degradation: make events still work without template being
|
|
844
|
+
// registered
|
|
845
|
+
if (document.readyState === 'loading') {
|
|
846
|
+
// Children not yet present - wait until they are
|
|
847
|
+
window.addEventListener("DOMContentLoaded", () => {
|
|
848
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
849
|
+
if(fallbackTextarea) {
|
|
850
|
+
this.setupTextareaSyncEvents(fallbackTextarea);
|
|
851
|
+
}
|
|
852
|
+
})
|
|
853
|
+
} else {
|
|
854
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
855
|
+
if(fallbackTextarea) {
|
|
856
|
+
this.setupTextareaSyncEvents(fallbackTextarea);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
841
859
|
}
|
|
842
860
|
|
|
843
861
|
mutationObserverCallback(mutationList, observer) {
|
|
@@ -855,7 +873,7 @@ var codeInput = {
|
|
|
855
873
|
if (mutation.attributeName == codeInput.textareaSyncAttributes[i]) {
|
|
856
874
|
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
|
|
857
875
|
}
|
|
858
|
-
|
|
876
|
+
}
|
|
859
877
|
if (mutation.attributeName.substring(0, 5) == "aria-") {
|
|
860
878
|
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
|
|
861
879
|
}
|
|
@@ -949,12 +967,31 @@ var codeInput = {
|
|
|
949
967
|
|
|
950
968
|
}
|
|
951
969
|
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
970
|
+
//-------------------------------------------
|
|
971
|
+
//----------- Textarea interface ------------
|
|
972
|
+
//-------------------------------------------
|
|
973
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
|
|
974
|
+
// Attributes defined at codeInput.textareaSyncAttributes
|
|
975
|
+
// Event listener added to pass to code-input element
|
|
957
976
|
|
|
977
|
+
/**
|
|
978
|
+
* Capture all events from textareaSyncEvents triggered on the given textarea
|
|
979
|
+
* element and pass them to the code-input element.
|
|
980
|
+
*/
|
|
981
|
+
setupTextareaSyncEvents(textarea) {
|
|
982
|
+
for(let i = 0; i < codeInput.textareaSyncEvents.length; i++) {
|
|
983
|
+
const evtName = codeInput.textareaSyncEvents[i];
|
|
984
|
+
textarea.addEventListener(evtName, (evt) => {
|
|
985
|
+
if(!evt.bubbles) { // Don't duplicate the callback
|
|
986
|
+
this.dispatchEvent(new evt.constructor(evt.type, evt)); // Thanks to
|
|
987
|
+
}
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// addEventListener and removeEventListener overrides are still used
|
|
993
|
+
// for backwards compatibility - unlike the solution above, they keep
|
|
994
|
+
// the event's isTrusted as true.
|
|
958
995
|
/**
|
|
959
996
|
* @override
|
|
960
997
|
*/
|
|
@@ -975,12 +1012,22 @@ var codeInput = {
|
|
|
975
1012
|
|
|
976
1013
|
if (options === undefined) {
|
|
977
1014
|
if(this.textareaElement == null) {
|
|
1015
|
+
// Unregistered
|
|
1016
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1017
|
+
if(fallbackTextarea) {
|
|
1018
|
+
fallbackTextarea.addEventListener(type, boundCallback);
|
|
1019
|
+
}
|
|
978
1020
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback); });
|
|
979
1021
|
} else {
|
|
980
1022
|
this.textareaElement.addEventListener(type, boundCallback);
|
|
981
1023
|
}
|
|
982
1024
|
} else {
|
|
983
1025
|
if(this.textareaElement == null) {
|
|
1026
|
+
// Unregistered
|
|
1027
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1028
|
+
if(fallbackTextarea) {
|
|
1029
|
+
fallbackTextarea.addEventListener(type, boundCallback, options);
|
|
1030
|
+
}
|
|
984
1031
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback, options); });
|
|
985
1032
|
} else {
|
|
986
1033
|
this.textareaElement.addEventListener(type, boundCallback, options);
|
|
@@ -1000,19 +1047,29 @@ var codeInput = {
|
|
|
1000
1047
|
* @override
|
|
1001
1048
|
*/
|
|
1002
1049
|
removeEventListener(type, listener, options = undefined) {
|
|
1003
|
-
// Save a copy of the callback where `this` refers to the code-input element
|
|
1050
|
+
// Save a copy of the callback where `this` refers to the code-input element
|
|
1004
1051
|
let boundCallback = this.boundEventCallbacks[listener];
|
|
1005
1052
|
|
|
1006
1053
|
if (codeInput.textareaSyncEvents.includes(type)) {
|
|
1007
1054
|
// Synchronise with textarea
|
|
1008
1055
|
if (options === undefined) {
|
|
1009
1056
|
if(this.textareaElement == null) {
|
|
1057
|
+
// Unregistered
|
|
1058
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1059
|
+
if(fallbackTextarea) {
|
|
1060
|
+
fallbackTextarea.removeEventListener(type, boundCallback);
|
|
1061
|
+
}
|
|
1010
1062
|
this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback); });
|
|
1011
1063
|
} else {
|
|
1012
1064
|
this.textareaElement.removeEventListener(type, boundCallback);
|
|
1013
1065
|
}
|
|
1014
1066
|
} else {
|
|
1015
1067
|
if(this.textareaElement == null) {
|
|
1068
|
+
// Unregistered
|
|
1069
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1070
|
+
if(fallbackTextarea) {
|
|
1071
|
+
fallbackTextarea.removeEventListener(type, boundCallback, options);
|
|
1072
|
+
}
|
|
1016
1073
|
this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback, options); });
|
|
1017
1074
|
} else {
|
|
1018
1075
|
this.textareaElement.removeEventListener(type, boundCallback, options);
|
|
@@ -1028,12 +1085,6 @@ var codeInput = {
|
|
|
1028
1085
|
}
|
|
1029
1086
|
}
|
|
1030
1087
|
|
|
1031
|
-
//-------------------------------------------
|
|
1032
|
-
//----------- Textarea interface ------------
|
|
1033
|
-
//-------------------------------------------
|
|
1034
|
-
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
|
|
1035
|
-
// Attributes defined at codeInput.textareaSyncAttributes
|
|
1036
|
-
|
|
1037
1088
|
/**
|
|
1038
1089
|
* Get the JavaScript property from the internal textarea
|
|
1039
1090
|
* 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"),"loading"===document.readyState?window.addEventListener("DOMContentLoaded",this.setup.bind(this)):this.setup())}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))})}}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&&(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
|
@@ -11,7 +11,7 @@ Aiming to be [more <mark>flexible</mark>, <mark>lightweight</mark>,
|
|
|
11
11
|
[HTML forms](interface/forms), the [`<textarea>` JavaScript interface](interface/js), more languages and
|
|
12
12
|
more use cases.
|
|
13
13
|
|
|
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.
|
|
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.8), [in a ZIP archive](/release/code-input-js-v2.6.8.zip), [in a TAR.GZ archive](/release/code-input-js-v2.6.8.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.).**
|
|
15
15
|
|
|
16
16
|
## Get Started with a Demo
|
|
17
17
|
|
|
@@ -313,6 +313,6 @@ something like [CodeMirror](https://codemirror.net/),
|
|
|
313
313
|
|
|
314
314
|
## Contribute Bug Reports / Code / Docs {#contributing}
|
|
315
315
|
|
|
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)
|
|
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)).**
|
|
317
317
|
|
|
318
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");
|
|
@@ -663,7 +665,6 @@ var codeInput = {
|
|
|
663
665
|
// Update with fallback textarea's state so can keep editing
|
|
664
666
|
// if loaded slowly
|
|
665
667
|
if(fallbackSelectionStart !== undefined) {
|
|
666
|
-
console.log("sel", fallbackSelectionStart, fallbackSelectionEnd, fallbackSelectionDirection, "scr", fallbackScrollTop, fallbackScrollLeft, "foc", fallbackFocused);
|
|
667
668
|
textarea.setSelectionRange(fallbackSelectionStart, fallbackSelectionEnd, fallbackSelectionDirection);
|
|
668
669
|
textarea.scrollTo(fallbackScrollTop, fallbackScrollLeft);
|
|
669
670
|
}
|
|
@@ -735,7 +736,24 @@ var codeInput = {
|
|
|
735
736
|
} else {
|
|
736
737
|
this.setup();
|
|
737
738
|
}
|
|
738
|
-
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// Graceful degradation: make events still work without template being
|
|
742
|
+
// registered
|
|
743
|
+
if (document.readyState === 'loading') {
|
|
744
|
+
// Children not yet present - wait until they are
|
|
745
|
+
window.addEventListener("DOMContentLoaded", () => {
|
|
746
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
747
|
+
if(fallbackTextarea) {
|
|
748
|
+
this.setupTextareaSyncEvents(fallbackTextarea);
|
|
749
|
+
}
|
|
750
|
+
})
|
|
751
|
+
} else {
|
|
752
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
753
|
+
if(fallbackTextarea) {
|
|
754
|
+
this.setupTextareaSyncEvents(fallbackTextarea);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
739
757
|
}
|
|
740
758
|
|
|
741
759
|
mutationObserverCallback(mutationList, observer) {
|
|
@@ -753,7 +771,7 @@ var codeInput = {
|
|
|
753
771
|
if (mutation.attributeName == codeInput.textareaSyncAttributes[i]) {
|
|
754
772
|
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
|
|
755
773
|
}
|
|
756
|
-
|
|
774
|
+
}
|
|
757
775
|
if (mutation.attributeName.substring(0, 5) == "aria-") {
|
|
758
776
|
return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
|
|
759
777
|
}
|
|
@@ -847,12 +865,31 @@ var codeInput = {
|
|
|
847
865
|
|
|
848
866
|
}
|
|
849
867
|
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
868
|
+
//-------------------------------------------
|
|
869
|
+
//----------- Textarea interface ------------
|
|
870
|
+
//-------------------------------------------
|
|
871
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
|
|
872
|
+
// Attributes defined at codeInput.textareaSyncAttributes
|
|
873
|
+
// Event listener added to pass to code-input element
|
|
855
874
|
|
|
875
|
+
/**
|
|
876
|
+
* Capture all events from textareaSyncEvents triggered on the given textarea
|
|
877
|
+
* element and pass them to the code-input element.
|
|
878
|
+
*/
|
|
879
|
+
setupTextareaSyncEvents(textarea) {
|
|
880
|
+
for(let i = 0; i < codeInput.textareaSyncEvents.length; i++) {
|
|
881
|
+
const evtName = codeInput.textareaSyncEvents[i];
|
|
882
|
+
textarea.addEventListener(evtName, (evt) => {
|
|
883
|
+
if(!evt.bubbles) { // Don't duplicate the callback
|
|
884
|
+
this.dispatchEvent(new evt.constructor(evt.type, evt)); // Thanks to
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// addEventListener and removeEventListener overrides are still used
|
|
891
|
+
// for backwards compatibility - unlike the solution above, they keep
|
|
892
|
+
// the event's isTrusted as true.
|
|
856
893
|
/**
|
|
857
894
|
* @override
|
|
858
895
|
*/
|
|
@@ -873,12 +910,22 @@ var codeInput = {
|
|
|
873
910
|
|
|
874
911
|
if (options === undefined) {
|
|
875
912
|
if(this.textareaElement == null) {
|
|
913
|
+
// Unregistered
|
|
914
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
915
|
+
if(fallbackTextarea) {
|
|
916
|
+
fallbackTextarea.addEventListener(type, boundCallback);
|
|
917
|
+
}
|
|
876
918
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback); });
|
|
877
919
|
} else {
|
|
878
920
|
this.textareaElement.addEventListener(type, boundCallback);
|
|
879
921
|
}
|
|
880
922
|
} else {
|
|
881
923
|
if(this.textareaElement == null) {
|
|
924
|
+
// Unregistered
|
|
925
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
926
|
+
if(fallbackTextarea) {
|
|
927
|
+
fallbackTextarea.addEventListener(type, boundCallback, options);
|
|
928
|
+
}
|
|
882
929
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback, options); });
|
|
883
930
|
} else {
|
|
884
931
|
this.textareaElement.addEventListener(type, boundCallback, options);
|
|
@@ -898,19 +945,29 @@ var codeInput = {
|
|
|
898
945
|
* @override
|
|
899
946
|
*/
|
|
900
947
|
removeEventListener(type, listener, options = undefined) {
|
|
901
|
-
// Save a copy of the callback where `this` refers to the code-input element
|
|
948
|
+
// Save a copy of the callback where `this` refers to the code-input element
|
|
902
949
|
let boundCallback = this.boundEventCallbacks[listener];
|
|
903
950
|
|
|
904
951
|
if (codeInput.textareaSyncEvents.includes(type)) {
|
|
905
952
|
// Synchronise with textarea
|
|
906
953
|
if (options === undefined) {
|
|
907
954
|
if(this.textareaElement == null) {
|
|
955
|
+
// Unregistered
|
|
956
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
957
|
+
if(fallbackTextarea) {
|
|
958
|
+
fallbackTextarea.removeEventListener(type, boundCallback);
|
|
959
|
+
}
|
|
908
960
|
this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback); });
|
|
909
961
|
} else {
|
|
910
962
|
this.textareaElement.removeEventListener(type, boundCallback);
|
|
911
963
|
}
|
|
912
964
|
} else {
|
|
913
965
|
if(this.textareaElement == null) {
|
|
966
|
+
// Unregistered
|
|
967
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
968
|
+
if(fallbackTextarea) {
|
|
969
|
+
fallbackTextarea.removeEventListener(type, boundCallback, options);
|
|
970
|
+
}
|
|
914
971
|
this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback, options); });
|
|
915
972
|
} else {
|
|
916
973
|
this.textareaElement.removeEventListener(type, boundCallback, options);
|
|
@@ -926,12 +983,6 @@ var codeInput = {
|
|
|
926
983
|
}
|
|
927
984
|
}
|
|
928
985
|
|
|
929
|
-
//-------------------------------------------
|
|
930
|
-
//----------- Textarea interface ------------
|
|
931
|
-
//-------------------------------------------
|
|
932
|
-
// See https://developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
|
|
933
|
-
// Attributes defined at codeInput.textareaSyncAttributes
|
|
934
|
-
|
|
935
986
|
/**
|
|
936
987
|
* Get the JavaScript property from the internal textarea
|
|
937
988
|
* element, given its name and a defaultValue to return
|
package/esm/plugins/indent.d.mts
CHANGED
|
@@ -15,7 +15,7 @@ import { Plugin, CodeInput } from "../code-input.d.mts";
|
|
|
15
15
|
* @param {boolean} escTabToChangeFocus Whether pressing the Escape key before (Shift+)Tab should make this keypress focus on a different element (Tab's default behaviour). You should always either enable this or use this plugin's disableTabIndentation and enableTabIndentation methods linked to other keyboard shortcuts, for accessibility.
|
|
16
16
|
* @param {Object} instructionTranslations: user interface string keys mapped to translated versions for localisation. Look at the go-to-line.js source code for the English text.
|
|
17
17
|
*/
|
|
18
|
-
constructor(defaultSpaces?: boolean, numSpaces?: Number, bracketPairs?: Object, escTabToChangeFocus?: boolean,
|
|
18
|
+
constructor(defaultSpaces?: boolean, numSpaces?: Number, bracketPairs?: Object, escTabToChangeFocus?: boolean, instructionTranslations?: {
|
|
19
19
|
tabForIndentation?: string;
|
|
20
20
|
tabForNavigation?: string;
|
|
21
21
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webcoder49/code-input",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.8",
|
|
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": {
|