@webcoder49/code-input 2.6.8 → 2.7.0
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 +28 -8
- package/code-input.js +114 -11
- package/code-input.min.css +1 -1
- package/code-input.min.js +1 -1
- package/docs/_index.md +7 -1
- package/docs/interface/css/_index.md +5 -1
- package/docs/interface/js/_index.md +14 -1
- package/docs/plugins/_index.md +7 -6
- package/esm/code-input.mjs +114 -11
- package/package.json +1 -1
- package/plugins/autocomplete.min.css +1 -1
- package/plugins/find-and-replace.min.css +1 -1
- package/plugins/go-to-line.min.css +1 -1
- package/plugins/prism-line-numbers.min.css +1 -1
- package/plugins/special-chars.min.css +1 -5
package/code-input.css
CHANGED
|
@@ -20,7 +20,14 @@ code-input {
|
|
|
20
20
|
top: 0;
|
|
21
21
|
left: 0;
|
|
22
22
|
|
|
23
|
-
|
|
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 */
|
|
@@ -36,7 +43,6 @@ code-input {
|
|
|
36
43
|
text-align: start;
|
|
37
44
|
line-height: 1.5; /* Inherited to child elements */
|
|
38
45
|
tab-size: 2;
|
|
39
|
-
caret-color: darkgrey;
|
|
40
46
|
white-space: pre;
|
|
41
47
|
padding: 0!important; /* Use --padding to set the code-input element's padding */
|
|
42
48
|
display: grid;
|
|
@@ -44,7 +50,7 @@ code-input {
|
|
|
44
50
|
grid-template-rows: 100%;
|
|
45
51
|
}
|
|
46
52
|
|
|
47
|
-
code-input * {
|
|
53
|
+
code-input :not(.code-input_dialog-container *) {
|
|
48
54
|
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
55
|
}
|
|
50
56
|
|
|
@@ -68,6 +74,12 @@ code-input textarea, code-input:not(.code-input_pre-element-styled) pre code, co
|
|
|
68
74
|
code-input:not(.code-input_pre-element-styled) pre code, code-input.code-input_pre-element-styled pre {
|
|
69
75
|
height: max-content;
|
|
70
76
|
width: max-content;
|
|
77
|
+
|
|
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 {
|
|
@@ -118,12 +130,13 @@ code-input pre {
|
|
|
118
130
|
/* Make textarea almost completely transparent, except for caret and placeholder */
|
|
119
131
|
|
|
120
132
|
code-input textarea:not([data-code-input-fallback]) {
|
|
121
|
-
color: transparent;
|
|
122
133
|
background: transparent;
|
|
123
|
-
|
|
134
|
+
color: transparent;
|
|
135
|
+
caret-color: inherit;
|
|
124
136
|
}
|
|
125
|
-
code-input textarea
|
|
126
|
-
|
|
137
|
+
code-input textarea:not([data-code-input-fallback]):placeholder-shown {
|
|
138
|
+
/* Show placeholder */
|
|
139
|
+
color: var(--code-input_highlight-text-color, inherit);
|
|
127
140
|
}
|
|
128
141
|
|
|
129
142
|
/* Can be scrolled */
|
|
@@ -163,6 +176,11 @@ code-input .code-input_dialog-container {
|
|
|
163
176
|
|
|
164
177
|
/* Dialog boxes' text is based on text-direction */
|
|
165
178
|
text-align: inherit;
|
|
179
|
+
|
|
180
|
+
/* Allow colour change to reflect properly;
|
|
181
|
+
* transition-behavior: allow-discrete could be used but this is * better supported and works with the color property. */
|
|
182
|
+
color: inherit;
|
|
183
|
+
transition: color 0.001s;
|
|
166
184
|
}
|
|
167
185
|
|
|
168
186
|
[dir=rtl] code-input .code-input_dialog-container, code-input[dir=rtl] .code-input_dialog-container {
|
|
@@ -252,11 +270,13 @@ code-input:not(.code-input_loaded) pre, code-input:not(.code-input_loaded) texta
|
|
|
252
270
|
code-input:has(textarea[data-code-input-fallback]) {
|
|
253
271
|
padding: 0!important; /* Padding now in the textarea */
|
|
254
272
|
box-sizing: content-box;
|
|
273
|
+
|
|
274
|
+
caret-color: revert; /* JS not setting the colour since no highlighting */
|
|
255
275
|
}
|
|
256
276
|
code-input textarea[data-code-input-fallback] {
|
|
257
277
|
overflow: auto;
|
|
258
278
|
background-color: inherit;
|
|
259
|
-
color: inherit;
|
|
279
|
+
color: var(--code-input_highlight-text-color, inherit);
|
|
260
280
|
|
|
261
281
|
/* Don't overlap with message */
|
|
262
282
|
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
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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
|
|
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
|
|
1042
|
+
if (mainTextarea.placeholder == oldValue || oldValue == null && mainTextarea.placeholder == "") {
|
|
1043
|
+
mainTextarea.placeholder = newValue;
|
|
1044
|
+
}
|
|
942
1045
|
|
|
943
1046
|
this.scheduleHighlight();
|
|
944
1047
|
|
package/code-input.min.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
code-input{
|
|
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{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[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,"&").replace(/</g,"<")}unescapeHtml(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}getTemplate(){let a;return a=null==this.getAttribute("template")?codeInput.defaultTemplate:this.getAttribute("template"),a in codeInput.usedTemplates?codeInput.usedTemplates[a]:(a in codeInput.templateNotYetRegisteredQueue||(codeInput.templateNotYetRegisteredQueue[a]=[]),void codeInput.templateNotYetRegisteredQueue[a].push(this))}setup(){if(null!=this.textareaElement)return;this.classList.add("code-input_registered"),this.mutationObserver=new MutationObserver(this.mutationObserverCallback.bind(this)),this.mutationObserver.observe(this,{attributes:!0,attributeOldValue:!0}),this.classList.add("code-input_registered"),this.templateObject.preElementStyled&&this.classList.add("code-input_pre-element-styled");const a=this.querySelector("textarea[data-code-input-fallback]");let b,c,d,e,f,g=!1;a&&(a===document.activeElement&&(g=!0),b=a.selectionStart,c=a.selectionEnd,d=a.selectionDirection,e=a.scrollLeft,f=a.scrollTop);let h;if(a){let b=a.getAttributeNames();for(let c=0;c<b.length;c++){const d=b[c];"data-code-input-fallback"!=d&&(this.hasAttribute(d)||this.setAttribute(d,a.getAttribute(d)))}h=a.value,this.innerHTML=this.escapeHtml(h)}else h=this.unescapeHtml(this.innerHTML);h=h||this.getAttribute("value")||"",this.pluginEvt("beforeElementsAdded");const i=this.getAttribute("language")||this.getAttribute("lang"),j=this.getAttribute("placeholder")||i||"";this.initialValue=h;const k=document.createElement("textarea");k.placeholder=j,""!=h&&(k.value=h),k.innerHTML=this.innerHTML,this.hasAttribute("spellcheck")||k.setAttribute("spellcheck","false"),k.setAttribute("tabindex",this.getAttribute("tabindex")||0),this.setAttribute("tabindex",-1),this.originalAriaDescription=this.getAttribute("aria-description")||"Code input field",this.addEventListener("mousedown",()=>{this.classList.add("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("blur",()=>{this.classList.remove("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("focus",()=>{window.setTimeout(()=>{this.syncSize()},0)}),this.innerHTML="";for(let a,b=0;b<this.attributes.length;b++)a=this.attributes[b].name,(codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5))&&k.setAttribute(a,this.getAttribute(a));k.addEventListener("input",()=>{this.value=this.textareaElement.value}),this.textareaElement=k,this.append(k),this.setupTextareaSyncEvents(this.textareaElement);let l=document.createElement("code"),m=document.createElement("pre");m.setAttribute("aria-hidden","true"),m.setAttribute("tabindex","-1"),m.setAttribute("inert",!0),this.preElement=m,this.codeElement=l,m.append(l),this.append(m),this.templateObject.isCode&&i!=null&&""!=i&&l.classList.add("language-"+i.toLowerCase());let n=document.createElement("div");n.classList.add("code-input_dialog-container"),this.append(n),this.dialogContainerElement=n;let o=document.createElement("div");o.classList.add("code-input_keyboard-navigation-instructions"),n.append(o),this.pluginEvt("afterElementsAdded"),this.dispatchEvent(new CustomEvent("code-input_load")),this.value=h,b!==void 0&&(k.setSelectionRange(b,c,d),k.scrollTo(f,e)),g&&k.focus(),this.animateFrame();const p=new ResizeObserver(()=>{this.syncSize()});p.observe(this.textareaElement),this.classList.add("code-input_loaded")}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}get template(){return this.templateObject}set template(a){}connectedCallback(){if(this.templateObject=this.getTemplate(),null!=this.templateObject&&(this.classList.add("code-input_registered"),"loading"===document.readyState?window.addEventListener("DOMContentLoaded",this.setup.bind(this)):this.setup()),"loading"===document.readyState)window.addEventListener("DOMContentLoaded",()=>{const a=this.querySelector("textarea[data-code-input-fallback]");a&&this.setupTextareaSyncEvents(a)});else{const a=this.querySelector("textarea[data-code-input-fallback]");a&&this.setupTextareaSyncEvents(a)}}mutationObserverCallback(a){for(const b of a)if("attributes"===b.type){for(let a=0;a<codeInput.observedAttributes.length;a++)if(b.attributeName==codeInput.observedAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));for(let a=0;a<codeInput.textareaSyncAttributes.length;a++)if(b.attributeName==codeInput.textareaSyncAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));if("aria-"==b.attributeName.substring(0,5))return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName))}}disconnectedCallback(){this.mutationObserver&&this.mutationObserver.disconnect()}attributeChangedCallback(a,b,c){if(this.isConnected)switch(this.pluginEvt("attributeChanged",[a,b,c]),a){case"value":this.value=c;break;case"template":this.templateObject=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.templateObject.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.scheduleHighlight();break;case"lang":case"language":let d=this.codeElement,e=this.textareaElement;if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;null!==b&&(b=b.toLowerCase(),d.classList.remove("language-"+b),d.parentElement.classList.remove("language-"+b)),d.classList.remove("language-none"),d.parentElement.classList.remove("language-none"),null!=c&&""!=c&&d.classList.add("language-"+c),e.placeholder==b&&(e.placeholder=c),this.scheduleHighlight();break;default:codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5)?null==c||null==c?this.textareaElement.removeAttribute(a):this.textareaElement.setAttribute(a,c):codeInput.textareaSyncAttributes.regexp.forEach(b=>{a.match(b)&&(null==c?this.textareaElement.removeAttribute(a):this.textareaElement.setAttribute(a,c))})}}setupTextareaSyncEvents(a){for(let b=0;b<codeInput.textareaSyncEvents.length;b++){const c=codeInput.textareaSyncEvents[b];a.addEventListener(c,a=>{a.bubbles||this.dispatchEvent(new a.constructor(a.type,a))})}}addEventListener(a,b,c=void 0){let d=function(a){"function"==typeof b?b(a):b&&b.handleEvent&&b.handleEvent(a)}.bind(this);if(this.boundEventCallbacks[b]=d,!codeInput.textareaSyncEvents.includes(a))void 0===c?super.addEventListener(a,d):super.addEventListener(a,d,c);else if(this.boundEventCallbacks[b]=d,void 0===c){if(null==this.textareaElement){const b=this.querySelector("textarea[data-code-input-fallback]");b&&b.addEventListener(a,d),this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d)})}else this.textareaElement.addEventListener(a,d);}else if(null==this.textareaElement){const b=this.querySelector("textarea[data-code-input-fallback]");b&&b.addEventListener(a,d,c),this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d,c)})}else this.textareaElement.addEventListener(a,d,c)}removeEventListener(a,b,c=void 0){let d=this.boundEventCallbacks[b];if(!codeInput.textareaSyncEvents.includes(a))void 0===c?super.removeEventListener(a,d):super.removeEventListener(a,d,c);else if(void 0===c){if(null==this.textareaElement){const b=this.querySelector("textarea[data-code-input-fallback]");b&&b.removeEventListener(a,d),this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d)})}else this.textareaElement.removeEventListener(a,d);}else if(null==this.textareaElement){const b=this.querySelector("textarea[data-code-input-fallback]");b&&b.removeEventListener(a,d,c),this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d,c)})}else this.textareaElement.removeEventListener(a,d,c)}getTextareaProperty(a,b=void 0){if(this.textareaElement)return this.textareaElement[a];else{const c=this.querySelector("textarea[data-code-input-fallback]");if(c)return c[a];if(void 0===b)throw new Error("Cannot get "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.");return b}}setTextareaProperty(a,b,c=!0){if(this.textareaElement)this.textareaElement[a]=b;else{const d=this.querySelector("textarea[data-code-input-fallback]");if(d)d[a]=b;else{if(!c)return(!1);throw new Error("Cannot set "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.")}}return(!0)}get autocomplete(){return this.getAttribute("autocomplete")}set autocomplete(a){return this.setAttribute("autocomplete",a)}get cols(){return this.getTextareaProperty("cols",+this.getAttribute("cols"))}set cols(a){this.setAttribute("cols",a)}get defaultValue(){return this.initialValue}set defaultValue(a){this.initialValue=a}get textContent(){return this.initialValue}set textContent(a){this.initialValue=a}get dirName(){return this.getAttribute("dirName")||""}set dirName(a){this.setAttribute("dirname",a)}get disabled(){return this.hasAttribute("disabled")}set disabled(a){a?this.setAttribute("disabled",!0):this.removeAttribute("disabled")}get form(){return this.getTextareaProperty("form")}get labels(){return this.getTextareaProperty("labels")}get maxLength(){const a=+this.getAttribute("maxlength");return isNaN(a)?-1:a}set maxLength(a){-1==a?this.removeAttribute("maxlength"):this.setAttribute("maxlength",a)}get minLength(){const a=+this.getAttribute("minlength");return isNaN(a)?-1:a}set minLength(a){-1==a?this.removeAttribute("minlength"):this.setAttribute("minlength",a)}get name(){return this.getAttribute("name")||""}set name(a){this.setAttribute("name",a)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(a){this.setAttribute("placeholder",a)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get required(){return this.hasAttribute("readonly")}set required(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get rows(){return this.getTextareaProperty("rows",+this.getAttribute("rows"))}set rows(a){this.setAttribute("rows",a)}get selectionDirection(){return this.getTextareaProperty("selectionDirection")}set selectionDirection(a){this.setTextareaProperty("selectionDirection",a)}get selectionEnd(){return this.getTextareaProperty("selectionEnd")}set selectionEnd(a){this.setTextareaProperty("selectionEnd",a)}get selectionStart(){return this.getTextareaProperty("selectionStart")}set selectionStart(a){this.setTextareaProperty("selectionStart",a)}get textLength(){return this.value.length}get type(){return"textarea"}get validationMessage(){return this.getTextareaProperty("validationMessage")}get validity(){return this.getTextareaProperty("validationMessage")}get value(){return this.getTextareaProperty("value",this.getAttribute("value")||this.innerHTML)}set value(a){a=a||"",this.setTextareaProperty("value",a,!1)?this.textareaElement&&this.scheduleHighlight():this.innerHTML=a}get willValidate(){return this.getTextareaProperty("willValidate",this.disabled||this.readOnly)}get wrap(){return this.getAttribute("wrap")||""}set wrap(a){this.setAttribute("wrap",a)}getTextareaMethod(a){if(this.textareaElement)return this.textareaElement[a].bind(this.textareaElement);else{const b=this.querySelector("textarea[data-code-input-fallback]");if(b)return b[a].bind(b);throw new Error("Cannot call "+a+" on an unregistered code-input element without a data-code-input-fallback textarea.")}}blur(a={}){this.getTextareaMethod("blur")(a)}checkValidity(){return this.getTextareaMethod("checkValidity")()}focus(a={}){this.getTextareaMethod("focus")(a)}reportValidity(){return this.getTextareaMethod("reportValidity")()}setCustomValidity(a){this.getTextareaMethod("setCustomValidity")(a)}setRangeText(a,b=this.selectionStart,c=this.selectionEnd,d="preserve"){this.getTextareaMethod("setRangeText")(a,b,c,d),this.textareaElement&&this.scheduleHighlight()}setSelectionRange(a,b,c="none"){this.getTextareaMethod("setSelectionRange")(a,b,c)}pluginData={};formResetCallback(){this.value=this.initialValue}}};{class a extends codeInput.Template{constructor(a,b=[],c=!0){super(a.highlightElement,c,!0,!1,b)}}codeInput.templates.Prism=a;class b extends codeInput.Template{constructor(a,b=[],c=!1){super(function(b){b.removeAttribute("data-highlighted"),a.highlightElement(b)},c,!0,!1,b)}}codeInput.templates.Hljs=b}customElements.define("code-input",codeInput.CodeInput);
|
|
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,"&").replace(/</g,"<")}unescapeHtml(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}getTemplate(){let a;return a=null==this.getAttribute("template")?codeInput.defaultTemplate:this.getAttribute("template"),a in codeInput.usedTemplates?codeInput.usedTemplates[a]:(a in codeInput.templateNotYetRegisteredQueue||(codeInput.templateNotYetRegisteredQueue[a]=[]),void codeInput.templateNotYetRegisteredQueue[a].push(this))}setup(){if(null!=this.textareaElement)return;this.classList.add("code-input_registered"),this.mutationObserver=new MutationObserver(this.mutationObserverCallback.bind(this)),this.mutationObserver.observe(this,{attributes:!0,attributeOldValue:!0}),this.classList.add("code-input_registered"),this.templateObject.preElementStyled&&this.classList.add("code-input_pre-element-styled");const a=this.querySelector("textarea[data-code-input-fallback]");let b,c,d,e,f,g=!1;a&&(a===document.activeElement&&(g=!0),b=a.selectionStart,c=a.selectionEnd,d=a.selectionDirection,e=a.scrollLeft,f=a.scrollTop);let h;if(a){let b=a.getAttributeNames();for(let c=0;c<b.length;c++){const d=b[c];"data-code-input-fallback"!=d&&(this.hasAttribute(d)||this.setAttribute(d,a.getAttribute(d)))}h=a.value,this.innerHTML=this.escapeHtml(h)}else h=this.unescapeHtml(this.innerHTML);h=h||this.getAttribute("value")||"",this.pluginEvt("beforeElementsAdded");const i=this.getAttribute("language")||this.getAttribute("lang"),j=this.getAttribute("placeholder")||i||"";this.initialValue=h;const k=document.createElement("textarea");k.placeholder=j,""!=h&&(k.value=h),k.innerHTML=this.innerHTML,this.hasAttribute("spellcheck")||k.setAttribute("spellcheck","false"),k.setAttribute("tabindex",this.getAttribute("tabindex")||0),this.setAttribute("tabindex",-1),this.originalAriaDescription=this.getAttribute("aria-description")||"Code input field",this.addEventListener("mousedown",()=>{this.classList.add("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("blur",()=>{this.classList.remove("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("focus",()=>{window.setTimeout(()=>{this.syncSize()},0)}),this.innerHTML="";for(let a,b=0;b<this.attributes.length;b++)a=this.attributes[b].name,(codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5))&&k.setAttribute(a,this.getAttribute(a));k.addEventListener("input",()=>{this.value=this.textareaElement.value}),this.textareaElement=k,this.append(k),this.setupTextareaSyncEvents(this.textareaElement);let l=document.createElement("code"),m=document.createElement("pre");m.setAttribute("aria-hidden","true"),m.setAttribute("tabindex","-1"),m.setAttribute("inert",!0),this.preElement=m,this.codeElement=l,m.append(l),this.append(m),this.templateObject.isCode&&i!=null&&""!=i&&l.classList.add("language-"+i.toLowerCase());let n=document.createElement("div");n.classList.add("code-input_dialog-container"),this.append(n),this.dialogContainerElement=n;let o=document.createElement("div");o.classList.add("code-input_keyboard-navigation-instructions"),n.append(o),this.pluginEvt("afterElementsAdded"),this.dispatchEvent(new CustomEvent("code-input_load")),this.value=h,b!==void 0&&(k.setSelectionRange(b,c,d),k.scrollTo(f,e)),g&&k.focus(),this.animateFrame();const p=new ResizeObserver(()=>{this.syncSize()});p.observe(this),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
|
-
|
|
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.0), [in a ZIP archive](/release/code-input-js-v2.7.0.zip), [in a TAR.GZ archive](/release/code-input-js-v2.7.0.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
|
|
|
@@ -308,6 +312,8 @@ something like [CodeMirror](https://codemirror.net/),
|
|
|
308
312
|
[Ace](https://ace.c9.io/) or
|
|
309
313
|
[Monaco](https://microsoft.github.io/monaco-editor/).
|
|
310
314
|
|
|
315
|
+
`code-input.js` is also improving and 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)!
|
|
316
|
+
|
|
311
317
|
## Read Enough?
|
|
312
318
|
**If you don't need web framework integration, get started with the commented tutorials by example on this page, for [Prism.js](#playground-preset-prism), [highlight.js](#playground-preset-hljs), or [another highlighter](#playground-preset-custom). If you're using ECMAScript modules or a web framework, start [here](modules-and-frameworks).**
|
|
313
319
|
|
|
@@ -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.
|
package/docs/plugins/_index.md
CHANGED
|
@@ -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
|
-
|
|
107
|
+
popupElem.firstElementChild.innerHTML += "[Tab]";
|
|
107
108
|
}
|
|
108
109
|
textarea.addEventListener("keydown", (event) => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
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>
|
package/esm/code-input.mjs
CHANGED
|
@@ -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
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
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
|
|
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
|
|
940
|
+
if (mainTextarea.placeholder == oldValue || oldValue == null && mainTextarea.placeholder == "") {
|
|
941
|
+
mainTextarea.placeholder = newValue;
|
|
942
|
+
}
|
|
840
943
|
|
|
841
944
|
this.scheduleHighlight();
|
|
842
945
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webcoder49/code-input",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "An editable <textarea> that supports *any* syntax highlighting algorithm, for code or something else. Also, added plugins.",
|
|
5
5
|
"browser": "code-input.js",
|
|
6
6
|
"exports": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
code-input .code-input_autocomplete_popup{
|
|
1
|
+
code-input .code-input_autocomplete_popup{z-index:100;margin-top:1em;display:block;position:absolute}code-input .code-input_autocomplete_testpos{opacity:0}
|
|
@@ -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 *{
|
|
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)}
|
|
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
|
|
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(
|
|
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}
|