@webcoder49/code-input 2.6.8 → 2.7.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.css CHANGED
@@ -20,7 +20,14 @@ code-input {
20
20
  top: 0;
21
21
  left: 0;
22
22
 
23
- color: black;
23
+ /* CSS variables rather than inline styles used for values synced from JavaScript
24
+ to keep low precedence and thus overridability
25
+ The variable names may change and are for internal use. */
26
+ /* --code-input_highlight-text-color: Set by JS to be base text color of pre code element */
27
+ /* --code-input_no-override-color: Set by JS for very short time to get whether color has been overriden */
28
+ color: var(--code-input_no-override-color, black);
29
+ /* --code-input_default-caret-color: Set by JS to be same as color property - currentColor won't work because it's lazily evaluated so gives transparent for the textarea */
30
+ caret-color: var(--code-input_default-caret-color, inherit);
24
31
  background-color: white;
25
32
 
26
33
  /* Normal inline styles */
@@ -30,13 +37,13 @@ code-input {
30
37
  --padding-right: var(--padding, 16px);
31
38
  --padding-top: var(--padding, 16px);
32
39
  --padding-bottom: var(--padding, 16px);
40
+
33
41
  height: 250px;
34
42
  font-size: inherit;
35
43
  font-family: monospace;
36
44
  text-align: start;
37
45
  line-height: 1.5; /* Inherited to child elements */
38
46
  tab-size: 2;
39
- caret-color: darkgrey;
40
47
  white-space: pre;
41
48
  padding: 0!important; /* Use --padding to set the code-input element's padding */
42
49
  display: grid;
@@ -44,7 +51,7 @@ code-input {
44
51
  grid-template-rows: 100%;
45
52
  }
46
53
 
47
- code-input * {
54
+ code-input :not(.code-input_dialog-container *) {
48
55
  box-sizing: content-box; /* Make height, width work consistently no matter the box-sizing of ancestors; dialogs can be styled as wanted so are excluded. */
49
56
  }
50
57
 
@@ -56,18 +63,23 @@ code-input textarea, code-input:not(.code-input_pre-element-styled) pre code, co
56
63
  padding-top: var(--padding-top, 16px)!important;
57
64
  padding-bottom: var(--padding-bottom, 16px)!important;
58
65
  border: 0;
66
+
59
67
  min-width: calc(100% - var(--padding-left, 16px) - var(--padding-right, 16px));
60
68
  min-height: calc(100% - var(--padding-top, 16px) - var(--padding-bottom, 16px));
61
- overflow: hidden;
62
69
  resize: none;
70
+ overflow: hidden;
63
71
  grid-row: 1;
64
72
  grid-column: 1;
65
73
  display: block;
66
74
  }
67
-
68
75
  code-input:not(.code-input_pre-element-styled) pre code, code-input.code-input_pre-element-styled pre {
69
76
  height: max-content;
70
77
  width: max-content;
78
+
79
+ /* Allow colour change to reflect properly;
80
+ transition-behavior: allow-discrete could be used but this is better supported and
81
+ works with the color property. */
82
+ transition: color 0.001s;
71
83
  }
72
84
 
73
85
  code-input:not(.code-input_pre-element-styled) pre, code-input.code-input_pre-element-styled pre code {
@@ -75,6 +87,9 @@ code-input:not(.code-input_pre-element-styled) pre, code-input.code-input_pre-el
75
87
  margin: 0!important;
76
88
  padding: 0!important;
77
89
  border: 0!important;
90
+
91
+ min-width: 100%;
92
+ min-height: 100%;
78
93
  }
79
94
 
80
95
  code-input textarea, code-input pre, code-input pre * {
@@ -85,6 +100,9 @@ code-input textarea, code-input pre, code-input pre * {
85
100
  tab-size: inherit!important;
86
101
  text-align: inherit!important;
87
102
  }
103
+ code-input textarea, code-input pre, code-input pre code {
104
+ overflow: visible!important;
105
+ }
88
106
 
89
107
  /* Make changing the text direction propogate */
90
108
  code-input textarea[dir=auto] + pre {
@@ -118,12 +136,13 @@ code-input pre {
118
136
  /* Make textarea almost completely transparent, except for caret and placeholder */
119
137
 
120
138
  code-input textarea:not([data-code-input-fallback]) {
121
- color: transparent;
122
139
  background: transparent;
123
- caret-color: inherit!important; /* Or choose your favourite color */
140
+ color: transparent;
141
+ caret-color: inherit;
124
142
  }
125
- code-input textarea::placeholder {
126
- color: lightgrey;
143
+ code-input textarea:not([data-code-input-fallback]):placeholder-shown {
144
+ /* Show placeholder */
145
+ color: var(--code-input_highlight-text-color, inherit);
127
146
  }
128
147
 
129
148
  /* Can be scrolled */
@@ -163,6 +182,11 @@ code-input .code-input_dialog-container {
163
182
 
164
183
  /* Dialog boxes' text is based on text-direction */
165
184
  text-align: inherit;
185
+
186
+ /* Allow colour change to reflect properly;
187
+ * transition-behavior: allow-discrete could be used but this is * better supported and works with the color property. */
188
+ color: inherit;
189
+ transition: color 0.001s;
166
190
  }
167
191
 
168
192
  [dir=rtl] code-input .code-input_dialog-container, code-input[dir=rtl] .code-input_dialog-container {
@@ -252,11 +276,13 @@ code-input:not(.code-input_loaded) pre, code-input:not(.code-input_loaded) texta
252
276
  code-input:has(textarea[data-code-input-fallback]) {
253
277
  padding: 0!important; /* Padding now in the textarea */
254
278
  box-sizing: content-box;
279
+
280
+ caret-color: revert; /* JS not setting the colour since no highlighting */
255
281
  }
256
282
  code-input textarea[data-code-input-fallback] {
257
283
  overflow: auto;
258
284
  background-color: inherit;
259
- color: inherit;
285
+ color: var(--code-input_highlight-text-color, inherit);
260
286
 
261
287
  /* Don't overlap with message */
262
288
  min-height: calc(100% - var(--padding-top, 16px) - 2em - var(--padding-bottom, 16px));
package/code-input.js CHANGED
@@ -152,6 +152,8 @@ var codeInput = {
152
152
  }
153
153
  },
154
154
 
155
+ stylesheetI: 0, // Increments to give different classes to each code-input element so they can have custom styles synchronised internally without affecting the inline style
156
+
155
157
  /**
156
158
  * Please see `codeInput.templates.prism` or `codeInput.templates.hljs`.
157
159
  * Templates are used in `<code-input>` elements and once registered with
@@ -445,6 +447,16 @@ var codeInput = {
445
447
  */
446
448
  dialogContainerElement = null;
447
449
 
450
+ /**
451
+ * Like style attribute, but with a specificity of 1
452
+ * element, 1 class. Present so styles can be set on only
453
+ * this element while giving other code freedom of use of
454
+ * the style attribute.
455
+ *
456
+ * For internal use only.
457
+ */
458
+ internalStyle = null;
459
+
448
460
  /**
449
461
  * Form-Associated Custom Element Callbacks
450
462
  * https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example
@@ -530,22 +542,75 @@ var codeInput = {
530
542
  this.pluginEvt("afterHighlight");
531
543
  }
532
544
 
545
+ getStyledHighlightingElement() {
546
+ if(this.templateObject.preElementStyled) {
547
+ return this.preElement;
548
+ } else {
549
+ return this.codeElement;
550
+ }
551
+ }
552
+
533
553
  /**
534
554
  * Set the size of the textarea element to the size of the pre/code element.
535
555
  */
536
556
  syncSize() {
537
557
  // Synchronise the size of the pre/code and textarea elements
538
- if(this.templateObject.preElementStyled) {
539
- this.style.backgroundColor = getComputedStyle(this.preElement).backgroundColor;
540
- this.textareaElement.style.height = getComputedStyle(this.preElement).height;
541
- this.textareaElement.style.width = getComputedStyle(this.preElement).width;
542
- } else {
543
- this.style.backgroundColor = getComputedStyle(this.codeElement).backgroundColor;
544
- this.textareaElement.style.height = getComputedStyle(this.codeElement).height;
545
- this.textareaElement.style.width = getComputedStyle(this.codeElement).width;
558
+ this.textareaElement.style.height = getComputedStyle(this.getStyledHighlightingElement()).height;
559
+ this.textareaElement.style.width = getComputedStyle(this.getStyledHighlightingElement()).width;
560
+ }
561
+
562
+ /**
563
+ * If the color attribute has been defined on the
564
+ * code-input element by external code, return true.
565
+ * Otherwise, make the aspects the color affects
566
+ * (placeholder and caret colour) be the base colour
567
+ * of the highlighted text, for best contrast, and
568
+ * return false.
569
+ */
570
+ isColorOverridenSyncIfNot() {
571
+ const oldTransition = this.style.transition;
572
+ this.style.transition = "unset";
573
+ window.requestAnimationFrame(() => {
574
+ this.internalStyle.setProperty("--code-input_no-override-color", "rgb(0, 0, 0)");
575
+ if(getComputedStyle(this).color == "rgb(0, 0, 0)") {
576
+ // May not be overriden
577
+ this.internalStyle.setProperty("--code-input_no-override-color", "rgb(255, 255, 255)");
578
+ if(getComputedStyle(this).color == "rgb(255, 255, 255)") {
579
+ // Definitely not overriden
580
+ this.internalStyle.removeProperty("--code-input_no-override-color");
581
+ this.style.transition = oldTransition;
582
+
583
+ const highlightedTextColor = getComputedStyle(this.getStyledHighlightingElement()).color;
584
+
585
+ this.internalStyle.setProperty("--code-input_highlight-text-color", highlightedTextColor);
586
+ this.internalStyle.setProperty("--code-input_default-caret-color", highlightedTextColor);
587
+ return false;
588
+ }
589
+ }
590
+ this.internalStyle.removeProperty("--code-input_no-override-color");
591
+ this.style.transition = oldTransition;
592
+ });
593
+
594
+ return true;
595
+ }
596
+
597
+ /**
598
+ * Update the aspects the color affects
599
+ * (placeholder and caret colour) to the correct
600
+ * colour: either that defined on the code-input
601
+ * element, or if none is defined externally the
602
+ * base colour of the highlighted text.
603
+ */
604
+ syncColorCompletely() {
605
+ // color of code-input element
606
+ if(this.isColorOverridenSyncIfNot()) {
607
+ // color overriden
608
+ this.internalStyle.removeProperty("--code-input_highlight-text-color");
609
+ this.internalStyle.setProperty("--code-input_default-caret-color", getComputedStyle(this).color);
546
610
  }
547
611
  }
548
612
 
613
+
549
614
  /**
550
615
  * Show some instructions to the user only if they are using keyboard navigation - for example, a prompt on how to navigate with the keyboard if Tab is repurposed.
551
616
  * @param {string} instructions The instructions to display only if keyboard navigation is being used. If it's blank, no instructions will be shown.
@@ -741,7 +806,6 @@ var codeInput = {
741
806
  this.codeElement = code;
742
807
  pre.append(code);
743
808
  this.append(pre);
744
-
745
809
  if (this.templateObject.isCode) {
746
810
  if (lang != undefined && lang != "") {
747
811
  code.classList.add("language-" + lang.toLowerCase());
@@ -780,7 +844,44 @@ var codeInput = {
780
844
  // The only element that could be resized is this code-input element.
781
845
  this.syncSize();
782
846
  });
783
- resizeObserver.observe(this.textareaElement);
847
+ resizeObserver.observe(this);
848
+
849
+
850
+ // Add internal style as non-externally-overridable alternative to style attribute for e.g. syncing color
851
+ this.classList.add("code-input_styles_" + codeInput.stylesheetI);
852
+ const stylesheet = document.createElement("style");
853
+ stylesheet.innerHTML = "code-input.code-input_styles_" + codeInput.stylesheetI + " {}";
854
+ this.appendChild(stylesheet);
855
+ this.internalStyle = stylesheet.sheet.cssRules[0].style;
856
+ codeInput.stylesheetI++;
857
+
858
+ // Synchronise colors
859
+ const preColorChangeCallback = (evt) => {
860
+ if(evt.propertyName == "color") {
861
+ this.isColorOverridenSyncIfNot();
862
+ }
863
+ };
864
+ this.preElement.addEventListener("transitionend", preColorChangeCallback);
865
+ this.preElement.addEventListener("-webkit-transitionend", preColorChangeCallback);
866
+ const thisColorChangeCallback = (evt) => {
867
+ if(evt.propertyName == "color") {
868
+ this.syncColorCompletely();
869
+ }
870
+ if(evt.target == this.dialogContainerElement) {
871
+ evt.stopPropagation();
872
+ // Prevent bubbling because code-input
873
+ // transitionend is separate
874
+ }
875
+ };
876
+ // Not on this element so CSS transition property does not override publicly-visible one
877
+ this.dialogContainerElement.addEventListener("transitionend", thisColorChangeCallback);
878
+ this.dialogContainerElement.addEventListener("-webkit-transitionend", thisColorChangeCallback);
879
+
880
+ // For when this code-input element has an externally-defined, different-duration transition
881
+ this.addEventListener("transitionend", thisColorChangeCallback);
882
+ this.addEventListener("-webkit-transitionend", thisColorChangeCallback);
883
+
884
+ this.syncColorCompletely();
784
885
 
785
886
  this.classList.add("code-input_loaded");
786
887
  }
@@ -938,7 +1039,9 @@ var codeInput = {
938
1039
  code.classList.add("language-" + newValue);
939
1040
  }
940
1041
 
941
- if (mainTextarea.placeholder == oldValue) mainTextarea.placeholder = newValue;
1042
+ if (mainTextarea.placeholder == oldValue || oldValue == null && mainTextarea.placeholder == "") {
1043
+ mainTextarea.placeholder = newValue;
1044
+ }
942
1045
 
943
1046
  this.scheduleHighlight();
944
1047
 
@@ -1 +1 @@
1
- code-input{display:block;overflow-y:auto;overflow-x:auto;position:relative;top:0;left:0;color:#000;background-color:#fff;margin:8px;--padding:16px;--padding-left:var(--padding, 16px);--padding-right:var(--padding, 16px);--padding-top:var(--padding, 16px);--padding-bottom:var(--padding, 16px);height:250px;font-size:inherit;font-family:monospace;text-align:start;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 *{box-sizing:content-box}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-left:var(--padding-left,16px)!important;padding-right:var(--padding-right,16px)!important;padding-top:var(--padding-top,16px)!important;padding-bottom:var(--padding-bottom,16px)!important;border:0;min-width:calc(100% - var(--padding-left,16px) - var(--padding-right,16px));min-height:calc(100% - var(--padding-top,16px) - var(--padding-bottom,16px));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;border:0!important}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;text-align:inherit!important}code-input textarea[dir=auto]+pre{unicode-bidi:plaintext}code-input textarea[dir=ltr]+pre{direction:ltr}code-input textarea[dir=rtl]+pre{direction:rtl}code-input pre,code-input textarea{grid-column:1;grid-row:1}code-input textarea:not([data-code-input-fallback]){z-index:1}code-input pre{z-index:0}code-input textarea:not([data-code-input-fallback]){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:has(textarea:focus):not(.code-input_mouse-focused){outline:2px solid currentColor}code-input .code-input_dialog-container{z-index:2;position:sticky;grid-row:1;grid-column:1;top:0;left:0;margin:0;padding:0;height:0;width:100%;text-align:inherit}[dir=rtl] code-input .code-input_dialog-container,code-input[dir=rtl] .code-input_dialog-container{left:unset;right:0}code-input .code-input_dialog-container .code-input_keyboard-navigation-instructions{top:0;left:0;display:block;position:absolute;top:0;left:0;background-color:#000;color:#fff;padding:2px;padding-left:var(--padding-left,16px);padding-right:var(--padding-right,16px);margin:0;text-wrap:balance;overflow-x:hidden;overflow-y:auto;width:100%;box-sizing:border-box;height:3em}code-input .code-input_dialog-container .code-input_keyboard-navigation-instructions:empty,code-input.code-input_mouse-focused .code-input_dialog-container .code-input_keyboard-navigation-instructions,code-input:not(:has(textarea:not([data-code-input-fallback]):focus)) .code-input_dialog-container .code-input_keyboard-navigation-instructions{display:none}code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused) textarea,code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused).code-input_pre-element-styled pre,code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused):not(.code-input_pre-element-styled) pre code{padding-top:calc(var(--padding-top,16px) + 3em)!important;min-height:calc(100% - var(--padding-top,16px) - 3em - var(--padding-bottom,16px))}code-input:not(.code-input_loaded){padding-left:var(--padding-left,16px)!important;padding-right:var(--padding-right,16px)!important;padding:var(--padding-top,16px)!important;padding:var(--padding-bottom,16px)!important;overflow:hidden;display:block;box-sizing:border-box}code-input:not(.code-input_loaded)::after{content:"No highlighting. JavaScript support is disabled or insufficient, or codeInput.registerTemplate has not been called.";display:block;position:absolute;bottom:0;left:var(--padding-left,16px);width:calc(100% - var(--padding-left,1.6px) - var(--padding-right,1.6px));overflow-x:auto;border-top:1px solid currentColor;outline-top:0;background-color:inherit;color:inherit;margin:0;padding:0;height:2em}code-input:not(.code-input_loaded) pre,code-input:not(.code-input_loaded) textarea:not([data-code-input-fallback]){opacity:0}code-input:has(textarea[data-code-input-fallback]){padding:0!important;box-sizing:content-box}code-input textarea[data-code-input-fallback]{overflow:auto;background-color:inherit;color:inherit;min-height:calc(100% - var(--padding-top,16px) - 2em - var(--padding-bottom,16px))}
1
+ code-input{color:var(--code-input_no-override-color,black);caret-color:var(--code-input_default-caret-color,inherit);--padding:16px;--padding-left:var(--padding,16px);--padding-right:var(--padding,16px);--padding-top:var(--padding,16px);--padding-bottom:var(--padding,16px);height:250px;font-size:inherit;text-align:start;tab-size:2;white-space:pre;background-color:#fff;grid-template-rows:100%;grid-template-columns:100%;margin:8px;font-family:monospace;line-height:1.5;display:grid;position:relative;top:0;left:0;overflow:auto;padding:0!important}code-input :not(.code-input_dialog-container *){box-sizing:content-box}code-input textarea,code-input:not(.code-input_pre-element-styled) pre code,code-input.code-input_pre-element-styled pre{min-width:calc(100% - var(--padding-left,16px) - var(--padding-right,16px));min-height:calc(100% - var(--padding-top,16px) - var(--padding-bottom,16px));resize:none;border:0;grid-area:1/1;display:block;overflow:hidden;padding-left:var(--padding-left,16px)!important;padding-right:var(--padding-right,16px)!important;padding-top:var(--padding-top,16px)!important;padding-bottom:var(--padding-bottom,16px)!important;margin:0!important}code-input:not(.code-input_pre-element-styled) pre code,code-input.code-input_pre-element-styled pre{width:max-content;height:max-content;transition:color 1ms}code-input:not(.code-input_pre-element-styled) pre,code-input.code-input_pre-element-styled pre code{min-width:100%;min-height:100%;border:0!important;margin:0!important;padding:0!important}code-input textarea,code-input pre,code-input pre *{font-size:inherit!important;font-family:inherit!important;line-height:inherit!important;tab-size:inherit!important;text-align:inherit!important}code-input textarea,code-input pre,code-input pre code{overflow:visible!important}code-input textarea[dir=auto]+pre{unicode-bidi:plaintext}code-input textarea[dir=ltr]+pre{direction:ltr}code-input textarea[dir=rtl]+pre{direction:rtl}code-input textarea,code-input pre{grid-area:1/1}code-input textarea:not([data-code-input-fallback]){z-index:1}code-input pre{z-index:0}code-input textarea:not([data-code-input-fallback]){color:#0000;caret-color:inherit;background:0 0}code-input textarea:not([data-code-input-fallback]):placeholder-shown{color:var(--code-input_highlight-text-color,inherit)}code-input textarea,code-input pre{white-space:inherit;word-spacing:normal;word-break:normal;word-wrap:normal}code-input textarea{resize:none;outline:none!important}code-input:has(textarea:focus):not(.code-input_mouse-focused){outline:2px solid}code-input .code-input_dialog-container{z-index:2;width:100%;height:0;text-align:inherit;color:inherit;grid-area:1/1;margin:0;padding:0;transition:color 1ms;position:sticky;top:0;left:0}[dir=rtl] code-input .code-input_dialog-container,code-input[dir=rtl] .code-input_dialog-container{left:unset;right:0}code-input .code-input_dialog-container .code-input_keyboard-navigation-instructions{color:#fff;padding:2px;padding-left:var(--padding-left,16px);padding-right:var(--padding-right,16px);text-wrap:balance;box-sizing:border-box;background-color:#000;width:100%;height:3em;margin:0;display:block;position:absolute;top:0;left:0;overflow:hidden auto}code-input:not(:has(textarea:not([data-code-input-fallback]):focus)) .code-input_dialog-container .code-input_keyboard-navigation-instructions,code-input.code-input_mouse-focused .code-input_dialog-container .code-input_keyboard-navigation-instructions,code-input .code-input_dialog-container .code-input_keyboard-navigation-instructions:empty{display:none}code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused) textarea,code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused):not(.code-input_pre-element-styled) pre code,code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused).code-input_pre-element-styled pre{min-height:calc(100% - var(--padding-top,16px) - 3em - var(--padding-bottom,16px));padding-top:calc(var(--padding-top,16px) + 3em)!important}code-input:not(.code-input_loaded){box-sizing:border-box;display:block;overflow:hidden;padding-left:var(--padding-left,16px)!important;padding-right:var(--padding-right,16px)!important;padding:var(--padding-top,16px)!important;padding:var(--padding-bottom,16px)!important}code-input:not(.code-input_loaded):after{content:"No highlighting. JavaScript support is disabled or insufficient, or codeInput.registerTemplate has not been called.";bottom:0;left:var(--padding-left,16px);width:calc(100% - var(--padding-left,1.6px) - var(--padding-right,1.6px));outline-top:0;background-color:inherit;color:inherit;border-top:1px solid;height:2em;margin:0;padding:0;display:block;position:absolute;overflow-x:auto}code-input:not(.code-input_loaded) pre,code-input:not(.code-input_loaded) textarea:not([data-code-input-fallback]){opacity:0}code-input:has(textarea[data-code-input-fallback]){box-sizing:content-box;caret-color:revert;padding:0!important}code-input textarea[data-code-input-fallback]{background-color:inherit;color:var(--code-input_highlight-text-color,inherit);min-height:calc(100% - var(--padding-top,16px) - 2em - var(--padding-bottom,16px));overflow:auto}
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,"&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.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);
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()}},stylesheetI:0,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;internalStyle=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")}getStyledHighlightingElement(){return this.templateObject.preElementStyled?this.preElement:this.codeElement}syncSize(){this.textareaElement.style.height=getComputedStyle(this.getStyledHighlightingElement()).height,this.textareaElement.style.width=getComputedStyle(this.getStyledHighlightingElement()).width}isColorOverridenSyncIfNot(){const a=this.style.transition;return this.style.transition="unset",window.requestAnimationFrame(()=>{if(this.internalStyle.setProperty("--code-input_no-override-color","rgb(0, 0, 0)"),"rgb(0, 0, 0)"==getComputedStyle(this).color&&(this.internalStyle.setProperty("--code-input_no-override-color","rgb(255, 255, 255)"),"rgb(255, 255, 255)"==getComputedStyle(this).color)){this.internalStyle.removeProperty("--code-input_no-override-color"),this.style.transition=a;const b=getComputedStyle(this.getStyledHighlightingElement()).color;return this.internalStyle.setProperty("--code-input_highlight-text-color",b),this.internalStyle.setProperty("--code-input_default-caret-color",b),!1}this.internalStyle.removeProperty("--code-input_no-override-color"),this.style.transition=a}),!0}syncColorCompletely(){this.isColorOverridenSyncIfNot()&&(this.internalStyle.removeProperty("--code-input_highlight-text-color"),this.internalStyle.setProperty("--code-input_default-caret-color",getComputedStyle(this).color))}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,"&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.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),this.classList.add("code-input_styles_"+codeInput.stylesheetI);const q=document.createElement("style");q.innerHTML="code-input.code-input_styles_"+codeInput.stylesheetI+" {}",this.appendChild(q),this.internalStyle=q.sheet.cssRules[0].style,codeInput.stylesheetI++;const r=a=>{"color"==a.propertyName&&this.isColorOverridenSyncIfNot()};this.preElement.addEventListener("transitionend",r),this.preElement.addEventListener("-webkit-transitionend",r);const s=a=>{"color"==a.propertyName&&this.syncColorCompletely(),a.target==this.dialogContainerElement&&a.stopPropagation()};this.dialogContainerElement.addEventListener("transitionend",s),this.dialogContainerElement.addEventListener("-webkit-transitionend",s),this.addEventListener("transitionend",s),this.addEventListener("-webkit-transitionend",s),this.syncColorCompletely(),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||null==b&&""==e.placeholder)&&(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,11 @@ 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.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.).**
14
+ ## Download
15
+
16
+ *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.7.1), [in a ZIP archive](/release/code-input-js-v2.7.1.zip), [in a TAR.GZ archive](/release/code-input-js-v2.7.1.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.).**
17
+
18
+ [Want to contribute to the code? You're very welcome to! See here.](#contributing)
15
19
 
16
20
  ## Get Started with a Demo
17
21
 
@@ -33,9 +37,9 @@ more use cases.
33
37
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.30/components/prism-core.min.js" data-manual></script><!--Remove data-manual if also using Prism normally-->
34
38
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.30/plugins/autoloader/prism-autoloader.min.js"></script>
35
39
  <!--2. Import code-input-js-->
36
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
37
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
38
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/indent.min.js"></script>
40
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
41
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
42
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/indent.min.js"></script>
39
43
  <!--3. Join code-input-js to highlighter-->
40
44
  <script>codeInput.registerTemplate("syntax-highlighted", new codeInput.templates.Prism(Prism, [new codeInput.plugins.Indent()]));</script>
41
45
  </head>
@@ -72,13 +76,13 @@ console.log("Hello, World!");</textarea></code-input>
72
76
 
73
77
  <!--Import code-input-->
74
78
  <!--The same goes for downloaded versions.-->
75
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
76
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
79
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
80
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
77
81
 
78
82
  <!--Import some code-input plugins-->
79
83
  <!--The same goes for downloaded versions.-->
80
84
  <!--Plugin files are here: https://code-input-js.org/plugins.-->
81
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/indent.min.js"></script>
85
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/indent.min.js"></script>
82
86
 
83
87
  <!--Register code-input template-->
84
88
  <!--This can be before the code-input element is created, in which case it will defer the registration of all code-input
@@ -132,13 +136,13 @@ console.log("Hello, World!");</textarea></code-input>
132
136
 
133
137
  <!--Import code-input-->
134
138
  <!--The same goes for downloaded versions.-->
135
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
136
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
139
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
140
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
137
141
 
138
142
  <!--Import some code-input plugins-->
139
143
  <!--The same goes for downloaded versions.-->
140
144
  <!--Plugin files are here: https://code-input-js.org/plugins.-->
141
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/indent.min.js"></script>
145
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/indent.min.js"></script>
142
146
 
143
147
  <!--Register code-input template-->
144
148
  <!--This can be before the code-input element is created, in which case it will defer the registration of all code-input
@@ -180,13 +184,13 @@ console.log("Hello, World!");</textarea></code-input>
180
184
 
181
185
  <!--Import code-input-->
182
186
  <!--The same goes for downloaded versions.-->
183
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
184
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
187
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
188
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
185
189
 
186
190
  <!--Import some code-input plugins-->
187
191
  <!--The same goes for downloaded versions.-->
188
192
  <!--Plugin files are here: https://code-input-js.org/plugins.-->
189
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/indent.min.js"></script>
193
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/indent.min.js"></script>
190
194
 
191
195
  <!--Register code-input template-->
192
196
  <!--This can be before the code-input element is created, in which case it will defer the registration of all code-input
@@ -313,6 +317,8 @@ something like [CodeMirror](https://codemirror.net/),
313
317
 
314
318
  ## Contribute Bug Reports / Code / Docs {#contributing}
315
319
 
320
+ **An even more lightweight, flexible and clean major version 3 is being planned. Please come and participate with your feedback/ideas [on GitHub](https://github.com/WebCoder49/code-input/issues/190) or [via email to code-input-js+v3@webcoder49.dev](mailto:code-input-js+v3@webcoder49.dev)!**
321
+
316
322
  🎉 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
323
 
318
324
  *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!*
@@ -7,6 +7,10 @@ title = 'Styling `code-input` elements with CSS'
7
7
  > Contributors: 2025 Oliver Geer
8
8
 
9
9
  `code-input` elements can be styled like `textarea` elements in most cases; however, there are some exceptions:
10
- * The CSS variable `--padding` should be used rather than the property `padding` (e.g. `<code-input style="--padding: 10px;">...`), or `--padding-left`, `--padding-right`, `--padding-top` and `--padding-bottom` instead of the CSS properties of the same names. For technical reasons, the value must have a unit (i.e. `0px`, not `0`).
10
+ * The CSS variable `--padding` should be used rather than the property `padding` (e.g. `<code-input style="--padding: 10px;">...`), or `--padding-left`, `--padding-right`, `--padding-top` and `--padding-bottom` instead of the CSS properties of the same names. For technical reasons, the value must have a unit (i.e. `0px`, not `0`). To avoid overcomplicating the code, this padding is always *included in* any width/heights of `code-input` elements, so if you want to style `textarea`s and `code-input` elements with best consistency set `box-sizing: border-box` on them.
11
11
  * Background colours set on `code-input` elements will not work with highlighters that set background colours themselves - use `(code-input's selector) pre[class*="language-"]` for Prism.js or `.hljs` for highlight.js to target the highlighted element with higher specificity than the highlighter's theme. You may also set the `background-color` of the code-input element for its appearance when its template is unregistered / there is no JavaScript.
12
+ * The caret and placeholder colour by default follow and give good contrast with the highlighted theme. Setting a CSS rule for `color` and/or `caret-color` properties on the code-input element will override this behaviour.
13
+ * For technical reasons, `code-input:focus` won't match anything. Use `code-input:has(textarea:focus)` instead.
12
14
  * For now, elements on top of `code-input` elements should have a CSS `z-index` at least 3 greater than the `code-input` element.
15
+
16
+ Please do **not** use `className` in JavaScript referring to code-input elements, because the code-input library needs to add its own classes to code-input elements for easier progressive enhancement. You can, however, use `classList` and `style` as much as you want - it will make your code cleaner anyway.
@@ -6,6 +6,19 @@ title = '`code-input` vs the `textarea` in JavaScript'
6
6
 
7
7
  > Contributors: 2025 Oliver Geer
8
8
 
9
- Once registered, `code-input` elements support the JavaScript properties and events used with a `textarea` element, because they are built around them. Try swapping out your `textarea` element in your JavaScript application for a `code-input`! If it doesn't work, [submit a bug report](https://github.com/WebCoder49/code-input/issues).
9
+ [Once registered](#code-input_load), `code-input` elements support the JavaScript properties and events used with a `textarea` element, because they are built around them. Try swapping out your `textarea` element in your JavaScript application for a `code-input`! If it doesn't work, [submit a bug report](https://github.com/WebCoder49/code-input/issues).
10
10
 
11
11
  If you want to replace a `textarea` with a `code-input` in an application that doesn't need JavaScript, [look here](../forms). We support HTML5 forms, and progressive enhancement so JavaScript isn't needed!
12
+
13
+ ## The `code-input_load` event {code-input_load}
14
+
15
+ Each `code-input` element fires a `code-input_load` event when it, its template and its plugins have been fully registered. You should carry out initialisation code for `code-input` elements in a handler for this event:
16
+ ```javascript
17
+ // TODO: Get code-input element as codeInputElement
18
+ codeInputElement.addEventListener("code-input_load", () => {
19
+ // TODO: Initialisation code
20
+ // TODO: Add event handlers to the element here.
21
+ });
22
+ ```
23
+
24
+ For backwards compatibility, you should also implement the subset of the functionality that doesn't require `code-input.js` on the `<textarea data-code-input-fallback>` element before load, if you have one. For backwards compatibility and technical reasons, event handlers registered in HTML attributes like `onchange` of the textarea will be passed to the code-input element when it is registered, but event listeners registered like that above will not - this should be cleaned up in major version 3.
@@ -23,13 +23,13 @@ Right now, you can only add one plugin of each type (e.g. one SelectTokenCallbac
23
23
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js" data-manual></script><!--Remove data-manual if also using Prism normally-->
24
24
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
25
25
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css"></link>
26
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
27
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
26
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
27
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
28
28
 
29
29
  <!--Import-->
30
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/auto-close-brackets.min.js"></script>
30
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/auto-close-brackets.min.js"></script>
31
31
  <!--Not necessary, but works very well with the Indent plugin-->
32
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/indent.min.js"></script>
32
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/indent.min.js"></script>
33
33
 
34
34
  <script>
35
35
  codeInput.registerTemplate("syntax-highlighted", new codeInput.templates.Prism(Prism, [
@@ -60,12 +60,12 @@ Right now, you can only add one plugin of each type (e.g. one SelectTokenCallbac
60
60
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js" data-manual></script><!--Remove data-manual if also using Prism normally-->
61
61
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
62
62
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css"></link>
63
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
64
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
63
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
64
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
65
65
 
66
66
  <!--Import-->
67
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/autocomplete.min.js"></script>
68
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/autocomplete.min.css">
67
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/autocomplete.min.js"></script>
68
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/autocomplete.min.css">
69
69
 
70
70
 
71
71
  <script>
@@ -95,6 +95,7 @@ Right now, you can only add one plugin of each type (e.g. one SelectTokenCallbac
95
95
  let autocompleteButton = document.createElement("button");
96
96
  autocompleteButton.innerHTML = "<i>" + tag.substring(0, start_tag.length) + "</i>" + tag.substring(start_tag.length, tag.length);
97
97
  autocompleteButton.addEventListener("click", () => {
98
+ textarea.parentElement.focus();
98
99
  document.execCommand("insertText", false, tag.substring(start_tag.length, tag.length));
99
100
  popupElem.innerHTML = ""; // On popup
100
101
  });
@@ -103,18 +104,18 @@ Right now, you can only add one plugin of each type (e.g. one SelectTokenCallbac
103
104
  });
104
105
 
105
106
  if(popupElem.firstElementChild != null) {
106
- popupElem.firstElementChild.innerHTML += "[Tab]";
107
+ popupElem.firstElementChild.innerHTML += "[Tab]";
107
108
  }
108
109
  textarea.addEventListener("keydown", (event) => {
109
- if(event.key == "Tab" && popupElem.firstElementChild != null) {
110
- popupElem.firstElementChild.click();
111
- event.preventDefault();
112
- }
110
+ if(event.key == "Tab" && popupElem.firstElementChild != null) {
111
+ popupElem.firstElementChild.click();
112
+ event.preventDefault();
113
+ }
113
114
  })
114
115
  }
115
116
  // Pass at register
116
117
  codeInput.registerTemplate("syntax-highlighted", new codeInput.templates.Prism(Prism, [
117
- new codeInput.plugins.Autocomplete(updatePopup) // See above
118
+ new codeInput.plugins.Autocomplete(updatePopup) // See above
118
119
  ]));
119
120
  </script>
120
121
  <p>Start typing some HTML tags to see the autocomplete in action. You can click an autocomplete suggestion, or press the Tab key to select the first.</p>
@@ -134,12 +135,12 @@ Right now, you can only add one plugin of each type (e.g. one SelectTokenCallbac
134
135
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js" data-manual></script><!--Remove data-manual if also using Prism normally-->
135
136
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
136
137
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css"></link>
137
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
138
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
138
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
139
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
139
140
 
140
141
  <!--Import-->
141
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/find-and-replace.min.js"></script>
142
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/find-and-replace.min.css"/>
142
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/find-and-replace.min.js"></script>
143
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/find-and-replace.min.css"/>
143
144
 
144
145
  <script>
145
146
  let findAndReplacePlugin = new codeInput.plugins.FindAndReplace(
@@ -183,14 +184,14 @@ Hickory dickory dock.</code-input>
183
184
  <!--Not necessary, but works very well with the Prism line-numbers plugin-->
184
185
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
185
186
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.css">
186
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
187
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
187
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
188
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
188
189
 
189
190
  <!--Import-->
190
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/go-to-line.min.js"></script>
191
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/go-to-line.min.css"/>
191
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/go-to-line.min.js"></script>
192
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/go-to-line.min.css"/>
192
193
  <!--Not necessary, but works very well with the Prism line-numbers plugin-->
193
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/prism-line-numbers.min.css"/>
194
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/prism-line-numbers.min.css"/>
194
195
 
195
196
  <script>
196
197
  let goToLinePlugin = new codeInput.plugins.GoToLine(
@@ -227,11 +228,11 @@ Hickory dickory dock.</code-input>
227
228
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js" data-manual></script><!--Remove data-manual if also using Prism normally-->
228
229
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
229
230
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css"></link>
230
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
231
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
231
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
232
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
232
233
 
233
234
  <!--Import-->
234
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/indent.min.js"></script>
235
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/indent.min.js"></script>
235
236
 
236
237
  <script>
237
238
  // Programatically opening the dialogs, to integrate with your user interface
@@ -500,11 +501,11 @@ Hickory dickory dock.</code-input>
500
501
  </script>
501
502
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/match-braces/prism-match-braces.min.css"/>
502
503
 
503
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
504
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
504
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
505
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
505
506
 
506
507
  <!--Import-->
507
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/select-token-callbacks.min.js"></script>
508
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/select-token-callbacks.min.js"></script>
508
509
  </head>
509
510
  <body>
510
511
  <!--For convenience, this demo uses files from JSDelivr CDN; for more privacy and security download and host them yourself.-->
@@ -567,12 +568,12 @@ See https://github.com/WebCoder49/code-input/issues?q=is%3Aissue%20state%3Aopen%
567
568
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js" data-manual></script><!--Remove data-manual if also using Prism normally-->
568
569
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
569
570
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css"></link>
570
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
571
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
571
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
572
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
572
573
 
573
574
  <!--Import-->
574
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/special-chars.min.js"></script>
575
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/special-chars.min.css"></script>
575
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/special-chars.min.js"></script>
576
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/special-chars.min.css"></script>
576
577
 
577
578
  <script>
578
579
  codeInput.registerTemplate("syntax-highlighted", new codeInput.templates.Prism(Prism, [
@@ -612,12 +613,12 @@ See https://github.com/WebCoder49/code-input/issues?q=is%3Aissue%20state%3Aopen%
612
613
  <!--highlight.js+code-input-->
613
614
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css">
614
615
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
615
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
616
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
616
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
617
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
617
618
 
618
619
 
619
620
  <!--Import-->
620
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/autodetect.min.js"></script>
621
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/autodetect.min.js"></script>
621
622
 
622
623
  <script>
623
624
  codeInput.registerTemplate("syntax-highlighted", new codeInput.templates.Hljs(hljs, [
@@ -625,7 +626,7 @@ See https://github.com/WebCoder49/code-input/issues?q=is%3Aissue%20state%3Aopen%
625
626
  new codeInput.plugins.Autodetect()
626
627
  ]));
627
628
  </script>
628
- <p>Start typing code of any language. <st;;;rong>Detected language: <span id="language"></span></strong>. Inaccurate language detection should be reported to <a target="_blank" href="highlightjs.org">highlight.js</a>, not code-input-js.</p>
629
+ <p>Start typing code of any language. <strong>Detected language: <span id="language"></span></strong>. Inaccurate language detection should be reported to <a target="_blank" href="https://highlightjs.org">highlight.js</a>, not code-input-js.</p>
629
630
  <code-input oninput="document.getElementById('language').textContent = this.getAttribute('language');"></code-input>
630
631
  <p></p>
631
632
  </body>
@@ -645,14 +646,14 @@ See https://github.com/WebCoder49/code-input/issues?q=is%3Aissue%20state%3Aopen%
645
646
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js" data-manual></script><!--Remove data-manual if also using Prism normally-->
646
647
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
647
648
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css"></link>
648
- <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.js"></script>
649
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/code-input.min.css">
649
+ <script src="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.js"></script>
650
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/code-input.min.css">
650
651
 
651
652
 
652
653
  <!--Import-->
653
654
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
654
655
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.css">
655
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.6/plugins/prism-line-numbers.min.css"/>
656
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/WebCoder49/code-input@2.7/plugins/prism-line-numbers.min.css"/>
656
657
 
657
658
  <script>
658
659
  codeInput.registerTemplate("syntax-highlighted", new codeInput.templates.Prism(Prism, [
@@ -154,6 +154,8 @@ var codeInput = {
154
154
  }
155
155
  },
156
156
 
157
+ stylesheetI: 0, // Increments to give different classes to each code-input element so they can have custom styles synchronised internally without affecting the inline style
158
+
157
159
  /**
158
160
  * Please see `codeInput.templates.prism` or `codeInput.templates.hljs`.
159
161
  * Templates are used in `<code-input>` elements and once registered with
@@ -343,6 +345,16 @@ var codeInput = {
343
345
  */
344
346
  dialogContainerElement = null;
345
347
 
348
+ /**
349
+ * Like style attribute, but with a specificity of 1
350
+ * element, 1 class. Present so styles can be set on only
351
+ * this element while giving other code freedom of use of
352
+ * the style attribute.
353
+ *
354
+ * For internal use only.
355
+ */
356
+ internalStyle = null;
357
+
346
358
  /**
347
359
  * Form-Associated Custom Element Callbacks
348
360
  * https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example
@@ -428,22 +440,75 @@ var codeInput = {
428
440
  this.pluginEvt("afterHighlight");
429
441
  }
430
442
 
443
+ getStyledHighlightingElement() {
444
+ if(this.templateObject.preElementStyled) {
445
+ return this.preElement;
446
+ } else {
447
+ return this.codeElement;
448
+ }
449
+ }
450
+
431
451
  /**
432
452
  * Set the size of the textarea element to the size of the pre/code element.
433
453
  */
434
454
  syncSize() {
435
455
  // Synchronise the size of the pre/code and textarea elements
436
- if(this.templateObject.preElementStyled) {
437
- this.style.backgroundColor = getComputedStyle(this.preElement).backgroundColor;
438
- this.textareaElement.style.height = getComputedStyle(this.preElement).height;
439
- this.textareaElement.style.width = getComputedStyle(this.preElement).width;
440
- } else {
441
- this.style.backgroundColor = getComputedStyle(this.codeElement).backgroundColor;
442
- this.textareaElement.style.height = getComputedStyle(this.codeElement).height;
443
- this.textareaElement.style.width = getComputedStyle(this.codeElement).width;
456
+ this.textareaElement.style.height = getComputedStyle(this.getStyledHighlightingElement()).height;
457
+ this.textareaElement.style.width = getComputedStyle(this.getStyledHighlightingElement()).width;
458
+ }
459
+
460
+ /**
461
+ * If the color attribute has been defined on the
462
+ * code-input element by external code, return true.
463
+ * Otherwise, make the aspects the color affects
464
+ * (placeholder and caret colour) be the base colour
465
+ * of the highlighted text, for best contrast, and
466
+ * return false.
467
+ */
468
+ isColorOverridenSyncIfNot() {
469
+ const oldTransition = this.style.transition;
470
+ this.style.transition = "unset";
471
+ window.requestAnimationFrame(() => {
472
+ this.internalStyle.setProperty("--code-input_no-override-color", "rgb(0, 0, 0)");
473
+ if(getComputedStyle(this).color == "rgb(0, 0, 0)") {
474
+ // May not be overriden
475
+ this.internalStyle.setProperty("--code-input_no-override-color", "rgb(255, 255, 255)");
476
+ if(getComputedStyle(this).color == "rgb(255, 255, 255)") {
477
+ // Definitely not overriden
478
+ this.internalStyle.removeProperty("--code-input_no-override-color");
479
+ this.style.transition = oldTransition;
480
+
481
+ const highlightedTextColor = getComputedStyle(this.getStyledHighlightingElement()).color;
482
+
483
+ this.internalStyle.setProperty("--code-input_highlight-text-color", highlightedTextColor);
484
+ this.internalStyle.setProperty("--code-input_default-caret-color", highlightedTextColor);
485
+ return false;
486
+ }
487
+ }
488
+ this.internalStyle.removeProperty("--code-input_no-override-color");
489
+ this.style.transition = oldTransition;
490
+ });
491
+
492
+ return true;
493
+ }
494
+
495
+ /**
496
+ * Update the aspects the color affects
497
+ * (placeholder and caret colour) to the correct
498
+ * colour: either that defined on the code-input
499
+ * element, or if none is defined externally the
500
+ * base colour of the highlighted text.
501
+ */
502
+ syncColorCompletely() {
503
+ // color of code-input element
504
+ if(this.isColorOverridenSyncIfNot()) {
505
+ // color overriden
506
+ this.internalStyle.removeProperty("--code-input_highlight-text-color");
507
+ this.internalStyle.setProperty("--code-input_default-caret-color", getComputedStyle(this).color);
444
508
  }
445
509
  }
446
510
 
511
+
447
512
  /**
448
513
  * Show some instructions to the user only if they are using keyboard navigation - for example, a prompt on how to navigate with the keyboard if Tab is repurposed.
449
514
  * @param {string} instructions The instructions to display only if keyboard navigation is being used. If it's blank, no instructions will be shown.
@@ -639,7 +704,6 @@ var codeInput = {
639
704
  this.codeElement = code;
640
705
  pre.append(code);
641
706
  this.append(pre);
642
-
643
707
  if (this.templateObject.isCode) {
644
708
  if (lang != undefined && lang != "") {
645
709
  code.classList.add("language-" + lang.toLowerCase());
@@ -678,7 +742,44 @@ var codeInput = {
678
742
  // The only element that could be resized is this code-input element.
679
743
  this.syncSize();
680
744
  });
681
- resizeObserver.observe(this.textareaElement);
745
+ resizeObserver.observe(this);
746
+
747
+
748
+ // Add internal style as non-externally-overridable alternative to style attribute for e.g. syncing color
749
+ this.classList.add("code-input_styles_" + codeInput.stylesheetI);
750
+ const stylesheet = document.createElement("style");
751
+ stylesheet.innerHTML = "code-input.code-input_styles_" + codeInput.stylesheetI + " {}";
752
+ this.appendChild(stylesheet);
753
+ this.internalStyle = stylesheet.sheet.cssRules[0].style;
754
+ codeInput.stylesheetI++;
755
+
756
+ // Synchronise colors
757
+ const preColorChangeCallback = (evt) => {
758
+ if(evt.propertyName == "color") {
759
+ this.isColorOverridenSyncIfNot();
760
+ }
761
+ };
762
+ this.preElement.addEventListener("transitionend", preColorChangeCallback);
763
+ this.preElement.addEventListener("-webkit-transitionend", preColorChangeCallback);
764
+ const thisColorChangeCallback = (evt) => {
765
+ if(evt.propertyName == "color") {
766
+ this.syncColorCompletely();
767
+ }
768
+ if(evt.target == this.dialogContainerElement) {
769
+ evt.stopPropagation();
770
+ // Prevent bubbling because code-input
771
+ // transitionend is separate
772
+ }
773
+ };
774
+ // Not on this element so CSS transition property does not override publicly-visible one
775
+ this.dialogContainerElement.addEventListener("transitionend", thisColorChangeCallback);
776
+ this.dialogContainerElement.addEventListener("-webkit-transitionend", thisColorChangeCallback);
777
+
778
+ // For when this code-input element has an externally-defined, different-duration transition
779
+ this.addEventListener("transitionend", thisColorChangeCallback);
780
+ this.addEventListener("-webkit-transitionend", thisColorChangeCallback);
781
+
782
+ this.syncColorCompletely();
682
783
 
683
784
  this.classList.add("code-input_loaded");
684
785
  }
@@ -836,7 +937,9 @@ var codeInput = {
836
937
  code.classList.add("language-" + newValue);
837
938
  }
838
939
 
839
- if (mainTextarea.placeholder == oldValue) mainTextarea.placeholder = newValue;
940
+ if (mainTextarea.placeholder == oldValue || oldValue == null && mainTextarea.placeholder == "") {
941
+ mainTextarea.placeholder = newValue;
942
+ }
840
943
 
841
944
  this.scheduleHighlight();
842
945
 
@@ -36,6 +36,7 @@ plugins.Autocomplete = class extends Plugin {
36
36
  codeInput.appendChild(popupElem);
37
37
 
38
38
  let testPosPre = document.createElement("pre");
39
+ testPosPre.classList.add("code-input_autocomplete_invisiblepre"); // Hide visually
39
40
  testPosPre.setAttribute("aria-hidden", true); // Hide for screen readers
40
41
  if(codeInput.templateObject.preElementStyled) {
41
42
  testPosPre.classList.add("code-input_autocomplete_testpos");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webcoder49/code-input",
3
- "version": "2.6.8",
3
+ "version": "2.7.1",
4
4
  "description": "An editable &lt;textarea&gt; that supports *any* syntax highlighting algorithm, for code or something else. Also, added plugins.",
5
5
  "browser": "code-input.js",
6
6
  "exports": {
@@ -9,7 +9,6 @@ code-input .code-input_autocomplete_popup {
9
9
  z-index: 100;
10
10
  }
11
11
 
12
-
13
- code-input .code-input_autocomplete_testpos {
14
- opacity: 0;
15
- }
12
+ code-input pre.code-input_autocomplete_invisiblepre {
13
+ opacity: 0!important;
14
+ }
@@ -32,6 +32,7 @@ codeInput.plugins.Autocomplete = class extends codeInput.Plugin {
32
32
  codeInput.appendChild(popupElem);
33
33
 
34
34
  let testPosPre = document.createElement("pre");
35
+ testPosPre.classList.add("code-input_autocomplete_invisiblepre"); // Hide visually
35
36
  testPosPre.setAttribute("aria-hidden", true); // Hide for screen readers
36
37
  if(codeInput.templateObject.preElementStyled) {
37
38
  testPosPre.classList.add("code-input_autocomplete_testpos");
@@ -1 +1 @@
1
- code-input .code-input_autocomplete_popup{display:block;position:absolute;margin-top:1em;z-index:100}code-input .code-input_autocomplete_testpos{opacity:0}
1
+ code-input .code-input_autocomplete_popup{z-index:100;margin-top:1em;display:block;position:absolute}code-input pre.code-input_autocomplete_invisiblepre{opacity:0!important}
@@ -1 +1 @@
1
- "use strict";codeInput.plugins.Autocomplete=class extends codeInput.Plugin{constructor(a){super([]),this.updatePopupCallback=a}updatePopup(a,b){let c=a.textareaElement,d=this.getCaretCoordinates(a,c,c.selectionEnd,b),e=a.querySelector(".code-input_autocomplete_popup");e.style.top=d.top+"px",e.style.left=d.left+"px",b||this.updatePopupCallback(e,c,c.selectionEnd,c.selectionStart)}afterElementsAdded(a){let b=document.createElement("div");b.classList.add("code-input_autocomplete_popup"),a.appendChild(b);let c=document.createElement("pre");if(c.setAttribute("aria-hidden",!0),a.templateObject.preElementStyled)c.classList.add("code-input_autocomplete_testpos"),a.appendChild(c);else{let b=document.createElement("code");b.classList.add("code-input_autocomplete_testpos"),c.appendChild(b),a.appendChild(c)}let d=a.textareaElement;d.addEventListener("input",()=>{this.updatePopup(a,!1)}),d.addEventListener("selectionchange",()=>{this.updatePopup(a,!1)})}getCaretCoordinates(a,b,c,d){let e;if(d){let d=a.querySelector(".code-input_autocomplete_testpos").querySelectorAll("span");if(2>d.length)return this.getCaretCoordinates(a,b,c,!1);e=d[1]}else{let d=a.querySelector(".code-input_autocomplete_testpos"),f=document.createElement("span");for(f.textContent=b.value.substring(0,c),e=document.createElement("span"),e.textContent=".";d.firstChild;)d.removeChild(d.firstChild);d.appendChild(f),d.appendChild(e)}return{top:e.offsetTop-b.scrollTop,left:e.offsetLeft-b.scrollLeft}}updatePopupCallback=function(){}};
1
+ "use strict";codeInput.plugins.Autocomplete=class extends codeInput.Plugin{constructor(a){super([]),this.updatePopupCallback=a}updatePopup(a,b){let c=a.textareaElement,d=this.getCaretCoordinates(a,c,c.selectionEnd,b),e=a.querySelector(".code-input_autocomplete_popup");e.style.top=d.top+"px",e.style.left=d.left+"px",b||this.updatePopupCallback(e,c,c.selectionEnd,c.selectionStart)}afterElementsAdded(a){let b=document.createElement("div");b.classList.add("code-input_autocomplete_popup"),a.appendChild(b);let c=document.createElement("pre");if(c.classList.add("code-input_autocomplete_invisiblepre"),c.setAttribute("aria-hidden",!0),a.templateObject.preElementStyled)c.classList.add("code-input_autocomplete_testpos"),a.appendChild(c);else{let b=document.createElement("code");b.classList.add("code-input_autocomplete_testpos"),c.appendChild(b),a.appendChild(c)}let d=a.textareaElement;d.addEventListener("input",()=>{this.updatePopup(a,!1)}),d.addEventListener("selectionchange",()=>{this.updatePopup(a,!1)})}getCaretCoordinates(a,b,c,d){let e;if(d){let d=a.querySelector(".code-input_autocomplete_testpos").querySelectorAll("span");if(2>d.length)return this.getCaretCoordinates(a,b,c,!1);e=d[1]}else{let d=a.querySelector(".code-input_autocomplete_testpos"),f=document.createElement("span");for(f.textContent=b.value.substring(0,c),e=document.createElement("span"),e.textContent=".";d.firstChild;)d.removeChild(d.firstChild);d.appendChild(f),d.appendChild(e)}return{top:e.offsetTop-b.scrollTop,left:e.offsetLeft-b.scrollLeft}}updatePopupCallback=function(){}};
@@ -1 +1 @@
1
- .code-input_find-and-replace_find-match{color:inherit;text-shadow:none!important;background-color:#ff0!important}.code-input_find-and-replace_find-match-focused,.code-input_find-and-replace_find-match-focused *{background-color:#f80!important;color:#000!important}.code-input_find-and-replace_start-newline::before{content:"⤶"}@keyframes code-input_find-and-replace_roll-in{0%{opacity:0;transform:translateY(-34px)}100%{opacity:1;transform:translateY(0)}}@keyframes code-input_find-and-replace_roll-out{0%{opacity:1;top:0}100%{opacity:0;top:-34px}}.code-input_find-and-replace_dialog{position:absolute;top:0;right:14px;padding:6px;padding-top:8px;border:solid 1px #00000044;background-color:#fff;border-radius:6px;box-shadow:0 .2em 1em .2em rgba(0,0,0,.16)}.code-input_find-and-replace_dialog:not(.code-input_find-and-replace_hidden-dialog){animation:code-input_find-and-replace_roll-in .2s;opacity:1;pointer-events:all}.code-input_find-and-replace_dialog.code-input_find-and-replace_hidden-dialog{animation:code-input_find-and-replace_roll-out .2s;opacity:0;pointer-events:none}.code-input_find-and-replace_dialog input::placeholder{font-size:80%}.code-input_find-and-replace_dialog input{position:relative;width:240px;height:32px;top:-3px;font-size:large;color:#000000aa;border:0}.code-input_find-and-replace_dialog input.code-input_find-and-replace_error{color:#ff0000aa}.code-input_find-and-replace_dialog button,.code-input_find-and-replace_dialog input[type=checkbox]{display:inline-block;line-height:24px;font-size:22px;cursor:pointer;appearance:none;width:min-content;margin:5px;padding:5px;border:0;background-color:#ddd;text-align:center;color:#000;vertical-align:top}.code-input_find-and-replace_dialog input[type=checkbox].code-input_find-and-replace_case-sensitive-checkbox::before{content:"Aa"}.code-input_find-and-replace_dialog input[type=checkbox].code-input_find-and-replace_reg-exp-checkbox::before{content:".*"}.code-input_find-and-replace_dialog button:hover,.code-input_find-and-replace_dialog input[type=checkbox]:hover{background-color:#bbb}.code-input_find-and-replace_dialog input[type=checkbox]:checked{background-color:#222;color:#fff}.code-input_find-and-replace_match-description{display:block;color:#444}.code-input_find-and-replace_dialog button,.code-input_find-and-replace_dialog details summary{cursor:pointer}.code-input_find-and-replace_dialog button.code-input_find-and-replace_button-hidden{opacity:0;pointer-events:none}.code-input_find-and-replace_dialog span{display:block;float:right;margin:5px;padding:5px;width:24px;line-height:24px;font-family:system-ui;font-size:22px;font-weight:500;text-align:center;border-radius:50%;color:#000;opacity:.6}.code-input_find-and-replace_dialog span:before{content:"\00d7"}.code-input_find-and-replace_dialog span:hover{opacity:.8;background-color:#00000018}
1
+ .code-input_find-and-replace_find-match{color:inherit;text-shadow:none!important;background-color:#ff0!important}.code-input_find-and-replace_find-match-focused,.code-input_find-and-replace_find-match-focused *{color:#000!important;background-color:#f80!important}.code-input_find-and-replace_start-newline:before{content:"⤶"}@keyframes code-input_find-and-replace_roll-in{0%{opacity:0;transform:translateY(-34px)}to{opacity:1;transform:translateY(0)}}@keyframes code-input_find-and-replace_roll-out{0%{opacity:1;top:0}to{opacity:0;top:-34px}}.code-input_find-and-replace_dialog{background-color:#fff;border:1px solid #0004;border-radius:6px;padding:8px 6px 6px;position:absolute;top:0;right:14px;box-shadow:0 .2em 1em .2em #00000029}.code-input_find-and-replace_dialog:not(.code-input_find-and-replace_hidden-dialog){opacity:1;pointer-events:all;animation:.2s code-input_find-and-replace_roll-in}.code-input_find-and-replace_dialog.code-input_find-and-replace_hidden-dialog{opacity:0;pointer-events:none;animation:.2s code-input_find-and-replace_roll-out}.code-input_find-and-replace_dialog input::placeholder{font-size:80%}.code-input_find-and-replace_dialog input{color:#000a;border:0;width:240px;height:32px;font-size:large;position:relative;top:-3px}.code-input_find-and-replace_dialog input.code-input_find-and-replace_error{color:#f00a}.code-input_find-and-replace_dialog button,.code-input_find-and-replace_dialog input[type=checkbox]{cursor:pointer;appearance:none;text-align:center;color:#000;vertical-align:top;background-color:#ddd;border:0;width:min-content;margin:5px;padding:5px;font-size:22px;line-height:24px;display:inline-block}.code-input_find-and-replace_dialog input[type=checkbox].code-input_find-and-replace_case-sensitive-checkbox:before{content:"Aa"}.code-input_find-and-replace_dialog input[type=checkbox].code-input_find-and-replace_reg-exp-checkbox:before{content:".*"}.code-input_find-and-replace_dialog button:hover,.code-input_find-and-replace_dialog input[type=checkbox]:hover{background-color:#bbb}.code-input_find-and-replace_dialog input[type=checkbox]:checked{color:#fff;background-color:#222}.code-input_find-and-replace_match-description{color:#444;display:block}.code-input_find-and-replace_dialog details summary,.code-input_find-and-replace_dialog button{cursor:pointer}.code-input_find-and-replace_dialog button.code-input_find-and-replace_button-hidden{opacity:0;pointer-events:none}.code-input_find-and-replace_dialog span{float:right;text-align:center;color:#000;opacity:.6;border-radius:50%;width:24px;margin:5px;padding:5px;font-family:system-ui;font-size:22px;font-weight:500;line-height:24px;display:block}.code-input_find-and-replace_dialog span:before{content:"×"}.code-input_find-and-replace_dialog span:hover{opacity:.8;background-color:#00000018}
@@ -1 +1 @@
1
- @keyframes code-input_go-to-line_roll-in{0%{opacity:0;transform:translateY(-34px)}100%{opacity:1;transform:translateY(0)}}@keyframes code-input_go-to-line_roll-out{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(-34px)}}.code-input_go-to-line_dialog{position:absolute;top:0;right:14px;padding:6px;padding-top:8px;border:solid 1px #00000044;background-color:#fff;border-radius:6px;box-shadow:0 .2em 1em .2em rgba(0,0,0,.16)}.code-input_go-to-line_dialog:not(.code-input_go-to-line_hidden-dialog){animation:code-input_go-to-line_roll-in .2s;opacity:1;pointer-events:all}.code-input_go-to-line_dialog.code-input_go-to-line_hidden-dialog{animation:code-input_go-to-line_roll-out .2s;opacity:0;pointer-events:none}.code-input_go-to-line_dialog input::placeholder{font-size:80%}.code-input_go-to-line_dialog input{position:relative;width:240px;height:32px;top:-3px;font-size:large;color:#000000aa;border:0}.code-input_go-to-line_dialog input.code-input_go-to-line_error{color:#ff0000aa}.code-input_go-to-line_dialog span{display:inline-block;width:24px;line-height:24px;font-family:system-ui;font-size:22px;font-weight:500;text-align:center;border-radius:50%;color:#000;opacity:.6;vertical-align:top}.code-input_go-to-line_dialog span:before{content:"\00d7"}.code-input_go-to-line_dialog span:hover{opacity:.8;background-color:#00000018}.code-input_go-to-line_dialog p{font-family:monospace;width:264px;margin:0;overflow:hidden;white-space:wrap}
1
+ @keyframes code-input_go-to-line_roll-in{0%{opacity:0;transform:translateY(-34px)}to{opacity:1;transform:translateY(0)}}@keyframes code-input_go-to-line_roll-out{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-34px)}}.code-input_go-to-line_dialog{background-color:#fff;border:1px solid #0004;border-radius:6px;padding:8px 6px 6px;position:absolute;top:0;right:14px;box-shadow:0 .2em 1em .2em #00000029}.code-input_go-to-line_dialog:not(.code-input_go-to-line_hidden-dialog){opacity:1;pointer-events:all;animation:.2s code-input_go-to-line_roll-in}.code-input_go-to-line_dialog.code-input_go-to-line_hidden-dialog{opacity:0;pointer-events:none;animation:.2s code-input_go-to-line_roll-out}.code-input_go-to-line_dialog input::placeholder{font-size:80%}.code-input_go-to-line_dialog input{color:#000a;border:0;width:240px;height:32px;font-size:large;position:relative;top:-3px}.code-input_go-to-line_dialog input.code-input_go-to-line_error{color:#f00a}.code-input_go-to-line_dialog span{text-align:center;color:#000;opacity:.6;vertical-align:top;border-radius:50%;width:24px;font-family:system-ui;font-size:22px;font-weight:500;line-height:24px;display:inline-block}.code-input_go-to-line_dialog span:before{content:"×"}.code-input_go-to-line_dialog span:hover{opacity:.8;background-color:#00000018}.code-input_go-to-line_dialog p{width:264px;white-space:wrap;margin:0;font-family:monospace;overflow:hidden}
@@ -1 +1 @@
1
- .line-numbers code-input textarea,.line-numbers code-input.code-input_pre-element-styled pre,.line-numbers code-input:not(.code-input_pre-element-styled) pre code,code-input.line-numbers textarea,code-input.line-numbers.code-input_pre-element-styled pre,code-input.line-numbers:not(.code-input_pre-element-styled) pre code{padding-left:max(3.8em,var(--padding-left,16px))!important}.line-numbers code-input,code-input.line-numbers{grid-template-columns:calc(100% - max(0em,calc(3.8em - var(--padding-left,16px))))}.line-numbers code-input .code-input_dialog-container,code-input.line-numbers .code-input_dialog-container{width:calc(100% + max(0em,calc(3.8em - var(--padding-left,16px))))}code-input pre[class*=language-].line-numbers>code{position:static}code-input .line-numbers .line-numbers-rows{left:max(0,calc(var(--padding-left,16px) - 3.8em));top:var(--padding-top)}code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused) .line-numbers .line-numbers-rows{top:calc(var(--padding-top) + 3em)}
1
+ code-input.line-numbers textarea,code-input.line-numbers.code-input_pre-element-styled pre,code-input.line-numbers:not(.code-input_pre-element-styled) pre code,.line-numbers code-input textarea,.line-numbers code-input.code-input_pre-element-styled pre,.line-numbers code-input:not(.code-input_pre-element-styled) pre code{padding-left:max(3.8em,var(--padding-left,16px))!important}code-input.line-numbers,.line-numbers code-input{grid-template-columns:calc(100% - max(0em,calc(3.8em - var(--padding-left,16px))))}code-input.line-numbers .code-input_dialog-container,.line-numbers code-input .code-input_dialog-container{width:calc(100% + max(0em,calc(3.8em - var(--padding-left,16px))))}code-input pre[class*=language-].line-numbers>code{position:static}code-input .line-numbers .line-numbers-rows{left:max(0em,calc(var(--padding-left,16px) - 3.8em));top:var(--padding-top)}code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused) .line-numbers .line-numbers-rows{top:calc(var(--padding-top) + 3em)}
@@ -1,5 +1 @@
1
- :root,body{--code-input_special-chars_0:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdjZGBgYPj///9/RhCAMcA0bg6yHgAPmh/6BoxTcQAAAABJRU5ErkJgggAA');--code-input_special-chars_1:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdjZGBgYPj///9/RhAggwMAitIUBr9U6sYAAAAASUVORK5CYII=');--code-input_special-chars_2:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGCEMUCCjCgyYBFGRrAKFBkAuLYT9kYcIu0AAAAASUVORK5CYII=');--code-input_special-chars_3:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABhJREFUGFdj/P///38GKGCEMUCCjMTJAACYiBPyG8sfAgAAAABJRU5ErkJggg==');--code-input_special-chars_4:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///39GRkZGMI3BYYACRhgDrAKZAwAYxhvyz0DRIQAAAABJRU5ErkJggg==');--code-input_special-chars_5:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACJJREFUGFdj/P///38GKGAEcRgZGRlBfDAHLgNjgFUgywAAuR4T9hxJl2YAAAAASUVORK5CYII=');--code-input_special-chars_6:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdj/P///38GKGAEcRgZGRlBfDAHQwasAlkGABcdF/Y4yco2AAAAAElFTkSuQmCC');--code-input_special-chars_7:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdj/P///38GKGCEMUCCRHIAWMgT8kue3bQAAAAASUVORK5CYII=');--code-input_special-chars_8:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GKGAEcRgZGSE0cTIAvHcb8v+mIfAAAAAASUVORK5CYII=');--code-input_special-chars_9:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGAEcRgZGSE0igxMCVgGmQMAPqcX8hWL1K0AAAAASUVORK5CYII=');--code-input_special-chars_A:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdjZGBgYPj///9/RhCAMcA0iADJggCmDEw5ALdxH/aGuYHqAAAAAElFTkSuQmCC');--code-input_special-chars_B:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GBgYGRhAAceA0cTIAvc0b/vRDnVoAAAAASUVORK5CYII=');--code-input_special-chars_C:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdjZGBgYPj///9/EM0IYjAyMjIS4CDrAQC57hP+uLwvFQAAAABJRU5ErkJggg==');--code-input_special-chars_D:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdj/P///38GBgYGRhAAceA0fg5MDwAveh/6ToN9VwAAAABJRU5ErkJggg==');--code-input_special-chars_E:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABxJREFUGFdj/P///38GKGAEcRgZGRlBfDCHsAwA2UwT+mVIH1MAAAAASUVORK5CYII=');--code-input_special-chars_F:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///38GKGAEcRgZGRlBfDAHtwxMGQDZZhP+BnB1kwAAAABJRU5ErkJggg==')}.code-input_special-char{display:inline-block;position:relative;top:0;left:0;height:1em;overflow:hidden;text-decoration:none;text-shadow:none;vertical-align:middle;outline:.1px solid currentColor;color:transparent;font-size:0;--hex-0:var(
2
- --code-input_special-chars_0);--hex-1:var(
3
- --code-input_special-chars_0);--hex-2:var(
4
- --code-input_special-chars_0);--hex-3:var(
5
- --code-input_special-chars_0)}.code-input_special-char::before{margin-left:50%;transform:translate(-50%,0);content:" ";background-color:var(--code-input_special-char_color,currentColor);image-rendering:pixelated;display:inline-block;width:calc(100%-2px);height:100%;mask-image:var(--hex-0),var(--hex-1),var(--hex-2),var(--hex-3);mask-repeat:no-repeat,no-repeat,no-repeat,no-repeat;mask-size:min(40%,.25em),min(40%,.25em),min(40%,.25em),min(40%,.25em);mask-position:10% 10%,90% 10%,10% 90%,90% 90%;-webkit-mask-image:var(--hex-0),var(--hex-1),var(--hex-2),var(--hex-3);-webkit-mask-repeat:no-repeat,no-repeat,no-repeat,no-repeat;-webkit-mask-size:min(40%,.25em),min(40%,.25em),min(40%,.25em),min(40%,.25em);-webkit-mask-position:10% 10%,min(90%,.5em) 10%,10% 90%,min(90%,.5em) 90%}.code-input_special-char_zero-width{z-index:1;width:1em;margin-left:-.5em;margin-right:-.5em;position:relative;opacity:.75}.code-input_special-char_one-byte::before{height:1.5em;top:-1em;content:attr(data-hex2)}.code-input_special-char_one-byte::after{height:1.5em;bottom:-1em;content:attr(data-hex3)}
1
+ :root,body{--code-input_special-chars_0:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdjZGBgYPj///9/RhCAMcA0bg6yHgAPmh/6BoxTcQAAAABJRU5ErkJgggAA);--code-input_special-chars_1:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdjZGBgYPj///9/RhAggwMAitIUBr9U6sYAAAAASUVORK5CYII=);--code-input_special-chars_2:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGCEMUCCjCgyYBFGRrAKFBkAuLYT9kYcIu0AAAAASUVORK5CYII=);--code-input_special-chars_3:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABhJREFUGFdj/P///38GKGCEMUCCjMTJAACYiBPyG8sfAgAAAABJRU5ErkJggg==);--code-input_special-chars_4:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///39GRkZGMI3BYYACRhgDrAKZAwAYxhvyz0DRIQAAAABJRU5ErkJggg==);--code-input_special-chars_5:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACJJREFUGFdj/P///38GKGAEcRgZGRlBfDAHLgNjgFUgywAAuR4T9hxJl2YAAAAASUVORK5CYII=);--code-input_special-chars_6:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdj/P///38GKGAEcRgZGRlBfDAHQwasAlkGABcdF/Y4yco2AAAAAElFTkSuQmCC);--code-input_special-chars_7:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdj/P///38GKGCEMUCCRHIAWMgT8kue3bQAAAAASUVORK5CYII=);--code-input_special-chars_8:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GKGAEcRgZGSE0cTIAvHcb8v+mIfAAAAAASUVORK5CYII=);--code-input_special-chars_9:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGAEcRgZGSE0igxMCVgGmQMAPqcX8hWL1K0AAAAASUVORK5CYII=);--code-input_special-chars_A:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdjZGBgYPj///9/RhCAMcA0iADJggCmDEw5ALdxH/aGuYHqAAAAAElFTkSuQmCC);--code-input_special-chars_B:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GBgYGRhAAceA0cTIAvc0b/vRDnVoAAAAASUVORK5CYII=);--code-input_special-chars_C:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdjZGBgYPj///9/EM0IYjAyMjIS4CDrAQC57hP+uLwvFQAAAABJRU5ErkJggg==);--code-input_special-chars_D:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdj/P///38GBgYGRhAAceA0fg5MDwAveh/6ToN9VwAAAABJRU5ErkJggg==);--code-input_special-chars_E:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABxJREFUGFdj/P///38GKGAEcRgZGRlBfDCHsAwA2UwT+mVIH1MAAAAASUVORK5CYII=);--code-input_special-chars_F:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///38GKGAEcRgZGRlBfDAHtwxMGQDZZhP+BnB1kwAAAABJRU5ErkJggg==)}.code-input_special-char{height:1em;text-shadow:none;vertical-align:middle;color:#0000;--hex-0:var(--code-input_special-chars_0);--hex-1:var(--code-input_special-chars_0);--hex-2:var(--code-input_special-chars_0);--hex-3:var(--code-input_special-chars_0);outline:.1px solid;font-size:0;text-decoration:none;display:inline-block;position:relative;top:0;left:0;overflow:hidden}.code-input_special-char:before{content:" ";background-color:var(--code-input_special-char_color,currentColor);image-rendering:pixelated;width:calc(100%-2px);height:100%;mask-image:var(--hex-0),var(--hex-1),var(--hex-2),var(--hex-3);mask-position:10% 10%,90% 10%,10% 90%,90% 90%;mask-size:min(40%,.25em),min(40%,.25em),min(40%,.25em),min(40%,.25em);mask-repeat:no-repeat,no-repeat,no-repeat,no-repeat;-webkit-mask-image:var(--hex-0),var(--hex-1),var(--hex-2),var(--hex-3);margin-left:50%;display:inline-block;transform:translate(-50%);-webkit-mask-position:10% 10%,min(90%,.5em) 10%,10% 90%,min(90%,.5em) 90%;-webkit-mask-size:min(40%,.25em),min(40%,.25em),min(40%,.25em),min(40%,.25em);-webkit-mask-repeat:no-repeat,no-repeat,no-repeat,no-repeat}.code-input_special-char_zero-width{z-index:1;opacity:.75;width:1em;margin-left:-.5em;margin-right:-.5em;position:relative}.code-input_special-char_one-byte:before{content:attr(data-hex2);height:1.5em;top:-1em}.code-input_special-char_one-byte:after{content:attr(data-hex3);height:1.5em;bottom:-1em}