@webcoder49/code-input 2.6.4 → 2.6.5
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 +62 -53
- package/code-input.js +83 -10
- package/code-input.min.css +1 -1
- package/code-input.min.js +1 -1
- package/docs/_index.md +1 -1
- package/docs/interface/css/_index.md +1 -1
- package/docs/modules-and-frameworks/hljs/esm/_index.md +1 -1
- package/esm/code-input.mjs +83 -10
- package/package.json +1 -1
- package/plugins/prism-line-numbers.css +10 -5
- package/plugins/prism-line-numbers.min.css +1 -1
package/code-input.css
CHANGED
|
@@ -26,6 +26,10 @@ code-input {
|
|
|
26
26
|
/* Normal inline styles */
|
|
27
27
|
margin: 8px;
|
|
28
28
|
--padding: 16px;
|
|
29
|
+
--padding-left: var(--padding, 16px);
|
|
30
|
+
--padding-right: var(--padding, 16px);
|
|
31
|
+
--padding-top: var(--padding, 16px);
|
|
32
|
+
--padding-bottom: var(--padding, 16px);
|
|
29
33
|
height: 250px;
|
|
30
34
|
font-size: inherit;
|
|
31
35
|
font-family: monospace;
|
|
@@ -40,19 +44,20 @@ code-input {
|
|
|
40
44
|
grid-template-rows: 100%;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
padding: var(--padding, 16px)!important;
|
|
47
|
+
code-input * {
|
|
48
|
+
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. */
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
code-input textarea, code-input:not(.code-input_pre-element-styled) pre code, code-input.code-input_pre-element-styled pre {
|
|
49
52
|
/* Both elements need the same text and space styling so they are directly on top of each other */
|
|
50
53
|
margin: 0px!important;
|
|
51
|
-
padding: var(--padding, 16px)!important;
|
|
54
|
+
padding-left: var(--padding-left, 16px)!important;
|
|
55
|
+
padding-right: var(--padding-right, 16px)!important;
|
|
56
|
+
padding-top: var(--padding-top, 16px)!important;
|
|
57
|
+
padding-bottom: var(--padding-bottom, 16px)!important;
|
|
52
58
|
border: 0;
|
|
53
|
-
min-width: calc(100% - var(--padding, 16px)
|
|
54
|
-
min-height: calc(100% - var(--padding, 16px)
|
|
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. */
|
|
59
|
+
min-width: calc(100% - var(--padding-left, 16px) - var(--padding-right, 16px));
|
|
60
|
+
min-height: calc(100% - var(--padding-top, 16px) - var(--padding-bottom, 16px));
|
|
56
61
|
overflow: hidden;
|
|
57
62
|
resize: none;
|
|
58
63
|
grid-row: 1;
|
|
@@ -138,42 +143,6 @@ code-input:has(textarea:focus):not(.code-input_mouse-focused) {
|
|
|
138
143
|
outline: 2px solid currentColor;
|
|
139
144
|
}
|
|
140
145
|
|
|
141
|
-
/* Before registering give a hint about how to register. */
|
|
142
|
-
code-input:not(.code-input_registered) {
|
|
143
|
-
overflow: hidden;
|
|
144
|
-
display: block;
|
|
145
|
-
box-sizing: border-box; /* Include padding in width/height */
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
code-input:not(.code-input_registered)::after {
|
|
149
|
-
/* Display message to register */
|
|
150
|
-
content: "No highlighting. JavaScript support is disabled or insufficient, or codeInput.registerTemplate has not been called.";
|
|
151
|
-
display: block;
|
|
152
|
-
position: absolute;
|
|
153
|
-
bottom: 0;
|
|
154
|
-
left: var(--padding, 16px);
|
|
155
|
-
width: calc(100% - 2 * var(--padding, 16px));
|
|
156
|
-
overflow-x: auto;
|
|
157
|
-
|
|
158
|
-
border-top: 1px solid currentColor;
|
|
159
|
-
outline-top: 0;
|
|
160
|
-
background-color: inherit;
|
|
161
|
-
color: inherit;
|
|
162
|
-
|
|
163
|
-
margin: 0;
|
|
164
|
-
padding: 0;
|
|
165
|
-
height: 2em;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
code-input:not(.code-input_registered) textarea {
|
|
169
|
-
/* Don't overlap with message */
|
|
170
|
-
min-height: calc(100% - var(--padding, 16px) * 2 - 2em);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
code-input:not(.code-input_loaded) pre, code-input:not(.code-input_loaded) textarea:not([data-code-input-fallback]) {
|
|
174
|
-
opacity: 0;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
146
|
/* Contains dialog boxes that might appear as the result of a plugin.
|
|
178
147
|
Sticks to the top of the code-input element */
|
|
179
148
|
|
|
@@ -195,9 +164,6 @@ code-input .code-input_dialog-container {
|
|
|
195
164
|
/* Dialog boxes' text is based on text-direction */
|
|
196
165
|
text-align: inherit;
|
|
197
166
|
}
|
|
198
|
-
code-input.code-input_pre-element-styled .code-input_dialog-container {
|
|
199
|
-
width: calc(100% + 2 * var(--padding, 16px));
|
|
200
|
-
}
|
|
201
167
|
|
|
202
168
|
[dir=rtl] code-input .code-input_dialog-container, code-input[dir=rtl] .code-input_dialog-container {
|
|
203
169
|
left: unset;
|
|
@@ -217,14 +183,16 @@ code-input .code-input_dialog-container .code-input_keyboard-navigation-instruct
|
|
|
217
183
|
background-color: black;
|
|
218
184
|
color: white;
|
|
219
185
|
padding: 2px;
|
|
186
|
+
padding-left: var(--padding-left, 16px);
|
|
187
|
+
padding-right: var(--padding-right, 16px);
|
|
220
188
|
margin: 0;
|
|
221
189
|
text-wrap: balance;
|
|
222
|
-
overflow: hidden;
|
|
223
|
-
|
|
190
|
+
overflow-x: hidden;
|
|
191
|
+
overflow-y: auto;
|
|
224
192
|
|
|
225
193
|
width: 100%;
|
|
226
194
|
box-sizing: border-box;
|
|
227
|
-
|
|
195
|
+
height: 3em;
|
|
228
196
|
}
|
|
229
197
|
|
|
230
198
|
code-input:not(:has(textarea:not([data-code-input-fallback]):focus)) .code-input_dialog-container .code-input_keyboard-navigation-instructions,
|
|
@@ -238,17 +206,58 @@ code-input .code-input_dialog-container .code-input_keyboard-navigation-instruct
|
|
|
238
206
|
code-input:not(:has(.code-input_keyboard-navigation-instructions:empty)):has(textarea:not([data-code-input-fallback]):focus):not(.code-input_mouse-focused) textarea,
|
|
239
207
|
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,
|
|
240
208
|
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 {
|
|
241
|
-
padding-top: calc(var(--padding, 16px) + 3em)!important;
|
|
209
|
+
padding-top: calc(var(--padding-top, 16px) + 3em)!important;
|
|
210
|
+
min-height: calc(100% - var(--padding-top, 16px) - 3em - var(--padding-bottom, 16px));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* Pre-loaded appearance */
|
|
214
|
+
|
|
215
|
+
code-input:not(.code-input_loaded) {
|
|
216
|
+
padding-left: var(--padding-left, 16px)!important;
|
|
217
|
+
padding-right: var(--padding-right, 16px)!important;
|
|
218
|
+
padding: var(--padding-top, 16px)!important;
|
|
219
|
+
padding: var(--padding-bottom, 16px)!important;
|
|
220
|
+
overflow: hidden;
|
|
221
|
+
display: block;
|
|
222
|
+
box-sizing: border-box; /* Include padding in width/height */
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
code-input:not(.code-input_loaded)::after {
|
|
226
|
+
/* Display message to register */
|
|
227
|
+
content: "No highlighting. JavaScript support is disabled or insufficient, or codeInput.registerTemplate has not been called.";
|
|
228
|
+
display: block;
|
|
229
|
+
position: absolute;
|
|
230
|
+
bottom: 0;
|
|
231
|
+
left: var(--padding-left, 16px);
|
|
232
|
+
width: calc(100% - var(--padding-left, 1.6px) - var(--padding-right, 1.6px));
|
|
233
|
+
overflow-x: auto;
|
|
234
|
+
|
|
235
|
+
border-top: 1px solid currentColor;
|
|
236
|
+
outline-top: 0;
|
|
237
|
+
background-color: inherit;
|
|
238
|
+
color: inherit;
|
|
239
|
+
|
|
240
|
+
margin: 0;
|
|
241
|
+
padding: 0;
|
|
242
|
+
height: 2em;
|
|
242
243
|
}
|
|
243
|
-
|
|
244
|
-
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
code-input:not(.code-input_loaded) pre, code-input:not(.code-input_loaded) textarea:not([data-code-input-fallback]) {
|
|
247
|
+
opacity: 0;
|
|
245
248
|
}
|
|
246
249
|
|
|
247
250
|
/* No JavaScript fallback - styles to override all previous */
|
|
248
251
|
|
|
252
|
+
code-input:has(textarea[data-code-input-fallback]) {
|
|
253
|
+
padding: 0!important; /* Padding now in the textarea */
|
|
254
|
+
box-sizing: content-box;
|
|
255
|
+
}
|
|
249
256
|
code-input textarea[data-code-input-fallback] {
|
|
250
257
|
overflow: auto;
|
|
251
258
|
background-color: inherit;
|
|
252
259
|
color: inherit;
|
|
253
|
-
|
|
260
|
+
|
|
261
|
+
/* Don't overlap with message */
|
|
262
|
+
min-height: calc(100% - var(--padding-top, 16px) - 2em - var(--padding-bottom, 16px));
|
|
254
263
|
}
|
package/code-input.js
CHANGED
|
@@ -620,9 +620,26 @@ var codeInput = {
|
|
|
620
620
|
this.classList.add("code-input_registered"); // Remove register message
|
|
621
621
|
if (this.templateObject.preElementStyled) this.classList.add("code-input_pre-element-styled");
|
|
622
622
|
|
|
623
|
-
this.pluginEvt("beforeElementsAdded");
|
|
624
|
-
|
|
625
623
|
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
624
|
+
let fallbackFocused = false;
|
|
625
|
+
let fallbackSelectionStart = undefined;
|
|
626
|
+
let fallbackSelectionEnd = undefined;
|
|
627
|
+
let fallbackSelectionDirection = undefined;
|
|
628
|
+
let fallbackScrollLeft = undefined;
|
|
629
|
+
let fallbackScrollTop = undefined;
|
|
630
|
+
if(fallbackTextarea) {
|
|
631
|
+
// Move some attributes to new textarea so typing during
|
|
632
|
+
// slow load not interrupted
|
|
633
|
+
if(fallbackTextarea === document.activeElement) { // Thanks to https://stackoverflow.com/a/36430896
|
|
634
|
+
fallbackFocused = true;
|
|
635
|
+
}
|
|
636
|
+
fallbackSelectionStart = fallbackTextarea.selectionStart;
|
|
637
|
+
fallbackSelectionEnd = fallbackTextarea.selectionEnd;
|
|
638
|
+
fallbackSelectionDirection = fallbackTextarea.selectionDirection;
|
|
639
|
+
fallbackScrollLeft = fallbackTextarea.scrollLeft;
|
|
640
|
+
fallbackScrollTop = fallbackTextarea.scrollTop;
|
|
641
|
+
}
|
|
642
|
+
|
|
626
643
|
let value;
|
|
627
644
|
if(fallbackTextarea) {
|
|
628
645
|
// Fallback textarea exists
|
|
@@ -638,11 +655,15 @@ var codeInput = {
|
|
|
638
655
|
}
|
|
639
656
|
// Sync value
|
|
640
657
|
value = fallbackTextarea.value;
|
|
658
|
+
// Backwards compatibility with plugins
|
|
659
|
+
this.innerHTML = this.escapeHtml(value);
|
|
641
660
|
} else {
|
|
642
661
|
value = this.unescapeHtml(this.innerHTML);
|
|
643
662
|
}
|
|
644
663
|
value = value || this.getAttribute("value") || "";
|
|
645
664
|
|
|
665
|
+
this.pluginEvt("beforeElementsAdded");
|
|
666
|
+
|
|
646
667
|
// First-time attribute sync
|
|
647
668
|
const lang = this.getAttribute("language") || this.getAttribute("lang");
|
|
648
669
|
const placeholder = this.getAttribute("placeholder") || lang || "";
|
|
@@ -671,9 +692,23 @@ var codeInput = {
|
|
|
671
692
|
// Accessibility - detect when mouse focus to remove focus outline + keyboard navigation guidance that could irritate users.
|
|
672
693
|
this.addEventListener("mousedown", () => {
|
|
673
694
|
this.classList.add("code-input_mouse-focused");
|
|
695
|
+
// Wait for CSS to update padding
|
|
696
|
+
window.setTimeout(() => {
|
|
697
|
+
this.syncSize();
|
|
698
|
+
}, 0);
|
|
674
699
|
});
|
|
675
700
|
textarea.addEventListener("blur", () => {
|
|
676
701
|
this.classList.remove("code-input_mouse-focused");
|
|
702
|
+
// Wait for CSS to update padding
|
|
703
|
+
window.setTimeout(() => {
|
|
704
|
+
this.syncSize();
|
|
705
|
+
}, 0);
|
|
706
|
+
});
|
|
707
|
+
textarea.addEventListener("focus", () => {
|
|
708
|
+
// Wait for CSS to update padding
|
|
709
|
+
window.setTimeout(() => {
|
|
710
|
+
this.syncSize();
|
|
711
|
+
}, 0);
|
|
677
712
|
});
|
|
678
713
|
|
|
679
714
|
this.innerHTML = ""; // Clear Content
|
|
@@ -726,13 +761,25 @@ var codeInput = {
|
|
|
726
761
|
this.dispatchEvent(new CustomEvent("code-input_load"));
|
|
727
762
|
|
|
728
763
|
this.value = value;
|
|
764
|
+
|
|
765
|
+
// Update with fallback textarea's state so can keep editing
|
|
766
|
+
// if loaded slowly
|
|
767
|
+
if(fallbackSelectionStart !== undefined) {
|
|
768
|
+
console.log("sel", fallbackSelectionStart, fallbackSelectionEnd, fallbackSelectionDirection, "scr", fallbackScrollTop, fallbackScrollLeft, "foc", fallbackFocused);
|
|
769
|
+
textarea.setSelectionRange(fallbackSelectionStart, fallbackSelectionEnd, fallbackSelectionDirection);
|
|
770
|
+
textarea.scrollTo(fallbackScrollTop, fallbackScrollLeft);
|
|
771
|
+
}
|
|
772
|
+
if(fallbackFocused) {
|
|
773
|
+
textarea.focus();
|
|
774
|
+
}
|
|
775
|
+
|
|
729
776
|
this.animateFrame();
|
|
730
777
|
|
|
731
778
|
const resizeObserver = new ResizeObserver((elements) => {
|
|
732
779
|
// The only element that could be resized is this code-input element.
|
|
733
780
|
this.syncSize();
|
|
734
781
|
});
|
|
735
|
-
resizeObserver.observe(this);
|
|
782
|
+
resizeObserver.observe(this.textareaElement);
|
|
736
783
|
|
|
737
784
|
this.classList.add("code-input_loaded");
|
|
738
785
|
}
|
|
@@ -1128,14 +1175,40 @@ var codeInput = {
|
|
|
1128
1175
|
get wrap() { return this.getAttribute("wrap") || ""; }
|
|
1129
1176
|
set wrap(val) { this.setAttribute("wrap", val); }
|
|
1130
1177
|
|
|
1178
|
+
/**
|
|
1179
|
+
* Get the JavaScript method from the internal textarea
|
|
1180
|
+
* element, throwing an error when no textarea is present.
|
|
1181
|
+
* The method is bound to the textarea as `this`.
|
|
1182
|
+
*
|
|
1183
|
+
* For internal use - treat the code-input element as a
|
|
1184
|
+
* textarea for the standard functions (e.g. document.
|
|
1185
|
+
* querySelector("code-input").focus()).
|
|
1186
|
+
*/
|
|
1187
|
+
getTextareaMethod(name) {
|
|
1188
|
+
if(this.textareaElement) {
|
|
1189
|
+
return this.textareaElement[name].bind(this.textareaElement);
|
|
1190
|
+
} else {
|
|
1191
|
+
// Unregistered
|
|
1192
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1193
|
+
if(fallbackTextarea) {
|
|
1194
|
+
return fallbackTextarea[name].bind(fallbackTextarea);
|
|
1195
|
+
} else {
|
|
1196
|
+
throw new Error("Cannot call "+name+" on an unregistered code-input element without a data-code-input-fallback textarea.");
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1131
1200
|
|
|
1132
|
-
blur(options={}) {
|
|
1133
|
-
checkValidity() { return this.
|
|
1134
|
-
focus(options={}) {
|
|
1135
|
-
reportValidity() { return this.
|
|
1136
|
-
setCustomValidity(error) { this.
|
|
1137
|
-
setRangeText(replacement, selectionStart=this.selectionStart, selectionEnd=this.selectionEnd, selectMode="preserve") {
|
|
1138
|
-
|
|
1201
|
+
blur(options={}) { this.getTextareaMethod("blur")(options); }
|
|
1202
|
+
checkValidity() { return this.getTextareaMethod("checkValidity")(); }
|
|
1203
|
+
focus(options={}) { this.getTextareaMethod("focus")(options); }
|
|
1204
|
+
reportValidity() { return this.getTextareaMethod("reportValidity")(); }
|
|
1205
|
+
setCustomValidity(error) { this.getTextareaMethod("setCustomValidity")(error); }
|
|
1206
|
+
setRangeText(replacement, selectionStart=this.selectionStart, selectionEnd=this.selectionEnd, selectMode="preserve") {
|
|
1207
|
+
this.getTextareaMethod("setRangeText")(replacement, selectionStart, selectionEnd, selectMode);
|
|
1208
|
+
// Reflect that value updated
|
|
1209
|
+
if(this.textareaElement) this.scheduleHighlight();
|
|
1210
|
+
}
|
|
1211
|
+
setSelectionRange(selectionStart, selectionEnd, selectionDirection="none") { this.getTextareaMethod("setSelectionRange")(selectionStart, selectionEnd, selectionDirection); }
|
|
1139
1212
|
|
|
1140
1213
|
/**
|
|
1141
1214
|
* Allows plugins to store data in the scope of a single element.
|
package/code-input.min.css
CHANGED
|
@@ -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;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:
|
|
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))}
|
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"),this.pluginEvt("beforeElementsAdded");const a=this.querySelector("textarea[data-code-input-fallback]");let b;if(a){let c=a.getAttributeNames();for(let b=0;b<c.length;b++){const d=c[b];"data-code-input-fallback"!=d&&(this.hasAttribute(d)||this.setAttribute(d,a.getAttribute(d)))}b=a.value}else b=this.unescapeHtml(this.innerHTML);b=b||this.getAttribute("value")||"";const c=this.getAttribute("language")||this.getAttribute("lang"),d=this.getAttribute("placeholder")||c||"";this.initialValue=b;const e=document.createElement("textarea");e.placeholder=d,""!=b&&(e.value=b),e.innerHTML=this.innerHTML,this.hasAttribute("spellcheck")||e.setAttribute("spellcheck","false"),e.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")}),e.addEventListener("blur",()=>{this.classList.remove("code-input_mouse-focused")}),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))&&e.setAttribute(a,this.getAttribute(a));e.addEventListener("input",()=>{this.value=this.textareaElement.value}),this.textareaElement=e,this.append(e);let f=document.createElement("code"),g=document.createElement("pre");g.setAttribute("aria-hidden","true"),g.setAttribute("tabindex","-1"),g.setAttribute("inert",!0),this.preElement=g,this.codeElement=f,g.append(f),this.append(g),this.templateObject.isCode&&c!=null&&""!=c&&f.classList.add("language-"+c.toLowerCase());let h=document.createElement("div");h.classList.add("code-input_dialog-container"),this.append(h),this.dialogContainerElement=h;let i=document.createElement("div");i.classList.add("code-input_keyboard-navigation-instructions"),h.append(i),this.pluginEvt("afterElementsAdded"),this.dispatchEvent(new CustomEvent("code-input_load")),this.value=b,this.animateFrame();const j=new ResizeObserver(()=>{this.syncSize()});j.observe(this),this.classList.add("code-input_loaded")}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}get template(){return this.templateObject}set template(a){}connectedCallback(){this.templateObject=this.getTemplate(),this.templateObject!=null&&(this.classList.add("code-input_registered"),window.addEventListener("DOMContentLoaded",this.setup.bind(this)))}mutationObserverCallback(a){for(const b of a)if("attributes"===b.type){for(let a=0;a<codeInput.observedAttributes.length;a++)if(b.attributeName==codeInput.observedAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));for(let a=0;a<codeInput.textareaSyncAttributes.length;a++)if(b.attributeName==codeInput.textareaSyncAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));if("aria-"==b.attributeName.substring(0,5))return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName))}}disconnectedCallback(){this.mutationObserver.disconnect()}attributeChangedCallback(a,b,c){if(this.isConnected)switch(this.pluginEvt("attributeChanged",[a,b,c]),a){case"value":this.value=c;break;case"template":this.templateObject=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.templateObject.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.scheduleHighlight();break;case"lang":case"language":let d=this.codeElement,e=this.textareaElement;if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;null!==b&&(b=b.toLowerCase(),d.classList.remove("language-"+b),d.parentElement.classList.remove("language-"+b)),d.classList.remove("language-none"),d.parentElement.classList.remove("language-none"),null!=c&&""!=c&&d.classList.add("language-"+c),e.placeholder==b&&(e.placeholder=c),this.scheduleHighlight();break;default:codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5)?null==c||null==c?this.textareaElement.removeAttribute(a):this.textareaElement.setAttribute(a,c):codeInput.textareaSyncAttributes.regexp.forEach(b=>{a.match(b)&&(null==c?this.textareaElement.removeAttribute(a):this.textareaElement.setAttribute(a,c))})}}addEventListener(a,b,c=void 0){let d=function(a){"function"==typeof b?b(a):b&&b.handleEvent&&b.handleEvent(a)}.bind(this);this.boundEventCallbacks[b]=d,codeInput.textareaSyncEvents.includes(a)?(this.boundEventCallbacks[b]=d,c===void 0?null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d)}):this.textareaElement.addEventListener(a,d):null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d,c)}):this.textareaElement.addEventListener(a,d,c)):c===void 0?super.addEventListener(a,d):super.addEventListener(a,d,c)}removeEventListener(a,b,c=void 0){let d=this.boundEventCallbacks[b];codeInput.textareaSyncEvents.includes(a)?c===void 0?null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d)}):this.textareaElement.removeEventListener(a,d):null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d,c)}):this.textareaElement.removeEventListener(a,d,c):c===void 0?super.removeEventListener(a,d):super.removeEventListener(a,d,c)}getTextareaProperty(a,b=void 0){if(this.textareaElement)return this.textareaElement[a];else{const c=this.querySelector("textarea[data-code-input-fallback]");if(c)return c[a];if(void 0===b)throw new Error("Cannot get "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.");return b}}setTextareaProperty(a,b,c=!0){if(this.textareaElement)this.textareaElement[a]=b;else{const d=this.querySelector("textarea[data-code-input-fallback]");if(d)d[a]=b;else{if(!c)return(!1);throw new Error("Cannot set "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.")}}return(!0)}get autocomplete(){return this.getAttribute("autocomplete")}set autocomplete(a){return this.setAttribute("autocomplete",a)}get cols(){return this.getTextareaProperty("cols",+this.getAttribute("cols"))}set cols(a){this.setAttribute("cols",a)}get defaultValue(){return this.initialValue}set defaultValue(a){this.initialValue=a}get textContent(){return this.initialValue}set textContent(a){this.initialValue=a}get dirName(){return this.getAttribute("dirName")||""}set dirName(a){this.setAttribute("dirname",a)}get disabled(){return this.hasAttribute("disabled")}set disabled(a){a?this.setAttribute("disabled",!0):this.removeAttribute("disabled")}get form(){return this.getTextareaProperty("form")}get labels(){return this.getTextareaProperty("labels")}get maxLength(){const a=+this.getAttribute("maxlength");return isNaN(a)?-1:a}set maxLength(a){-1==a?this.removeAttribute("maxlength"):this.setAttribute("maxlength",a)}get minLength(){const a=+this.getAttribute("minlength");return isNaN(a)?-1:a}set minLength(a){-1==a?this.removeAttribute("minlength"):this.setAttribute("minlength",a)}get name(){return this.getAttribute("name")||""}set name(a){this.setAttribute("name",a)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(a){this.setAttribute("placeholder",a)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get required(){return this.hasAttribute("readonly")}set required(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get rows(){return this.getTextareaProperty("rows",+this.getAttribute("rows"))}set rows(a){this.setAttribute("rows",a)}get selectionDirection(){return this.getTextareaProperty("selectionDirection")}set selectionDirection(a){this.setTextareaProperty("selectionDirection",a)}get selectionEnd(){return this.getTextareaProperty("selectionEnd")}set selectionEnd(a){this.setTextareaProperty("selectionEnd",a)}get selectionStart(){return this.getTextareaProperty("selectionStart")}set selectionStart(a){this.setTextareaProperty("selectionStart",a)}get textLength(){return this.value.length}get type(){return"textarea"}get validationMessage(){return this.getTextareaProperty("validationMessage")}get validity(){return this.getTextareaProperty("validationMessage")}get value(){return this.getTextareaProperty("value",this.getAttribute("value")||this.innerHTML)}set value(a){a=a||"",this.setTextareaProperty("value",a,!1)?this.textareaElement&&this.scheduleHighlight():this.innerHTML=a}get willValidate(){return this.getTextareaProperty("willValidate",this.disabled||this.readOnly)}get wrap(){return this.getAttribute("wrap")||""}set wrap(a){this.setAttribute("wrap",a)}blur(a={}){return this.textareaElement.blur(a)}checkValidity(){return this.textareaElement.checkValidity()}focus(a={}){return this.textareaElement.focus(a)}reportValidity(){return this.textareaElement.reportValidity()}setCustomValidity(a){this.textareaElement.setCustomValidity(a)}setRangeText(a,b=this.selectionStart,c=this.selectionEnd,d="preserve"){this.getTextareaProperty("setRangeText")(a,b,c,d)}setSelectionRange(a,b,c="none"){this.getTextareaProperty("setSelectionRange")(a,b,c)}pluginData={};formResetCallback(){this.value=this.initialValue}}};{class a extends codeInput.Template{constructor(a,b=[],c=!0){super(a.highlightElement,c,!0,!1,b)}}codeInput.templates.Prism=a;class b extends codeInput.Template{constructor(a,b=[],c=!1){super(function(b){b.removeAttribute("data-highlighted"),a.highlightElement(b)},c,!0,!1,b)}}codeInput.templates.Hljs=b}customElements.define("code-input",codeInput.CodeInput);
|
|
12
|
+
*/"use strict";var codeInput={observedAttributes:["value","placeholder","language","lang","template"],textareaSyncAttributes:["value","min","max","type","pattern","autocomplete","autocorrect","autofocus","cols","dirname","disabled","form","maxlength","minlength","name","placeholder","readonly","required","rows","spellcheck","wrap"],textareaSyncEvents:["change","selectionchange","invalid","input","focus","blur","focusin","focusout"],usedTemplates:{},defaultTemplate:void 0,templateNotYetRegisteredQueue:{},registerTemplate:function(a,b){if(!("string"==typeof a||a instanceof String))throw TypeError(`code-input: Name of template "${a}" must be a string.`);if(!("function"==typeof b.highlight||b.highlight instanceof Function))throw TypeError(`code-input: Template for "${a}" invalid, because the highlight function provided is not a function; it is "${b.highlight}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.includeCodeInputInHighlightFunc||b.includeCodeInputInHighlightFunc instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the includeCodeInputInHighlightFunc value provided is not a true or false; it is "${b.includeCodeInputInHighlightFunc}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.preElementStyled||b.preElementStyled instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the preElementStyled value provided is not a true or false; it is "${b.preElementStyled}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!("boolean"==typeof b.isCode||b.isCode instanceof Boolean))throw TypeError(`code-input: Template for "${a}" invalid, because the isCode value provided is not a true or false; it is "${b.isCode}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(!Array.isArray(b.plugins))throw TypeError(`code-input: Template for "${a}" invalid, because the plugin array provided is not an array; it is "${b.plugins}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`);if(b.plugins.forEach((c,d)=>{if(!(c instanceof codeInput.Plugin))throw TypeError(`code-input: Template for "${a}" invalid, because the plugin provided at index ${d} is not valid; it is "${b.plugins[d]}". Please make sure you use one of the constructors in codeInput.templates, and that you provide the correct arguments.`)}),codeInput.usedTemplates[a]=b,a in codeInput.templateNotYetRegisteredQueue)for(let c in codeInput.templateNotYetRegisteredQueue[a]){const d=codeInput.templateNotYetRegisteredQueue[a][c];d.templateObject=b,d.setup()}if(null==codeInput.defaultTemplate&&(codeInput.defaultTemplate=a,void 0 in codeInput.templateNotYetRegisteredQueue))for(let a in codeInput.templateNotYetRegisteredQueue[void 0]){const c=codeInput.templateNotYetRegisteredQueue[void 0][a];c.templateObject=b,c.setup()}},Template:class{constructor(a=function(){},b=!0,c=!0,d=!1,e=[]){this.highlight=a,this.preElementStyled=b,this.isCode=c,this.includeCodeInputInHighlightFunc=d,this.plugins=e}highlight=function(){};preElementStyled=!0;isCode=!0;includeCodeInputInHighlightFunc=!1;plugins=[]},templates:{prism(a,b=[]){return new codeInput.templates.Prism(a,b)},hljs(a,b=[]){return new codeInput.templates.Hljs(a,b)},characterLimit(a){return{highlight:function(a,b,c=[]){let d=+b.getAttribute("data-character-limit"),e=b.escapeHtml(b.value.slice(0,d)),f=b.escapeHtml(b.value.slice(d));a.innerHTML=`${e}<mark class="overflow">${f}</mark>`,0<f.length&&(a.innerHTML+=` <mark class="overflow-msg">${b.getAttribute("data-overflow-msg")||"(Character limit reached)"}</mark>`)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,plugins:a}},rainbowText(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return{highlight:function(a,b){let c=[],d=b.value.split(b.template.delimiter);for(let e=0;e<d.length;e++)c.push(`<span style="color: ${b.template.rainbowColors[e%b.template.rainbowColors.length]}">${b.escapeHtml(d[e])}</span>`);a.innerHTML=c.join(b.template.delimiter)},includeCodeInputInHighlightFunc:!0,preElementStyled:!0,isCode:!1,rainbowColors:a,delimiter:b,plugins:c}},character_limit(){return this.characterLimit([])},rainbow_text(a=["red","orangered","orange","goldenrod","gold","green","darkgreen","navy","blue","magenta"],b="",c=[]){return this.rainbowText(a,b,c)},custom(a=function(){},b=!0,c=!0,d=!1,e=[]){return{highlight:a,includeCodeInputInHighlightFunc:d,preElementStyled:b,isCode:c,plugins:e}}},plugins:new Proxy({},{get(a,b){if(a[b]==null)throw ReferenceError(`code-input: Plugin '${b}' is not defined. Please ensure you import the necessary files from the plugins folder in the WebCoder49/code-input repository, in the <head> of your HTML, before the plugin is instatiated.`);return a[b]}}),Plugin:class{constructor(a){a.forEach(a=>{codeInput.observedAttributes.push(a)})}addTranslations(a,b){for(const c in b)a[c]=b[c]}beforeHighlight(){}afterHighlight(){}beforeElementsAdded(){}afterElementsAdded(){}attributeChanged(){}},CodeInput:class extends HTMLElement{constructor(){super()}templateObject=null;textareaElement=null;preElement=null;codeElement=null;dialogContainerElement=null;static formAssociated=!0;boundEventCallbacks={};pluginEvt(a,b){for(let c in this.templateObject.plugins){let d=this.templateObject.plugins[c];a in d&&(b===void 0?d[a](this):d[a](this,...b))}}needsHighlight=!1;originalAriaDescription;scheduleHighlight(){this.needsHighlight=!0}animateFrame(){this.needsHighlight&&(this.update(),this.needsHighlight=!1),window.requestAnimationFrame(this.animateFrame.bind(this))}update(){let a=this.codeElement,b=this.value;b+="\n",a.innerHTML=this.escapeHtml(b),this.pluginEvt("beforeHighlight"),this.templateObject.includeCodeInputInHighlightFunc?this.templateObject.highlight(a,this):this.templateObject.highlight(a),this.syncSize(),this.pluginEvt("afterHighlight")}syncSize(){this.templateObject.preElementStyled?(this.style.backgroundColor=getComputedStyle(this.preElement).backgroundColor,this.textareaElement.style.height=getComputedStyle(this.preElement).height,this.textareaElement.style.width=getComputedStyle(this.preElement).width):(this.style.backgroundColor=getComputedStyle(this.codeElement).backgroundColor,this.textareaElement.style.height=getComputedStyle(this.codeElement).height,this.textareaElement.style.width=getComputedStyle(this.codeElement).width)}setKeyboardNavInstructions(a,b){this.dialogContainerElement.querySelector(".code-input_keyboard-navigation-instructions").innerText=a,b?this.textareaElement.setAttribute("aria-description",this.originalAriaDescription+". "+a):this.textareaElement.setAttribute("aria-description",a)}escapeHtml(a){return a.replace(/&/g,"&").replace(/</g,"<")}unescapeHtml(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}getTemplate(){let a;return a=null==this.getAttribute("template")?codeInput.defaultTemplate:this.getAttribute("template"),a in codeInput.usedTemplates?codeInput.usedTemplates[a]:(a in codeInput.templateNotYetRegisteredQueue||(codeInput.templateNotYetRegisteredQueue[a]=[]),void codeInput.templateNotYetRegisteredQueue[a].push(this))}setup(){if(null!=this.textareaElement)return;this.classList.add("code-input_registered"),this.mutationObserver=new MutationObserver(this.mutationObserverCallback.bind(this)),this.mutationObserver.observe(this,{attributes:!0,attributeOldValue:!0}),this.classList.add("code-input_registered"),this.templateObject.preElementStyled&&this.classList.add("code-input_pre-element-styled");const a=this.querySelector("textarea[data-code-input-fallback]");let b,c,d,e,f,g=!1;a&&(a===document.activeElement&&(g=!0),b=a.selectionStart,c=a.selectionEnd,d=a.selectionDirection,e=a.scrollLeft,f=a.scrollTop);let h;if(a){let b=a.getAttributeNames();for(let c=0;c<b.length;c++){const d=b[c];"data-code-input-fallback"!=d&&(this.hasAttribute(d)||this.setAttribute(d,a.getAttribute(d)))}h=a.value,this.innerHTML=this.escapeHtml(h)}else h=this.unescapeHtml(this.innerHTML);h=h||this.getAttribute("value")||"",this.pluginEvt("beforeElementsAdded");const i=this.getAttribute("language")||this.getAttribute("lang"),j=this.getAttribute("placeholder")||i||"";this.initialValue=h;const k=document.createElement("textarea");k.placeholder=j,""!=h&&(k.value=h),k.innerHTML=this.innerHTML,this.hasAttribute("spellcheck")||k.setAttribute("spellcheck","false"),k.setAttribute("tabindex",this.getAttribute("tabindex")||0),this.setAttribute("tabindex",-1),this.originalAriaDescription=this.getAttribute("aria-description")||"Code input field",this.addEventListener("mousedown",()=>{this.classList.add("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("blur",()=>{this.classList.remove("code-input_mouse-focused"),window.setTimeout(()=>{this.syncSize()},0)}),k.addEventListener("focus",()=>{window.setTimeout(()=>{this.syncSize()},0)}),this.innerHTML="";for(let a,b=0;b<this.attributes.length;b++)a=this.attributes[b].name,(codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5))&&k.setAttribute(a,this.getAttribute(a));k.addEventListener("input",()=>{this.value=this.textareaElement.value}),this.textareaElement=k,this.append(k);let l=document.createElement("code"),m=document.createElement("pre");m.setAttribute("aria-hidden","true"),m.setAttribute("tabindex","-1"),m.setAttribute("inert",!0),this.preElement=m,this.codeElement=l,m.append(l),this.append(m),this.templateObject.isCode&&i!=null&&""!=i&&l.classList.add("language-"+i.toLowerCase());let n=document.createElement("div");n.classList.add("code-input_dialog-container"),this.append(n),this.dialogContainerElement=n;let o=document.createElement("div");o.classList.add("code-input_keyboard-navigation-instructions"),n.append(o),this.pluginEvt("afterElementsAdded"),this.dispatchEvent(new CustomEvent("code-input_load")),this.value=h,b!==void 0&&(console.log("sel",b,c,d,"scr",f,e,"foc",g),k.setSelectionRange(b,c,d),k.scrollTo(f,e)),g&&k.focus(),this.animateFrame();const p=new ResizeObserver(()=>{this.syncSize()});p.observe(this.textareaElement),this.classList.add("code-input_loaded")}escape_html(a){return this.escapeHtml(a)}get_template(){return this.getTemplate()}get template(){return this.templateObject}set template(a){}connectedCallback(){this.templateObject=this.getTemplate(),this.templateObject!=null&&(this.classList.add("code-input_registered"),window.addEventListener("DOMContentLoaded",this.setup.bind(this)))}mutationObserverCallback(a){for(const b of a)if("attributes"===b.type){for(let a=0;a<codeInput.observedAttributes.length;a++)if(b.attributeName==codeInput.observedAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));for(let a=0;a<codeInput.textareaSyncAttributes.length;a++)if(b.attributeName==codeInput.textareaSyncAttributes[a])return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName));if("aria-"==b.attributeName.substring(0,5))return this.attributeChangedCallback(b.attributeName,b.oldValue,super.getAttribute(b.attributeName))}}disconnectedCallback(){this.mutationObserver.disconnect()}attributeChangedCallback(a,b,c){if(this.isConnected)switch(this.pluginEvt("attributeChanged",[a,b,c]),a){case"value":this.value=c;break;case"template":this.templateObject=codeInput.usedTemplates[c||codeInput.defaultTemplate],this.templateObject.preElementStyled?this.classList.add("code-input_pre-element-styled"):this.classList.remove("code-input_pre-element-styled"),this.scheduleHighlight();break;case"lang":case"language":let d=this.codeElement,e=this.textareaElement;if(null!=c&&(c=c.toLowerCase(),d.classList.contains(`language-${c}`)))break;null!==b&&(b=b.toLowerCase(),d.classList.remove("language-"+b),d.parentElement.classList.remove("language-"+b)),d.classList.remove("language-none"),d.parentElement.classList.remove("language-none"),null!=c&&""!=c&&d.classList.add("language-"+c),e.placeholder==b&&(e.placeholder=c),this.scheduleHighlight();break;default:codeInput.textareaSyncAttributes.includes(a)||"aria-"==a.substring(0,5)?null==c||null==c?this.textareaElement.removeAttribute(a):this.textareaElement.setAttribute(a,c):codeInput.textareaSyncAttributes.regexp.forEach(b=>{a.match(b)&&(null==c?this.textareaElement.removeAttribute(a):this.textareaElement.setAttribute(a,c))})}}addEventListener(a,b,c=void 0){let d=function(a){"function"==typeof b?b(a):b&&b.handleEvent&&b.handleEvent(a)}.bind(this);this.boundEventCallbacks[b]=d,codeInput.textareaSyncEvents.includes(a)?(this.boundEventCallbacks[b]=d,c===void 0?null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d)}):this.textareaElement.addEventListener(a,d):null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.addEventListener(a,d,c)}):this.textareaElement.addEventListener(a,d,c)):c===void 0?super.addEventListener(a,d):super.addEventListener(a,d,c)}removeEventListener(a,b,c=void 0){let d=this.boundEventCallbacks[b];codeInput.textareaSyncEvents.includes(a)?c===void 0?null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d)}):this.textareaElement.removeEventListener(a,d):null==this.textareaElement?this.addEventListener("code-input_load",()=>{this.textareaElement.removeEventListener(a,d,c)}):this.textareaElement.removeEventListener(a,d,c):c===void 0?super.removeEventListener(a,d):super.removeEventListener(a,d,c)}getTextareaProperty(a,b=void 0){if(this.textareaElement)return this.textareaElement[a];else{const c=this.querySelector("textarea[data-code-input-fallback]");if(c)return c[a];if(void 0===b)throw new Error("Cannot get "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.");return b}}setTextareaProperty(a,b,c=!0){if(this.textareaElement)this.textareaElement[a]=b;else{const d=this.querySelector("textarea[data-code-input-fallback]");if(d)d[a]=b;else{if(!c)return(!1);throw new Error("Cannot set "+a+" of an unregistered code-input element without a data-code-input-fallback textarea.")}}return(!0)}get autocomplete(){return this.getAttribute("autocomplete")}set autocomplete(a){return this.setAttribute("autocomplete",a)}get cols(){return this.getTextareaProperty("cols",+this.getAttribute("cols"))}set cols(a){this.setAttribute("cols",a)}get defaultValue(){return this.initialValue}set defaultValue(a){this.initialValue=a}get textContent(){return this.initialValue}set textContent(a){this.initialValue=a}get dirName(){return this.getAttribute("dirName")||""}set dirName(a){this.setAttribute("dirname",a)}get disabled(){return this.hasAttribute("disabled")}set disabled(a){a?this.setAttribute("disabled",!0):this.removeAttribute("disabled")}get form(){return this.getTextareaProperty("form")}get labels(){return this.getTextareaProperty("labels")}get maxLength(){const a=+this.getAttribute("maxlength");return isNaN(a)?-1:a}set maxLength(a){-1==a?this.removeAttribute("maxlength"):this.setAttribute("maxlength",a)}get minLength(){const a=+this.getAttribute("minlength");return isNaN(a)?-1:a}set minLength(a){-1==a?this.removeAttribute("minlength"):this.setAttribute("minlength",a)}get name(){return this.getAttribute("name")||""}set name(a){this.setAttribute("name",a)}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(a){this.setAttribute("placeholder",a)}get readOnly(){return this.hasAttribute("readonly")}set readOnly(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get required(){return this.hasAttribute("readonly")}set required(a){a?this.setAttribute("readonly",!0):this.removeAttribute("readonly")}get rows(){return this.getTextareaProperty("rows",+this.getAttribute("rows"))}set rows(a){this.setAttribute("rows",a)}get selectionDirection(){return this.getTextareaProperty("selectionDirection")}set selectionDirection(a){this.setTextareaProperty("selectionDirection",a)}get selectionEnd(){return this.getTextareaProperty("selectionEnd")}set selectionEnd(a){this.setTextareaProperty("selectionEnd",a)}get selectionStart(){return this.getTextareaProperty("selectionStart")}set selectionStart(a){this.setTextareaProperty("selectionStart",a)}get textLength(){return this.value.length}get type(){return"textarea"}get validationMessage(){return this.getTextareaProperty("validationMessage")}get validity(){return this.getTextareaProperty("validationMessage")}get value(){return this.getTextareaProperty("value",this.getAttribute("value")||this.innerHTML)}set value(a){a=a||"",this.setTextareaProperty("value",a,!1)?this.textareaElement&&this.scheduleHighlight():this.innerHTML=a}get willValidate(){return this.getTextareaProperty("willValidate",this.disabled||this.readOnly)}get wrap(){return this.getAttribute("wrap")||""}set wrap(a){this.setAttribute("wrap",a)}getTextareaMethod(a){if(this.textareaElement)return this.textareaElement[a].bind(this.textareaElement);else{const b=this.querySelector("textarea[data-code-input-fallback]");if(b)return b[a].bind(b);throw new Error("Cannot call "+a+" on an unregistered code-input element without a data-code-input-fallback textarea.")}}blur(a={}){this.getTextareaMethod("blur")(a)}checkValidity(){return this.getTextareaMethod("checkValidity")()}focus(a={}){this.getTextareaMethod("focus")(a)}reportValidity(){return this.getTextareaMethod("reportValidity")()}setCustomValidity(a){this.getTextareaMethod("setCustomValidity")(a)}setRangeText(a,b=this.selectionStart,c=this.selectionEnd,d="preserve"){this.getTextareaMethod("setRangeText")(a,b,c,d),this.textareaElement&&this.scheduleHighlight()}setSelectionRange(a,b,c="none"){this.getTextareaMethod("setSelectionRange")(a,b,c)}pluginData={};formResetCallback(){this.value=this.initialValue}}};{class a extends codeInput.Template{constructor(a,b=[],c=!0){super(a.highlightElement,c,!0,!1,b)}}codeInput.templates.Prism=a;class b extends codeInput.Template{constructor(a,b=[],c=!1){super(function(b){b.removeAttribute("data-highlighted"),a.highlightElement(b)},c,!0,!1,b)}}codeInput.templates.Hljs=b}customElements.define("code-input",codeInput.CodeInput);
|
package/docs/_index.md
CHANGED
|
@@ -10,7 +10,7 @@ Aiming to be [more <mark>flexible</mark>, <mark>lightweight</mark>,
|
|
|
10
10
|
[HTML forms](interface/forms), the [`<textarea>` JavaScript interface](interface/js), more languages and
|
|
11
11
|
more use cases.
|
|
12
12
|
|
|
13
|
-
*code-input.js is free, libre, open source software under the MIT (AKA Expat) license.* **Download it [from the Git repository](https://github.com/WebCoder49/code-input/tree/v2.6.
|
|
13
|
+
*code-input.js is free, libre, open source software under the MIT (AKA Expat) license.* **Download it [from the Git repository](https://github.com/WebCoder49/code-input/tree/v2.6.5), [in a ZIP archive](/release/code-input-js-v2.6.5.zip), [in a TAR.GZ archive](/release/code-input-js-v2.6.5.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
14
|
|
|
15
15
|
## Get Started with a Demo
|
|
16
16
|
|
|
@@ -7,6 +7,6 @@ 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;">...`)
|
|
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`).
|
|
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
12
|
* For now, elements on top of `code-input` elements should have a CSS `z-index` at least 3 greater than the `code-input` element.
|
|
@@ -60,7 +60,7 @@ Note the `.mjs` extensions on code-input.js import paths. They are needed, and a
|
|
|
60
60
|
The import paths above assume a package manager and `package.json` export paths are being used.
|
|
61
61
|
|
|
62
62
|
In some setups, this will not work. You have two options (replace `node_modules/@webcoder49/code-input` with the relative path to the library, if it is different):
|
|
63
|
-
* use relative paths instead: replace `"@webcoder49/code-input/path/to/file.mjs"` with `"node_modules/@webcoder49/code-input/esm/path/to/file.mjs"` (note the `esm` directory). Also replace `"@webcoder49/code-input/path/to/file.mjs"` with `"node_modules/@highlightjs/cdn-assets/es/path/to/file.mjs"` (note the `es` directory) *If you're not using an import map yet, I recommend this option because import maps are not supported on as many browsers.*
|
|
63
|
+
* use relative paths instead: assuming you are importing from your project's root directory and have installed the libraries with a typical JS package manager, replace `"@webcoder49/code-input/path/to/file.mjs"` with `"./node_modules/@webcoder49/code-input/esm/path/to/file.mjs"` (note the `esm` directory). Also replace `"@webcoder49/code-input/path/to/file.mjs"` with `"./node_modules/@highlightjs/cdn-assets/es/path/to/file.mjs"` (note the `es` directory) *If you're not using an import map yet, I recommend this option because import maps are not supported on as many browsers.*
|
|
64
64
|
* If you're using an [import map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#importing_modules_using_import_maps), add the following to it:
|
|
65
65
|
```json
|
|
66
66
|
{
|
package/esm/code-input.mjs
CHANGED
|
@@ -518,9 +518,26 @@ var codeInput = {
|
|
|
518
518
|
this.classList.add("code-input_registered"); // Remove register message
|
|
519
519
|
if (this.templateObject.preElementStyled) this.classList.add("code-input_pre-element-styled");
|
|
520
520
|
|
|
521
|
-
this.pluginEvt("beforeElementsAdded");
|
|
522
|
-
|
|
523
521
|
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
522
|
+
let fallbackFocused = false;
|
|
523
|
+
let fallbackSelectionStart = undefined;
|
|
524
|
+
let fallbackSelectionEnd = undefined;
|
|
525
|
+
let fallbackSelectionDirection = undefined;
|
|
526
|
+
let fallbackScrollLeft = undefined;
|
|
527
|
+
let fallbackScrollTop = undefined;
|
|
528
|
+
if(fallbackTextarea) {
|
|
529
|
+
// Move some attributes to new textarea so typing during
|
|
530
|
+
// slow load not interrupted
|
|
531
|
+
if(fallbackTextarea === document.activeElement) { // Thanks to https://stackoverflow.com/a/36430896
|
|
532
|
+
fallbackFocused = true;
|
|
533
|
+
}
|
|
534
|
+
fallbackSelectionStart = fallbackTextarea.selectionStart;
|
|
535
|
+
fallbackSelectionEnd = fallbackTextarea.selectionEnd;
|
|
536
|
+
fallbackSelectionDirection = fallbackTextarea.selectionDirection;
|
|
537
|
+
fallbackScrollLeft = fallbackTextarea.scrollLeft;
|
|
538
|
+
fallbackScrollTop = fallbackTextarea.scrollTop;
|
|
539
|
+
}
|
|
540
|
+
|
|
524
541
|
let value;
|
|
525
542
|
if(fallbackTextarea) {
|
|
526
543
|
// Fallback textarea exists
|
|
@@ -536,11 +553,15 @@ var codeInput = {
|
|
|
536
553
|
}
|
|
537
554
|
// Sync value
|
|
538
555
|
value = fallbackTextarea.value;
|
|
556
|
+
// Backwards compatibility with plugins
|
|
557
|
+
this.innerHTML = this.escapeHtml(value);
|
|
539
558
|
} else {
|
|
540
559
|
value = this.unescapeHtml(this.innerHTML);
|
|
541
560
|
}
|
|
542
561
|
value = value || this.getAttribute("value") || "";
|
|
543
562
|
|
|
563
|
+
this.pluginEvt("beforeElementsAdded");
|
|
564
|
+
|
|
544
565
|
// First-time attribute sync
|
|
545
566
|
const lang = this.getAttribute("language") || this.getAttribute("lang");
|
|
546
567
|
const placeholder = this.getAttribute("placeholder") || lang || "";
|
|
@@ -569,9 +590,23 @@ var codeInput = {
|
|
|
569
590
|
// Accessibility - detect when mouse focus to remove focus outline + keyboard navigation guidance that could irritate users.
|
|
570
591
|
this.addEventListener("mousedown", () => {
|
|
571
592
|
this.classList.add("code-input_mouse-focused");
|
|
593
|
+
// Wait for CSS to update padding
|
|
594
|
+
window.setTimeout(() => {
|
|
595
|
+
this.syncSize();
|
|
596
|
+
}, 0);
|
|
572
597
|
});
|
|
573
598
|
textarea.addEventListener("blur", () => {
|
|
574
599
|
this.classList.remove("code-input_mouse-focused");
|
|
600
|
+
// Wait for CSS to update padding
|
|
601
|
+
window.setTimeout(() => {
|
|
602
|
+
this.syncSize();
|
|
603
|
+
}, 0);
|
|
604
|
+
});
|
|
605
|
+
textarea.addEventListener("focus", () => {
|
|
606
|
+
// Wait for CSS to update padding
|
|
607
|
+
window.setTimeout(() => {
|
|
608
|
+
this.syncSize();
|
|
609
|
+
}, 0);
|
|
575
610
|
});
|
|
576
611
|
|
|
577
612
|
this.innerHTML = ""; // Clear Content
|
|
@@ -624,13 +659,25 @@ var codeInput = {
|
|
|
624
659
|
this.dispatchEvent(new CustomEvent("code-input_load"));
|
|
625
660
|
|
|
626
661
|
this.value = value;
|
|
662
|
+
|
|
663
|
+
// Update with fallback textarea's state so can keep editing
|
|
664
|
+
// if loaded slowly
|
|
665
|
+
if(fallbackSelectionStart !== undefined) {
|
|
666
|
+
console.log("sel", fallbackSelectionStart, fallbackSelectionEnd, fallbackSelectionDirection, "scr", fallbackScrollTop, fallbackScrollLeft, "foc", fallbackFocused);
|
|
667
|
+
textarea.setSelectionRange(fallbackSelectionStart, fallbackSelectionEnd, fallbackSelectionDirection);
|
|
668
|
+
textarea.scrollTo(fallbackScrollTop, fallbackScrollLeft);
|
|
669
|
+
}
|
|
670
|
+
if(fallbackFocused) {
|
|
671
|
+
textarea.focus();
|
|
672
|
+
}
|
|
673
|
+
|
|
627
674
|
this.animateFrame();
|
|
628
675
|
|
|
629
676
|
const resizeObserver = new ResizeObserver((elements) => {
|
|
630
677
|
// The only element that could be resized is this code-input element.
|
|
631
678
|
this.syncSize();
|
|
632
679
|
});
|
|
633
|
-
resizeObserver.observe(this);
|
|
680
|
+
resizeObserver.observe(this.textareaElement);
|
|
634
681
|
|
|
635
682
|
this.classList.add("code-input_loaded");
|
|
636
683
|
}
|
|
@@ -1026,14 +1073,40 @@ var codeInput = {
|
|
|
1026
1073
|
get wrap() { return this.getAttribute("wrap") || ""; }
|
|
1027
1074
|
set wrap(val) { this.setAttribute("wrap", val); }
|
|
1028
1075
|
|
|
1076
|
+
/**
|
|
1077
|
+
* Get the JavaScript method from the internal textarea
|
|
1078
|
+
* element, throwing an error when no textarea is present.
|
|
1079
|
+
* The method is bound to the textarea as `this`.
|
|
1080
|
+
*
|
|
1081
|
+
* For internal use - treat the code-input element as a
|
|
1082
|
+
* textarea for the standard functions (e.g. document.
|
|
1083
|
+
* querySelector("code-input").focus()).
|
|
1084
|
+
*/
|
|
1085
|
+
getTextareaMethod(name) {
|
|
1086
|
+
if(this.textareaElement) {
|
|
1087
|
+
return this.textareaElement[name].bind(this.textareaElement);
|
|
1088
|
+
} else {
|
|
1089
|
+
// Unregistered
|
|
1090
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
1091
|
+
if(fallbackTextarea) {
|
|
1092
|
+
return fallbackTextarea[name].bind(fallbackTextarea);
|
|
1093
|
+
} else {
|
|
1094
|
+
throw new Error("Cannot call "+name+" on an unregistered code-input element without a data-code-input-fallback textarea.");
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1029
1098
|
|
|
1030
|
-
blur(options={}) {
|
|
1031
|
-
checkValidity() { return this.
|
|
1032
|
-
focus(options={}) {
|
|
1033
|
-
reportValidity() { return this.
|
|
1034
|
-
setCustomValidity(error) { this.
|
|
1035
|
-
setRangeText(replacement, selectionStart=this.selectionStart, selectionEnd=this.selectionEnd, selectMode="preserve") {
|
|
1036
|
-
|
|
1099
|
+
blur(options={}) { this.getTextareaMethod("blur")(options); }
|
|
1100
|
+
checkValidity() { return this.getTextareaMethod("checkValidity")(); }
|
|
1101
|
+
focus(options={}) { this.getTextareaMethod("focus")(options); }
|
|
1102
|
+
reportValidity() { return this.getTextareaMethod("reportValidity")(); }
|
|
1103
|
+
setCustomValidity(error) { this.getTextareaMethod("setCustomValidity")(error); }
|
|
1104
|
+
setRangeText(replacement, selectionStart=this.selectionStart, selectionEnd=this.selectionEnd, selectMode="preserve") {
|
|
1105
|
+
this.getTextareaMethod("setRangeText")(replacement, selectionStart, selectionEnd, selectMode);
|
|
1106
|
+
// Reflect that value updated
|
|
1107
|
+
if(this.textareaElement) this.scheduleHighlight();
|
|
1108
|
+
}
|
|
1109
|
+
setSelectionRange(selectionStart, selectionEnd, selectionDirection="none") { this.getTextareaMethod("setSelectionRange")(selectionStart, selectionEnd, selectionDirection); }
|
|
1037
1110
|
|
|
1038
1111
|
/**
|
|
1039
1112
|
* Allows plugins to store data in the scope of a single element.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webcoder49/code-input",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.5",
|
|
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": {
|
|
@@ -7,13 +7,18 @@
|
|
|
7
7
|
/* Update padding to match line-numbers plugin */
|
|
8
8
|
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,
|
|
9
9
|
.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 {
|
|
10
|
-
padding-left: max(3.8em, var(--padding, 16px))!important;
|
|
10
|
+
padding-left: max(3.8em, var(--padding-left, 16px))!important;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/* Ensure pre code/textarea just wide enough to give 100% width with line numbers */
|
|
14
14
|
code-input.line-numbers, .line-numbers code-input {
|
|
15
|
-
grid-template-columns: calc(100% - max(0em, calc(3.8em - var(--padding, 16px))));
|
|
15
|
+
grid-template-columns: calc(100% - max(0em, calc(3.8em - var(--padding-left, 16px))));
|
|
16
16
|
}
|
|
17
|
+
/* Despite the above, keep dialog container full width */
|
|
18
|
+
code-input.line-numbers .code-input_dialog-container, .line-numbers code-input .code-input_dialog-container {
|
|
19
|
+
width: calc(100% + max(0em, calc(3.8em - var(--padding-left, 16px))));
|
|
20
|
+
}
|
|
21
|
+
|
|
17
22
|
|
|
18
23
|
/* Override Prism styles so there's no display:inline, relatively-positioned code element which breaks offsetTop, used in FindAndReplace, in Firefox. */
|
|
19
24
|
code-input pre[class*=language-].line-numbers>code {
|
|
@@ -21,10 +26,10 @@ code-input pre[class*=language-].line-numbers>code {
|
|
|
21
26
|
}
|
|
22
27
|
/* Line numbers now positioned relative to the pre element not the code element. */
|
|
23
28
|
code-input .line-numbers .line-numbers-rows {
|
|
24
|
-
left:
|
|
25
|
-
top: var(--padding);
|
|
29
|
+
left: max(0em, calc(var(--padding-left, 16px) - 3.8em));
|
|
30
|
+
top: var(--padding-top);
|
|
26
31
|
}
|
|
27
32
|
/* Things with padding when instructions are present */
|
|
28
33
|
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 {
|
|
29
|
-
top: calc(var(--padding) + 3em);
|
|
34
|
+
top: calc(var(--padding-top) + 3em);
|
|
30
35
|
}
|
|
@@ -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,16px))!important}.line-numbers code-input,code-input.line-numbers{grid-template-columns:calc(100% - max(0em,calc(3.8em - var(--padding,16px))))}code-input pre[class*=language-].line-numbers>code{position:static}code-input .line-numbers .line-numbers-rows{left:0;top:var(--padding)}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) + 3em)}
|
|
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)}
|