@webcoder49/code-input 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/code-input.js CHANGED
@@ -19,6 +19,7 @@ var codeInput = {
19
19
  observedAttributes: [
20
20
  "value",
21
21
  "placeholder",
22
+ "language",
22
23
  "lang",
23
24
  "template"
24
25
  ],
@@ -29,7 +30,6 @@ var codeInput = {
29
30
  * code-input element.
30
31
  */
31
32
  textareaSyncAttributes: [
32
- "aria-*",
33
33
  "value",
34
34
  // Form validation - https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation#using_built-in_form_validation
35
35
  "min", "max",
@@ -103,7 +103,7 @@ var codeInput = {
103
103
  * @param {Object} template - a Template object instance - see `codeInput.templates`
104
104
  */
105
105
  registerTemplate: function (templateName, template) {
106
- if(!(typeof templateName == "string" || templateName instanceof String)) throw TypeError(`code-input: Template for "${templateName}" must be a string.`);
106
+ if(!(typeof templateName == "string" || templateName instanceof String)) throw TypeError(`code-input: Name of template "${templateName}" must be a string.`);
107
107
  if(!(typeof template.highlight == "function" || template.highlight instanceof Function)) throw TypeError(`code-input: Template for "${templateName}" invalid, because the highlight function provided is not a function; it is "${template.highlight}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);
108
108
  if(!(typeof template.includeCodeInputInHighlightFunc == "boolean" || template.includeCodeInputInHighlightFunc instanceof Boolean)) throw TypeError(`code-input: Template for "${templateName}" invalid, because the includeCodeInputInHighlightFunc value provided is not a true or false; it is "${template.includeCodeInputInHighlightFunc}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);
109
109
  if(!(typeof template.preElementStyled == "boolean" || template.preElementStyled instanceof Boolean)) throw TypeError(`code-input: Template for "${templateName}" invalid, because the preElementStyled value provided is not a true or false; it is "${template.preElementStyled}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);
@@ -124,7 +124,7 @@ var codeInput = {
124
124
  elem = codeInput.templateNotYetRegisteredQueue[templateName][i];
125
125
  elem.template = template;
126
126
  codeInput.runOnceWindowLoaded((function(elem) { elem.connectedCallback(); }).bind(null, elem), elem);
127
- // Bind sets elem in parameter
127
+ // Bind sets elem as first parameter of function
128
128
  // So innerHTML can be read
129
129
  }
130
130
  console.log(`code-input: template: Added existing elements with template ${templateName}`);
@@ -138,7 +138,7 @@ var codeInput = {
138
138
  elem = codeInput.templateNotYetRegisteredQueue[undefined][i];
139
139
  elem.template = template;
140
140
  codeInput.runOnceWindowLoaded((function(elem) { elem.connectedCallback(); }).bind(null, elem), elem);
141
- // Bind sets elem in parameter
141
+ // Bind sets elem as first parameter of function
142
142
  // So innerHTML can be read
143
143
  }
144
144
  }
@@ -163,7 +163,7 @@ var codeInput = {
163
163
  * @param {boolean} isCode - is this for writing code? If true, the code-input's lang HTML attribute can be used, and the `<code>` element will be given the class name 'language-[lang attribute's value]'.
164
164
  * @param {boolean} includeCodeInputInHighlightFunc - Setting this to true passes the `<code-input>` element as a second argument to the highlight function.
165
165
  * @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.Plugin`
166
- * @returns template object
166
+ * @returns {codeInput.Template} template object
167
167
  */
168
168
  constructor(highlight = function () { }, preElementStyled = true, isCode = true, includeCodeInputInHighlightFunc = false, plugins = []) {
169
169
  this.highlight = highlight;
@@ -179,7 +179,7 @@ var codeInput = {
179
179
  * `<code-input>` element parameter if `this.includeCodeInputInHighlightFunc` is
180
180
  * `true`.
181
181
  */
182
- highlight = function() {};
182
+ highlight = function(codeElement) {};
183
183
 
184
184
  /**
185
185
  * Is the <pre> element CSS-styled as well as the `<code>` element?
@@ -226,37 +226,38 @@ var codeInput = {
226
226
  * Constructor to create a template that uses Prism.js syntax highlighting (https://prismjs.com/)
227
227
  * @param {Object} prism Import Prism.js, then after that import pass the `Prism` object as this parameter.
228
228
  * @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
229
- * @returns template object
229
+ * @returns {codeInput.Template} template object
230
230
  */
231
231
  prism(prism, plugins = []) { // Dependency: Prism.js (https://prismjs.com/)
232
- return {
233
- includeCodeInputInHighlightFunc: false,
234
- highlight: prism.highlightElement,
235
- preElementStyled: true,
236
- isCode: true,
237
- plugins: plugins,
238
- };
232
+ return new codeInput.Template(
233
+ prism.highlightElement, // highlight
234
+ true, // preElementStyled
235
+ true, // isCode
236
+ false, // includeCodeInputInHighlightFunc
237
+ plugins
238
+ );
239
239
  },
240
240
  /**
241
241
  * Constructor to create a template that uses highlight.js syntax highlighting (https://highlightjs.org/)
242
242
  * @param {Object} hljs Import highlight.js, then after that import pass the `hljs` object as this parameter.
243
243
  * @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
244
- * @returns template object
244
+ * @returns {codeInput.Template} template object
245
245
  */
246
246
  hljs(hljs, plugins = []) { // Dependency: Highlight.js (https://highlightjs.org/)
247
- return {
248
- includeCodeInputInHighlightFunc: false,
249
- highlight: hljs.highlightElement,
250
- preElementStyled: false,
251
- isCode: true,
252
- plugins: plugins,
253
- };
247
+ return new codeInput.Template(
248
+ function(codeElement) {
249
+ codeElement.removeAttribute("data-highlighted");
250
+ hljs.highlightElement(codeElement);
251
+ }, // highlight
252
+ false, // preElementStyled
253
+ true, // isCode
254
+ false, // includeCodeInputInHighlightFunc
255
+ plugins
256
+ );
254
257
  },
255
258
 
256
259
  /**
257
- * Constructor to create a proof-of-concept template that gives a message if too many characters are typed.
258
- * @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
259
- * @returns template object
260
+ * @deprecated Make your own version of this template if you need it - we think it isn't widely used so will remove it from the next version of code-input.
260
261
  */
261
262
  characterLimit(plugins) {
262
263
  return {
@@ -280,11 +281,7 @@ var codeInput = {
280
281
  },
281
282
 
282
283
  /**
283
- * Constructor to create a proof-of-concept template that shows text in a repeating series of colors.
284
- * @param {string[]} rainbowColors - An array of CSS colors, in the order each color will be shown
285
- * @param {string} delimiter - The character used to split up parts of text where each part is a different colour (e.g. "" = characters, " " = words)
286
- * @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
287
- * @returns template object
284
+ * @deprecated Make your own version of this template if you need it - we think it isn't widely used so will remove it from the next version of code-input.
288
285
  */
289
286
  rainbowText(rainbowColors = ["red", "orangered", "orange", "goldenrod", "gold", "green", "darkgreen", "navy", "blue", "magenta"], delimiter = "", plugins = []) {
290
287
  return {
@@ -299,20 +296,22 @@ var codeInput = {
299
296
  includeCodeInputInHighlightFunc: true,
300
297
  preElementStyled: true,
301
298
  isCode: false,
299
+
302
300
  rainbowColors: rainbowColors,
303
301
  delimiter: delimiter,
302
+
304
303
  plugins: plugins,
305
304
  }
306
305
  },
307
306
 
308
307
  /**
309
- * @deprecated Please use `codeInput.characterLimit(plugins)`
308
+ * @deprecated Make your own version of this template if you need it - we think it isn't widely used so will remove it from the next version of code-input.
310
309
  */
311
310
  character_limit() {
312
311
  return this.characterLimit([]);
313
312
  },
314
313
  /**
315
- * @deprecated Please use `codeInput.rainbowText`
314
+ * @deprecated Make your own version of this template if you need it - we think it isn't widely used so will remove it from the next version of code-input.
316
315
  */
317
316
  rainbow_text(rainbowColors = ["red", "orangered", "orange", "goldenrod", "gold", "green", "darkgreen", "navy", "blue", "magenta"], delimiter = "", plugins = []) {
318
317
  return this.rainbowText(rainbowColors, delimiter, plugins);
@@ -374,14 +373,7 @@ var codeInput = {
374
373
  console.log("code-input: plugin: Created plugin");
375
374
 
376
375
  observedAttributes.forEach((attribute) => {
377
- // Move plugin attribute to codeInput observed attributes
378
- let regexFromWildcard = codeInput.wildcard2regex(attribute);
379
- if(regexFromWildcard == null) {
380
- // Not a wildcard
381
- codeInput.observedAttributes.push(attribute);
382
- } else {
383
- codeInput.observedAttributes.regexp.push(regexFromWildcard);
384
- }
376
+ codeInput.observedAttributes.push(attribute);
385
377
  });
386
378
  }
387
379
 
@@ -426,10 +418,6 @@ var codeInput = {
426
418
  constructor() {
427
419
  super(); // Element
428
420
  }
429
- /**
430
- * Store value internally
431
- */
432
- _value = '';
433
421
 
434
422
  /**
435
423
  * Exposed child textarea element for user to input code in
@@ -439,13 +427,19 @@ var codeInput = {
439
427
  * Exposed child pre element where syntax-highlighted code is outputted.
440
428
  * Contains this.codeElement as its only child.
441
429
  */
442
- preElement = null;
430
+ preElement = null
443
431
  /**
444
432
  * Exposed child pre element's child code element where syntax-highlighted code is outputted.
445
433
  * Has this.preElement as its parent.
446
434
  */
447
435
  codeElement = null;
448
436
 
437
+ /**
438
+ * Exposed non-scrolling element designed to contain dialog boxes etc. that shouldn't scroll
439
+ * with the code-input element.
440
+ */
441
+ dialogContainerElement = null;
442
+
449
443
  /**
450
444
  * Form-Associated Custom Element Callbacks
451
445
  * https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example
@@ -487,31 +481,48 @@ var codeInput = {
487
481
  * the result (pre code) element, then use the template object
488
482
  * to syntax-highlight it. */
489
483
 
490
- /** Update the text value to the result element, after the textarea contents have changed.
491
- * @param {string} value - The text value of the code-input element
492
- * @param {boolean} originalUpdate - Whether this update originates from the textarea's content; if so, run it first so custom updates override it.
484
+ needsHighlight = false; // Just inputted
485
+
486
+ /**
487
+ * Highlight the code as soon as possible
488
+ */
489
+ scheduleHighlight() {
490
+ this.needsHighlight = true;
491
+ }
492
+
493
+ /**
494
+ * Call an animation frame
493
495
  */
494
- update(value) {
495
- // Prevent this from running multiple times on the same input when "value" attribute is changed,
496
- // by not running when value is already equal to the input of this (implying update has already
497
- // been run). Thank you to peterprvy for this.
498
- if (this.ignoreValueUpdate) return;
499
-
500
- if(this.textareaElement == null) {
501
- this.addEventListener("code-input_load", () => { this.update(value) }); // Only run when fully loaded
502
- return;
496
+ animateFrame() {
497
+ // Synchronise the size of the pre/code and textarea elements
498
+ if(this.template.preElementStyled) {
499
+ this.style.backgroundColor = getComputedStyle(this.preElement).backgroundColor;
500
+ this.textareaElement.style.height = getComputedStyle(this.preElement).height;
501
+ this.textareaElement.style.width = getComputedStyle(this.preElement).width;
502
+ } else {
503
+ this.style.backgroundColor = getComputedStyle(this.codeElement).backgroundColor;
504
+ this.textareaElement.style.height = getComputedStyle(this.codeElement).height;
505
+ this.textareaElement.style.width = getComputedStyle(this.codeElement).width;
503
506
  }
504
507
 
505
- this.ignoreValueUpdate = true;
506
- this.value = value;
507
- this.ignoreValueUpdate = false;
508
- if (this.textareaElement.value != value) this.textareaElement.value = value;
508
+ // Synchronise the contents of the pre/code and textarea elements
509
+ if(this.needsHighlight) {
510
+ this.update();
511
+ this.needsHighlight = false;
512
+ }
509
513
 
514
+ window.requestAnimationFrame(this.animateFrame.bind(this));
515
+ }
510
516
 
517
+ /**
518
+ * Update the text value to the result element, after the textarea contents have changed.
519
+ */
520
+ update() {
511
521
  let resultElement = this.codeElement;
522
+ let value = this.value;
512
523
 
513
524
  // Handle final newlines
514
- if (value[value.length - 1] == "\n") {
525
+ if (value[value.length - 1] == "\n" || value.length == 0) {
515
526
  value += " ";
516
527
  }
517
528
 
@@ -526,17 +537,6 @@ var codeInput = {
526
537
  this.pluginEvt("afterHighlight");
527
538
  }
528
539
 
529
- /**
530
- * Synchronise the scrolling of the textarea to the result element.
531
- */
532
- syncScroll() {
533
- let inputElement = this.textareaElement;
534
- let resultElement = this.template.preElementStyled ? this.preElement : this.codeElement;
535
-
536
- resultElement.scrollTop = inputElement.scrollTop;
537
- resultElement.scrollLeft = inputElement.scrollLeft;
538
- }
539
-
540
540
  /**
541
541
  * HTML-escape an arbitrary string.
542
542
  * @param {string} text - The original, unescaped text
@@ -592,7 +592,7 @@ var codeInput = {
592
592
  this.pluginEvt("beforeElementsAdded");
593
593
 
594
594
  // First-time attribute sync
595
- let lang = this.getAttribute("lang");
595
+ let lang = this.getAttribute("language") || this.getAttribute("lang");
596
596
  let placeholder = this.getAttribute("placeholder") || this.getAttribute("lang") || "";
597
597
  let value = this.unescapeHtml(this.innerHTML) || this.getAttribute("value") || "";
598
598
  // Value attribute deprecated, but included for compatibility
@@ -611,22 +611,14 @@ var codeInput = {
611
611
  this.innerHTML = ""; // Clear Content
612
612
 
613
613
  // Synchronise attributes to textarea
614
- codeInput.textareaSyncAttributes.forEach((attribute) => {
615
- if (this.hasAttribute(attribute)) {
614
+ for(let i = 0; i < this.attributes.length; i++) {
615
+ let attribute = this.attributes[i].name;
616
+ if (codeInput.textareaSyncAttributes.includes(attribute) || attribute.substring(0, 5) == "aria-") {
616
617
  textarea.setAttribute(attribute, this.getAttribute(attribute));
617
618
  }
618
- });
619
- codeInput.textareaSyncAttributes.regexp.forEach((reg) =>
620
- {
621
- for(const attr of this.attributes) {
622
- if (attr.nodeName.match(reg)) {
623
- textarea.setAttribute(attr.nodeName, attr.nodeValue);
624
- }
625
- }
626
- });
619
+ }
627
620
 
628
- textarea.addEventListener('input', (evt) => { textarea.parentElement.update(textarea.value); textarea.parentElement.sync_scroll(); });
629
- textarea.addEventListener('scroll', (evt) => textarea.parentElement.sync_scroll());
621
+ textarea.addEventListener('input', (evt) => { this.value = this.textareaElement.value; });
630
622
 
631
623
  // Save element internally
632
624
  this.textareaElement = textarea;
@@ -645,22 +637,22 @@ var codeInput = {
645
637
 
646
638
  if (this.template.isCode) {
647
639
  if (lang != undefined && lang != "") {
648
- code.classList.add("language-" + lang);
640
+ code.classList.add("language-" + lang.toLowerCase());
649
641
  }
650
642
  }
651
643
 
652
- this.pluginEvt("afterElementsAdded");
644
+ // dialogContainerElement used to store non-scrolling dialog boxes, etc.
645
+ let dialogContainerElement = document.createElement("div");
646
+ dialogContainerElement.classList.add("code-input_dialog-container");
647
+ this.append(dialogContainerElement);
648
+ this.dialogContainerElement = dialogContainerElement;
653
649
 
654
- this.update(value);
650
+ this.pluginEvt("afterElementsAdded");
655
651
 
656
652
  this.dispatchEvent(new CustomEvent("code-input_load"));
657
- }
658
653
 
659
- /**
660
- * @deprecated Please use `codeInput.CodeInput.syncScroll`
661
- */
662
- sync_scroll() {
663
- this.syncScroll();
654
+ this.value = value;
655
+ this.animateFrame();
664
656
  }
665
657
 
666
658
  /**
@@ -671,7 +663,7 @@ var codeInput = {
671
663
  }
672
664
 
673
665
  /**
674
- * @deprecated Please use `codeInput.CodeInput.escapeHtml`
666
+ * @deprecated Please use `codeInput.CodeInput.getTemplate`
675
667
  */
676
668
  get_template() {
677
669
  return this.getTemplate();
@@ -715,13 +707,8 @@ var codeInput = {
715
707
  return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
716
708
  }
717
709
  }
718
-
719
- /* Check wildcard attributes */
720
- for(let i = 0; i < codeInput.observedAttributes.regexp.length; i++) {
721
- const reg = codeInput.observedAttributes.regexp[i];
722
- if (mutation.attributeName.match(reg)) {
723
- return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
724
- }
710
+ if (mutation.attributeName.substring(0, 5) == "aria-") {
711
+ return this.attributeChangedCallback(mutation.attributeName, mutation.oldValue, super.getAttribute(mutation.attributeName));
725
712
  }
726
713
  }
727
714
  }
@@ -745,20 +732,17 @@ var codeInput = {
745
732
  case "value":
746
733
  this.value = newValue;
747
734
  break;
748
- case "placeholder":
749
- this.textareaElement.placeholder = newValue;
750
- break;
751
735
  case "template":
752
736
  this.template = codeInput.usedTemplates[newValue || codeInput.defaultTemplate];
753
737
  if (this.template.preElementStyled) this.classList.add("code-input_pre-element-styled");
754
738
  else this.classList.remove("code-input_pre-element-styled");
755
739
  // Syntax Highlight
756
- this.update(this.value);
740
+ this.needsHighlight = true;
757
741
 
758
742
  break;
759
743
 
760
744
  case "lang":
761
-
745
+ case "language":
762
746
  let code = this.codeElement;
763
747
  let mainTextarea = this.textareaElement;
764
748
 
@@ -785,11 +769,11 @@ var codeInput = {
785
769
 
786
770
  if (mainTextarea.placeholder == oldValue) mainTextarea.placeholder = newValue;
787
771
 
788
- this.update(this.value);
772
+ this.needsHighlight = true;
789
773
 
790
774
  break;
791
775
  default:
792
- if (codeInput.textareaSyncAttributes.includes(name)) {
776
+ if (codeInput.textareaSyncAttributes.includes(name) || name.substring(0, 5) == "aria-") {
793
777
  if(newValue == null || newValue == undefined) {
794
778
  this.textareaElement.removeAttribute(name);
795
779
  } else {
@@ -822,10 +806,12 @@ var codeInput = {
822
806
  * @override
823
807
  */
824
808
  addEventListener(type, listener, options = undefined) {
809
+ // Save a copy of the callback where `this` refers to the code-input element
825
810
  let boundCallback = listener.bind(this);
826
811
  this.boundEventCallbacks[listener] = boundCallback;
827
812
 
828
813
  if (codeInput.textareaSyncEvents.includes(type)) {
814
+ // Synchronise with textarea
829
815
  if (options === undefined) {
830
816
  if(this.textareaElement == null) {
831
817
  this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback); });
@@ -840,6 +826,7 @@ var codeInput = {
840
826
  }
841
827
  }
842
828
  } else {
829
+ // Synchronise with code-input element
843
830
  if (options === undefined) {
844
831
  super.addEventListener(type, boundCallback);
845
832
  } else {
@@ -851,22 +838,32 @@ var codeInput = {
851
838
  /**
852
839
  * @override
853
840
  */
854
- removeEventListener(type, listener, options = null) {
841
+ removeEventListener(type, listener, options = undefined) {
842
+ // Save a copy of the callback where `this` refers to the code-input element
855
843
  let boundCallback = this.boundEventCallbacks[listener];
856
- if (type == "change") {
857
- if (options === null) {
858
- this.textareaElement.removeEventListener("change", boundCallback);
844
+
845
+ if (codeInput.textareaSyncEvents.includes(type)) {
846
+ // Synchronise with textarea
847
+ if (options === undefined) {
848
+ if(this.textareaElement == null) {
849
+ this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback); });
850
+ } else {
851
+ this.textareaElement.removeEventListener(type, boundCallback);
852
+ }
859
853
  } else {
860
- this.textareaElement.removeEventListener("change", boundCallback, options);
854
+ if(this.textareaElement == null) {
855
+ this.addEventListener("code-input_load", () => { this.textareaElement.removeEventListener(type, boundCallback, options); });
856
+ } else {
857
+ this.textareaElement.removeEventListener(type, boundCallback, options);
858
+ }
861
859
  }
862
- } else if (type == "selectionchange") {
863
- if (options === null) {
864
- this.textareaElement.removeEventListener("selectionchange", boundCallback);
860
+ } else {
861
+ // Synchronise with code-input element
862
+ if (options === undefined) {
863
+ super.removeEventListener(type, boundCallback);
865
864
  } else {
866
- this.textareaElement.removeEventListener("selectionchange", boundCallback, options);
865
+ super.removeEventListener(type, boundCallback, options);
867
866
  }
868
- } else {
869
- super.removeEventListener(type, listener, options);
870
867
  }
871
868
  }
872
869
 
@@ -874,7 +871,8 @@ var codeInput = {
874
871
  * Get the text contents of the code-input element.
875
872
  */
876
873
  get value() {
877
- return this._value;
874
+ // Get from editable textarea element
875
+ return this.textareaElement.value;
878
876
  }
879
877
  /**
880
878
  * Set the text contents of the code-input element.
@@ -884,8 +882,10 @@ var codeInput = {
884
882
  if (val === null || val === undefined) {
885
883
  val = "";
886
884
  }
887
- this._value = val;
888
- this.update(val);
885
+ // Save in editable textarea element
886
+ this.textareaElement.value = val;
887
+ // Trigger highlight
888
+ this.needsHighlight = true;
889
889
  return val;
890
890
  }
891
891
 
@@ -963,34 +963,10 @@ var codeInput = {
963
963
  * Update value on form reset
964
964
  */
965
965
  formResetCallback() {
966
- this.update(this.initialValue);
967
- };
968
- },
969
-
970
- arrayWildcards2regex(list) {
971
- for(let i = 0; i < list.length; i++) {
972
- const name = list[i];
973
- if (name.indexOf("*") < 0)
974
- continue;
975
-
976
- list.regexp.push(new RegExp("^" +
977
- name.replace(/[/\-\\^$+?.()|[\]{}]/g, '\\$&')
978
- .replace("*", ".*")
979
- + "$", "i"));
980
- list.splice(i--, 1);
966
+ this.value = this.initialValue;
981
967
  };
982
968
  },
983
969
 
984
- wildcard2regex(wildcard) {
985
- if (wildcard.indexOf("*") < 0)
986
- return null;
987
-
988
- return new RegExp("^" +
989
- wildcard.replace(/[/\-\\^$+?.()|[\]{}]/g, '\\$&')
990
- .replace("*", ".*")
991
- + "$", "i");
992
- },
993
-
994
970
  /**
995
971
  * To ensure the DOM is ready, run this callback after the window
996
972
  * has loaded (or now if it has already loaded)
@@ -1008,29 +984,4 @@ window.addEventListener("load", function() {
1008
984
  codeInput.windowLoaded = true;
1009
985
  });
1010
986
 
1011
-
1012
- /**
1013
- * convert wildcards into regex
1014
- */
1015
-
1016
- {
1017
- Object.defineProperty(codeInput.textareaSyncAttributes, 'regexp', {
1018
- value: [],
1019
- writable: false,
1020
- enumerable: false,
1021
- configurable: false
1022
- });
1023
- codeInput.observedAttributes = codeInput.observedAttributes.concat(codeInput.textareaSyncAttributes);
1024
-
1025
- Object.defineProperty(codeInput.observedAttributes, 'regexp', {
1026
- value: [],
1027
- writable: false,
1028
- enumerable: false,
1029
- configurable: false
1030
- });
1031
-
1032
- codeInput.arrayWildcards2regex(codeInput.textareaSyncAttributes);
1033
- codeInput.arrayWildcards2regex(codeInput.observedAttributes);
1034
- }
1035
-
1036
- customElements.define("code-input", codeInput.CodeInput);
987
+ customElements.define("code-input", codeInput.CodeInput);
@@ -1 +1 @@
1
- code-input{position:relative;top:0;left:0;display:block;overflow:hidden;margin:8px;--padding:16px;height:250px;font-size:normal;font-family:monospace;line-height:1.5;tab-size:2;caret-color:#a9a9a9;white-space:pre;padding:0!important}code-input textarea,code-input.code-input_pre-element-styled pre,code-input:not(.code-input_pre-element-styled) pre code{margin:0!important;padding:var(--padding,16px)!important;border:0;width:calc(100% - var(--padding,16px) * 2);height:calc(100% - var(--padding,16px) * 2)}code-input:not(.code-input_loaded){margin:0!important;margin-bottom:calc(-1 * var(--padding,16px))!important;padding:var(--padding,16px)!important;border:0}code-input.code-input_pre-element-styled pre code,code-input:not(.code-input_pre-element-styled) pre{margin:0!important;padding:0!important;width:100%;height:100%}code-input pre,code-input pre *,code-input textarea{font-size:inherit!important;font-family:inherit!important;line-height:inherit!important;tab-size:inherit!important}code-input pre,code-input textarea{position:absolute;top:0;left:0}code-input textarea{z-index:1}code-input pre{z-index:0}code-input:not(.code-input_loaded) pre,code-input:not(.code-input_loaded) textarea{opacity:0}code-input:not(.code-input_loaded)::after{color:#ccc}code-input textarea{color:transparent;background:0 0;caret-color:inherit!important}code-input textarea::placeholder{color:#d3d3d3}code-input pre,code-input textarea{overflow:auto!important;white-space:inherit;word-spacing:normal;word-break:normal;word-wrap:normal}code-input textarea{resize:none;outline:0!important}code-input:not(.code-input_registered)::after{content:"Use codeInput.registerTemplate to set up.";display:block;color:grey}
1
+ code-input{display:block;overflow-y:auto;overflow-x:auto;position:relative;top:0;left:0;margin:8px;--padding:16px;height:250px;font-size:inherit;font-family:monospace;line-height:1.5;tab-size:2;caret-color:#a9a9a9;white-space:pre;padding:0!important;display:grid;grid-template-columns:100%;grid-template-rows:100%}code-input:not(.code-input_loaded){margin:0!important;margin-bottom:calc(-1 * var(--padding,16px))!important;padding:var(--padding,16px)!important;border:0}code-input textarea,code-input.code-input_pre-element-styled pre,code-input:not(.code-input_pre-element-styled) pre code{margin:0!important;padding:var(--padding,16px)!important;border:0;min-width:calc(100% - var(--padding,16px) * 2);min-height:calc(100% - var(--padding,16px) * 2);overflow:hidden;resize:none;grid-row:1;grid-column:1;display:block}code-input.code-input_pre-element-styled pre,code-input:not(.code-input_pre-element-styled) pre code{height:max-content;width:max-content}code-input.code-input_pre-element-styled pre code,code-input:not(.code-input_pre-element-styled) pre{margin:0!important;padding:0!important;width:100%;height:100%}code-input pre,code-input pre *,code-input textarea{font-size:inherit!important;font-family:inherit!important;line-height:inherit!important;tab-size:inherit!important}code-input pre,code-input textarea{grid-column:1;grid-row:1}code-input textarea{z-index:1}code-input pre{z-index:0}code-input:not(.code-input_loaded) pre,code-input:not(.code-input_loaded) textarea{opacity:0}code-input:not(.code-input_loaded)::before{color:#ccc}code-input textarea{color:transparent;background:0 0;caret-color:inherit!important}code-input textarea::placeholder{color:#d3d3d3}code-input pre,code-input textarea{white-space:inherit;word-spacing:normal;word-break:normal;word-wrap:normal}code-input textarea{resize:none;outline:0!important}code-input:not(.code-input_registered)::before{content:"Use codeInput.registerTemplate to set up.";display:block;color:grey}code-input .code-input_dialog-container{z-index:2;position:sticky;grid-row:1;grid-column:1;top:0;left:0;width:100%;height:0;text-align:left}
package/code-input.min.js CHANGED
@@ -1 +1 @@
1
- var codeInput={observedAttributes:["value","placeholder","lang","template"],textareaSyncAttributes:["aria-*","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"],usedTemplates:{},defaultTemplate:void 0,templateNotYetRegisteredQueue:{},registerTemplate:function(a,b){if(!("string"==typeof a||a instanceof String))throw TypeError(`code-input: Template for "${a}" must be a string.`);if(!("function"==typeof b.highlight||b.highlight instanceof Function))throw TypeError(`code-input: Template for "${a}" invalid, because the highlight function provided is not a function; it is "${b.highlight}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.includeCodeInputInHighlightFunc||b.includeCodeInputInHighlightFunc instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the includeCodeInputInHighlightFunc value provided is not a true or false; it is "${b.includeCodeInputInHighlightFunc}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.preElementStyled||b.preElementStyled instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the preElementStyled value provided is not a true or false; it is "${b.preElementStyled}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.isCode||b.isCode instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the isCode value provided is not a true or false; it is "${b.isCode}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!Array.isArray(b.plugins))throw TypeError(`code-input: Template for "${a}" invalid, because the plugin array provided is not an array; it is "${b.plugins}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(b.plugins.forEach((c,d)=>{if(!(c instanceof codeInput.Plugin))throw TypeError(`code-input: Template for "${a}" invalid, because the plugin provided at index ${d} is not valid; it is "${b.plugins[d]}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`)}),codeInput.usedTemplates[a]=b,a in codeInput.templateNotYetRegisteredQueue){for(let c in codeInput.templateNotYetRegisteredQueue[a])elem=codeInput.templateNotYetRegisteredQueue[a][c],elem.template=b,codeInput.runOnceWindowLoaded(function(a){a.connectedCallback()}.bind(null,elem),elem);console.log(`code-input: template: Added existing elements with template ${a}`)}if(null==codeInput.defaultTemplate){if(codeInput.defaultTemplate=a,void 0 in codeInput.templateNotYetRegisteredQueue)for(let a in codeInput.templateNotYetRegisteredQueue[void 0])elem=codeInput.templateNotYetRegisteredQueue[void 0][a],elem.template=b,codeInput.runOnceWindowLoaded(function(a){a.connectedCallback()}.bind(null,elem),elem);console.log(`code-input: template: Set template ${a} as default`)}console.log(`code-input: template: Created template ${a}`)},Template:class{constructor(a=function(){},b=!0,c=!0,d=!1,e=[]){this.highlight=a,this.preElementStyled=b,this.isCode=c,this.includeCodeInputInHighlightFunc=d,this.plugins=e}highlight=function(){};preElementStyled=!0;isCode=!0;includeCodeInputInHighlightFunc=!1;plugins=[]},templates:{prism(a,b=[]){return{includeCodeInputInHighlightFunc:!1,highlight:a.highlightElement,preElementStyled:!0,isCode:!0,plugins:b}},hljs(a,b=[]){return{includeCodeInputInHighlightFunc:!1,highlight:a.highlightElement,preElementStyled:!1,isCode:!0,plugins:b}},characterLimit(a){return{highlight:function(a,b,c=[]){let d=+b.getAttribute("data-character-limit"),e=b.escapeHtml(b.value.slice(0,d)),f=b.escapeHtml(b.value.slice(d));a.innerHTML=`${e}<mark class="overflow">${f}</mark>`,0<f.length&&(a.innerHTML+=` <mark class="overflow-msg">${b.getAttribute("data-overflow-msg")||"(Character limit reached)"}</mark>`)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,plugins:a}},rainbowText(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return{highlight:function(a,b){let c=[],d=b.value.split(b.template.delimiter);for(let e=0;e<d.length;e++)c.push(`<span style="color: ${b.template.rainbowColors[e%b.template.rainbowColors.length]}">${b.escapeHtml(d[e])}</span>`);a.innerHTML=c.join(b.template.delimiter)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,rainbowColors:a,delimiter:b,plugins:c}},character_limit(){return this.characterLimit([])},rainbow_text(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return this.rainbowText(a,b,c)},custom(a=function(){},b=!0,c=!0,d=!1,e=[]){return{highlight:a,includeCodeInputInHighlightFunc:d,preElementStyled:b,isCode:c,plugins:e}}},plugins:new Proxy({},{get(a,b){if(a[b]==null)throw ReferenceError(`code-input: Plugin '${b}' is not defined. Please ensure you import the necessary files from the plugins folder in the WebCoder49/code-input repository, in the <head> of your HTML, before the plugin is instatiated.`);return a[b]}}),Plugin:class{constructor(a){console.log("code-input: plugin: Created plugin"),a.forEach(a=>{let b=codeInput.wildcard2regex(a);null==b?codeInput.observedAttributes.push(a):codeInput.observedAttributes.regexp.push(b)})}beforeHighlight(){}afterHighlight(){}beforeElementsAdded(){}afterElementsAdded(){}attributeChanged(){}},CodeInput:class extends HTMLElement{constructor(){super()}_value="";textareaElement=null;preElement=null;codeElement=null;static formAssociated=!0;boundEventCallbacks={};pluginEvt(a,b){for(let c in this.template.plugins){let d=this.template.plugins[c];a in d&&(b===void 0?d[a](this):d[a](this,...b))}}update(a){if(!this.ignoreValueUpdate){if(null==this.textareaElement)return void this.addEventListener("code-input_load",()=>{this.update(a)});this.ignoreValueUpdate=!0,this.value=a,this.ignoreValueUpdate=!1,this.textareaElement.value!=a&&(this.textareaElement.value=a);let b=this.codeElement;"\n"==a[a.length-1]&&(a+=" "),b.innerHTML=this.escapeHtml(a),this.pluginEvt("beforeHighlight"),this.template.includeCodeInputInHighlightFunc?this.template.highlight(b,this):this.template.highlight(b),this.pluginEvt("afterHighlight")}}syncScroll(){let a=this.textareaElement,b=this.template.preElementStyled?this.preElement:this.codeElement;b.scrollTop=a.scrollTop,b.scrollLeft=a.scrollLeft}escapeHtml(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;")}unescapeHtml(a){return a.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">")}getTemplate(){let a;return a=null==this.getAttribute("template")?codeInput.defaultTemplate:this.getAttribute("template"),a in codeInput.usedTemplates?codeInput.usedTemplates[a]:(a in codeInput.templateNotYetRegisteredQueue||(codeInput.templateNotYetRegisteredQueue[a]=[]),void codeInput.templateNotYetRegisteredQueue[a].push(this))}setup(){if(null!=this.textareaElement)return;this.classList.add("code-input_registered"),this.template.preElementStyled&&this.classList.add("code-input_pre-element-styled"),this.pluginEvt("beforeElementsAdded");let a=this.getAttribute("lang"),b=this.getAttribute("placeholder")||this.getAttribute("lang")||"",c=this.unescapeHtml(this.innerHTML)||this.getAttribute("value")||"";this.initialValue=c;let d=document.createElement("textarea");d.placeholder=b,""!=c&&(d.value=c),d.innerHTML=this.innerHTML,d.setAttribute("spellcheck","false"),this.innerHTML="",codeInput.textareaSyncAttributes.forEach(a=>{this.hasAttribute(a)&&d.setAttribute(a,this.getAttribute(a))}),codeInput.textareaSyncAttributes.regexp.forEach(a=>{for(const b of this.attributes)b.nodeName.match(a)&&d.setAttribute(b.nodeName,b.nodeValue)}),d.addEventListener("input",()=>{d.parentElement.update(d.value),d.parentElement.sync_scroll()}),d.addEventListener("scroll",()=>d.parentElement.sync_scroll()),this.textareaElement=d,this.append(d);let e=document.createElement("code"),f=document.createElement("pre");f.setAttribute("aria-hidden","true"),this.preElement=f,this.codeElement=e,f.append(e),this.append(f),this.template.isCode&&a!=null&&""!=a&&e.classList.add("language-"+a),this.pluginEvt("afterElementsAdded"),this.update(c),this.dispatchEvent(new CustomEvent("code-input_load"))}sync_scroll(){this.syncScroll()}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}connectedCallback(){this.template=this.getTemplate(),this.template!=null&&(this.classList.add("code-input_registered"),codeInput.runOnceWindowLoaded(()=>{this.setup(),this.classList.add("code-input_loaded")},this)),this.mutationObserver=new MutationObserver(this.mutationObserverCallback.bind(this)),this.mutationObserver.observe(this,{attributes:!0,attributeOldValue:!0})}mutationObserverCallback(a){for(const b of a)if("attributes"===b.type){for(let a=0;a<codeInput.observedAttributes.length;a++)if(b.attributeName==codeInput.observedAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));for(let a=0;a<codeInput.observedAttributes.regexp.length;a++){const c=codeInput.observedAttributes.regexp[a];if(b.attributeName.match(c))return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName))}}}disconnectedCallback(){this.mutationObserver.disconnect()}attributeChangedCallback(a,b,c){if(this.isConnected)switch(this.pluginEvt("attributeChanged",[a,b,c]),a){case"value":this.value=c;break;case"placeholder":this.textareaElement.placeholder=c;break;case"template":this.template=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.template.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.update(this.value);break;case"lang":let d=this.codeElement,e=this.textareaElement;if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;b=b.toLowerCase(),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.update(this.value);break;default:codeInput.textareaSyncAttributes.includes(a)?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=b.bind(this);this.boundEventCallbacks[b]=d,codeInput.textareaSyncEvents.includes(a)?c===void 0?null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d)}):this.textareaElement.addEventListener(a,d):null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d,c)}):this.textareaElement.addEventListener(a,d,c):c===void 0?super.addEventListener(a,d):super.addEventListener(a,d,c)}removeEventListener(a,b,c=null){let d=this.boundEventCallbacks[b];"change"==a?null===c?this.textareaElement.removeEventListener("change",d):this.textareaElement.removeEventListener("change",d,c):"selectionchange"==a?null===c?this.textareaElement.removeEventListener("selectionchange",d):this.textareaElement.removeEventListener("selectionchange",d,c):super.removeEventListener(a,b,c)}get value(){return this._value}set value(a){return(null===a||void 0===a)&&(a=""),this._value=a,this.update(a),a}get placeholder(){return this.getAttribute("placeholder")}set placeholder(a){return this.setAttribute("placeholder",a)}get validity(){return this.textareaElement.validity}get validationMessage(){return this.textareaElement.validationMessage}setCustomValidity(a){return this.textareaElement.setCustomValidity(a)}checkValidity(){return this.textareaElement.checkValidity()}reportValidity(){return this.textareaElement.reportValidity()}pluginData={};formResetCallback(){this.update(this.initialValue)}},arrayWildcards2regex(a){for(let b=0;b<a.length;b++){const c=a[b];0>c.indexOf("*")||(a.regexp.push(new RegExp("^"+c.replace(/[/\-\\^$+?.()|[\]{}]/g,"\\$&").replace("*",".*")+"$","i")),a.splice(b--,1))}},wildcard2regex(a){return 0>a.indexOf("*")?null:new RegExp("^"+a.replace(/[/\-\\^$+?.()|[\]{}]/g,"\\$&").replace("*",".*")+"$","i")},runOnceWindowLoaded(a){codeInput.windowLoaded?a():window.addEventListener("load",a)},windowLoaded:!1};window.addEventListener("load",function(){codeInput.windowLoaded=!0}),Object.defineProperty(codeInput.textareaSyncAttributes,"regexp",{value:[],writable:!1,enumerable:!1,configurable:!1}),codeInput.observedAttributes=codeInput.observedAttributes.concat(codeInput.textareaSyncAttributes),Object.defineProperty(codeInput.observedAttributes,"regexp",{value:[],writable:!1,enumerable:!1,configurable:!1}),codeInput.arrayWildcards2regex(codeInput.textareaSyncAttributes),codeInput.arrayWildcards2regex(codeInput.observedAttributes),customElements.define("code-input",codeInput.CodeInput);
1
+ 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"],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])elem=codeInput.templateNotYetRegisteredQueue[a][c],elem.template=b,codeInput.runOnceWindowLoaded(function(a){a.connectedCallback()}.bind(null,elem),elem);console.log(`code-input: template: Added existing elements with template ${a}`)}if(null==codeInput.defaultTemplate){if(codeInput.defaultTemplate=a,void 0 in codeInput.templateNotYetRegisteredQueue)for(let a in codeInput.templateNotYetRegisteredQueue[void 0])elem=codeInput.templateNotYetRegisteredQueue[void 0][a],elem.template=b,codeInput.runOnceWindowLoaded(function(a){a.connectedCallback()}.bind(null,elem),elem);console.log(`code-input: template: Set template ${a} as default`)}console.log(`code-input: template: Created template ${a}`)},Template:class{constructor(a=function(){},b=!0,c=!0,d=!1,e=[]){this.highlight=a,this.preElementStyled=b,this.isCode=c,this.includeCodeInputInHighlightFunc=d,this.plugins=e}highlight=function(){};preElementStyled=!0;isCode=!0;includeCodeInputInHighlightFunc=!1;plugins=[]},templates:{prism(a,b=[]){return new codeInput.Template(a.highlightElement,!0,!0,!1,b)},hljs(a,b=[]){return new codeInput.Template(function(b){b.removeAttribute("data-highlighted"),a.highlightElement(b)},!1,!0,!1,b)},characterLimit(a){return{highlight:function(a,b,c=[]){let d=+b.getAttribute("data-character-limit"),e=b.escapeHtml(b.value.slice(0,d)),f=b.escapeHtml(b.value.slice(d));a.innerHTML=`${e}<mark class="overflow">${f}</mark>`,0<f.length&&(a.innerHTML+=` <mark class="overflow-msg">${b.getAttribute("data-overflow-msg")||"(Character limit reached)"}</mark>`)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,plugins:a}},rainbowText(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return{highlight:function(a,b){let c=[],d=b.value.split(b.template.delimiter);for(let e=0;e<d.length;e++)c.push(`<span style="color: ${b.template.rainbowColors[e%b.template.rainbowColors.length]}">${b.escapeHtml(d[e])}</span>`);a.innerHTML=c.join(b.template.delimiter)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,rainbowColors:a,delimiter:b,plugins:c}},character_limit(){return this.characterLimit([])},rainbow_text(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return this.rainbowText(a,b,c)},custom(a=function(){},b=!0,c=!0,d=!1,e=[]){return{highlight:a,includeCodeInputInHighlightFunc:d,preElementStyled:b,isCode:c,plugins:e}}},plugins:new Proxy({},{get(a,b){if(a[b]==null)throw ReferenceError(`code-input: Plugin '${b}' is not defined. Please ensure you import the necessary files from the plugins folder in the WebCoder49/code-input repository, in the <head> of your HTML, before the plugin is instatiated.`);return a[b]}}),Plugin:class{constructor(a){console.log("code-input: plugin: Created plugin"),a.forEach(a=>{codeInput.observedAttributes.push(a)})}beforeHighlight(){}afterHighlight(){}beforeElementsAdded(){}afterElementsAdded(){}attributeChanged(){}},CodeInput:class extends HTMLElement{constructor(){super()}textareaElement=null;preElement=null;codeElement=null;dialogContainerElement=null;static formAssociated=!0;boundEventCallbacks={};pluginEvt(a,b){for(let c in this.template.plugins){let d=this.template.plugins[c];a in d&&(b===void 0?d[a](this):d[a](this,...b))}}needsHighlight=!1;scheduleHighlight(){this.needsHighlight=!0}animateFrame(){this.template.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),this.needsHighlight&&(this.update(),this.needsHighlight=!1),window.requestAnimationFrame(this.animateFrame.bind(this))}update(){let a=this.codeElement,b=this.value;("\n"==b[b.length-1]||0==b.length)&&(b+=" "),a.innerHTML=this.escapeHtml(b),this.pluginEvt("beforeHighlight"),this.template.includeCodeInputInHighlightFunc?this.template.highlight(a,this):this.template.highlight(a),this.pluginEvt("afterHighlight")}escapeHtml(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;")}unescapeHtml(a){return a.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">")}getTemplate(){let a;return a=null==this.getAttribute("template")?codeInput.defaultTemplate:this.getAttribute("template"),a in codeInput.usedTemplates?codeInput.usedTemplates[a]:(a in codeInput.templateNotYetRegisteredQueue||(codeInput.templateNotYetRegisteredQueue[a]=[]),void codeInput.templateNotYetRegisteredQueue[a].push(this))}setup(){if(null!=this.textareaElement)return;this.classList.add("code-input_registered"),this.template.preElementStyled&&this.classList.add("code-input_pre-element-styled"),this.pluginEvt("beforeElementsAdded");let a=this.getAttribute("language")||this.getAttribute("lang"),b=this.getAttribute("placeholder")||this.getAttribute("lang")||"",c=this.unescapeHtml(this.innerHTML)||this.getAttribute("value")||"";this.initialValue=c;let d=document.createElement("textarea");d.placeholder=b,""!=c&&(d.value=c),d.innerHTML=this.innerHTML,d.setAttribute("spellcheck","false"),this.innerHTML="";for(let a,b=0;b<this.attributes.length;b++)a=this.attributes[b].name,(codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5))&&d.setAttribute(a,this.getAttribute(a));d.addEventListener("input",()=>{this.value=this.textareaElement.value}),this.textareaElement=d,this.append(d);let e=document.createElement("code"),f=document.createElement("pre");f.setAttribute("aria-hidden","true"),this.preElement=f,this.codeElement=e,f.append(e),this.append(f),this.template.isCode&&a!=null&&""!=a&&e.classList.add("language-"+a.toLowerCase());let g=document.createElement("div");g.classList.add("code-input_dialog-container"),this.append(g),this.dialogContainerElement=g,this.pluginEvt("afterElementsAdded"),this.dispatchEvent(new CustomEvent("code-input_load")),this.value=c,this.animateFrame()}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}connectedCallback(){this.template=this.getTemplate(),this.template!=null&&(this.classList.add("code-input_registered"),codeInput.runOnceWindowLoaded(()=>{this.setup(),this.classList.add("code-input_loaded")},this)),this.mutationObserver=new MutationObserver(this.mutationObserverCallback.bind(this)),this.mutationObserver.observe(this,{attributes:!0,attributeOldValue:!0})}mutationObserverCallback(a){for(const b of a)if("attributes"===b.type){for(let a=0;a<codeInput.observedAttributes.length;a++)if(b.attributeName==codeInput.observedAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));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.template=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.template.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.needsHighlight=!0;break;case"lang":case"language":let d=this.codeElement,e=this.textareaElement;if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;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.needsHighlight=!0;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=b.bind(this);this.boundEventCallbacks[b]=d,codeInput.textareaSyncEvents.includes(a)?c===void 0?null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d)}):this.textareaElement.addEventListener(a,d):null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d,c)}):this.textareaElement.addEventListener(a,d,c):c===void 0?super.addEventListener(a,d):super.addEventListener(a,d,c)}removeEventListener(a,b,c=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)}get value(){return this.textareaElement.value}set value(a){return(null===a||void 0===a)&&(a=""),this.textareaElement.value=a,this.needsHighlight=!0,a}get placeholder(){return this.getAttribute("placeholder")}set placeholder(a){return this.setAttribute("placeholder",a)}get validity(){return this.textareaElement.validity}get validationMessage(){return this.textareaElement.validationMessage}setCustomValidity(a){return this.textareaElement.setCustomValidity(a)}checkValidity(){return this.textareaElement.checkValidity()}reportValidity(){return this.textareaElement.reportValidity()}pluginData={};formResetCallback(){this.value=this.initialValue}},runOnceWindowLoaded(a){codeInput.windowLoaded?a():window.addEventListener("load",a)},windowLoaded:!1};window.addEventListener("load",function(){codeInput.windowLoaded=!0}),customElements.define("code-input",codeInput.CodeInput);