@webcoder49/code-input 2.5.1 → 2.6.2
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/LICENSE +1 -1
- package/README.md +9 -126
- package/code-input.css +70 -33
- package/code-input.d.ts +135 -59
- package/code-input.js +201 -110
- package/code-input.min.css +1 -1
- package/code-input.min.js +12 -1
- package/docs/LICENSE +3 -0
- package/docs/LICENSE.CC-BY-SA-4.0 +116 -0
- package/docs/LICENSE.CC0-1.0 +30 -0
- package/docs/README.md +5 -0
- package/docs/_index.md +308 -0
- package/docs/i18n/_index.md +52 -0
- package/docs/interface/_index.md +3 -0
- package/docs/interface/css/_index.md +12 -0
- package/docs/interface/forms/_index.md +17 -0
- package/docs/interface/js/_index.md +11 -0
- package/docs/modules-and-frameworks/_index.md +3 -0
- package/docs/modules-and-frameworks/custom/_index.md +9 -0
- package/docs/modules-and-frameworks/hljs/_index.md +13 -0
- package/docs/modules-and-frameworks/hljs/esm/_index.md +71 -0
- package/docs/modules-and-frameworks/hljs/nuxt/_index.md +250 -0
- package/docs/modules-and-frameworks/hljs/nuxt/nuxt-demo-screenshot.png +0 -0
- package/docs/modules-and-frameworks/hljs/vue/_index.md +233 -0
- package/docs/modules-and-frameworks/hljs/vue/vue-demo-screenshot.png +0 -0
- package/docs/modules-and-frameworks/prism/_index.md +14 -0
- package/docs/plugins/_index.md +676 -0
- package/docs/plugins/new/_index.md +52 -0
- package/docs/theory/_index.md +9 -0
- package/esm/README.md +23 -0
- package/esm/code-input.d.mts +154 -0
- package/esm/code-input.mjs +997 -0
- package/esm/plugins/auto-close-brackets.d.mts +15 -0
- package/esm/plugins/auto-close-brackets.mjs +84 -0
- package/esm/plugins/autocomplete.d.mts +14 -0
- package/esm/plugins/autocomplete.mjs +93 -0
- package/esm/plugins/autodetect.d.mts +11 -0
- package/esm/plugins/autodetect.mjs +35 -0
- package/esm/plugins/find-and-replace.d.mts +43 -0
- package/esm/plugins/find-and-replace.mjs +777 -0
- package/esm/plugins/go-to-line.d.mts +29 -0
- package/esm/plugins/go-to-line.mjs +217 -0
- package/esm/plugins/indent.d.mts +22 -0
- package/esm/plugins/indent.mjs +359 -0
- package/esm/plugins/select-token-callbacks.d.mts +51 -0
- package/esm/plugins/select-token-callbacks.mjs +296 -0
- package/esm/plugins/special-chars.d.mts +25 -0
- package/esm/plugins/special-chars.mjs +207 -0
- package/esm/plugins/test.d.mts +16 -0
- package/esm/plugins/test.mjs +56 -0
- package/esm/templates/hljs.d.mts +16 -0
- package/esm/templates/hljs.mjs +28 -0
- package/esm/templates/prism.d.mts +16 -0
- package/esm/templates/prism.mjs +25 -0
- package/package.json +83 -7
- package/plugins/README.md +2 -0
- package/plugins/auto-close-brackets.js +2 -0
- package/plugins/auto-close-brackets.min.js +1 -1
- package/plugins/autocomplete.js +6 -6
- package/plugins/autocomplete.min.js +1 -1
- package/plugins/autodetect.js +4 -2
- package/plugins/autodetect.min.js +1 -1
- package/plugins/find-and-replace.css +0 -4
- package/plugins/find-and-replace.js +28 -8
- package/plugins/find-and-replace.min.css +1 -1
- package/plugins/find-and-replace.min.js +1 -1
- package/plugins/go-to-line.css +10 -5
- package/plugins/go-to-line.js +39 -6
- package/plugins/go-to-line.min.css +1 -1
- package/plugins/go-to-line.min.js +1 -1
- package/plugins/indent.js +4 -2
- package/plugins/indent.min.js +1 -1
- package/plugins/prism-line-numbers.css +14 -5
- package/plugins/prism-line-numbers.min.css +1 -1
- package/plugins/select-token-callbacks.js +3 -1
- package/plugins/select-token-callbacks.min.js +1 -1
- package/plugins/special-chars.css +13 -1
- package/plugins/special-chars.js +14 -4
- package/plugins/special-chars.min.css +1 -1
- package/plugins/special-chars.min.js +1 -1
- package/plugins/test.js +22 -7
- package/plugins/test.min.js +1 -1
- package/.github/workflows/minify.yml +0 -22
- package/.github/workflows/npm-publish.yml +0 -21
- package/CODE_OF_CONDUCT.md +0 -130
- package/CONTRIBUTING.md +0 -35
- package/tests/hljs.html +0 -55
- package/tests/i18n.html +0 -197
- package/tests/prism-match-braces-compatibility.js +0 -215
- package/tests/prism-match-braces-compatibility.min.js +0 -1
- package/tests/prism.html +0 -54
- package/tests/tester.js +0 -600
- package/tests/tester.min.js +0 -21
package/code-input.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* **code-input** is a library which lets you create custom HTML `<code-input>`
|
|
3
3
|
* elements that act like `<textarea>` elements but support syntax-highlighted
|
|
4
|
-
* code, implemented using any typical syntax highlighting library.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* code, implemented using any typical syntax highlighting library.
|
|
5
|
+
*
|
|
6
|
+
* License of whole library for bundlers:
|
|
7
|
+
*
|
|
8
|
+
* Copyright 2021-2025 Oliver Geer and contributors
|
|
9
|
+
* @license MIT
|
|
10
|
+
*
|
|
11
|
+
* **<https://code-input-js.org>**
|
|
7
12
|
*/
|
|
13
|
+
"use strict";
|
|
8
14
|
|
|
9
15
|
|
|
10
16
|
var codeInput = {
|
|
@@ -64,7 +70,11 @@ var codeInput = {
|
|
|
64
70
|
"change",
|
|
65
71
|
"selectionchange",
|
|
66
72
|
"invalid",
|
|
67
|
-
"input"
|
|
73
|
+
"input",
|
|
74
|
+
"focus",
|
|
75
|
+
"blur",
|
|
76
|
+
"focusin",
|
|
77
|
+
"focusout"
|
|
68
78
|
],
|
|
69
79
|
|
|
70
80
|
/* ------------------------------------
|
|
@@ -121,13 +131,12 @@ var codeInput = {
|
|
|
121
131
|
// Add waiting code-input elements wanting this template from queue
|
|
122
132
|
if (templateName in codeInput.templateNotYetRegisteredQueue) {
|
|
123
133
|
for (let i in codeInput.templateNotYetRegisteredQueue[templateName]) {
|
|
124
|
-
elem = codeInput.templateNotYetRegisteredQueue[templateName][i];
|
|
125
|
-
elem.
|
|
126
|
-
|
|
134
|
+
const elem = codeInput.templateNotYetRegisteredQueue[templateName][i];
|
|
135
|
+
elem.templateObject = template;
|
|
136
|
+
elem.connectedCallback();
|
|
127
137
|
// Bind sets elem as first parameter of function
|
|
128
138
|
// So innerHTML can be read
|
|
129
139
|
}
|
|
130
|
-
console.log(`code-input: template: Added existing elements with template ${templateName}`);
|
|
131
140
|
}
|
|
132
141
|
|
|
133
142
|
if (codeInput.defaultTemplate == undefined) {
|
|
@@ -135,16 +144,14 @@ var codeInput = {
|
|
|
135
144
|
// Add elements with default template from queue
|
|
136
145
|
if (undefined in codeInput.templateNotYetRegisteredQueue) {
|
|
137
146
|
for (let i in codeInput.templateNotYetRegisteredQueue[undefined]) {
|
|
138
|
-
elem = codeInput.templateNotYetRegisteredQueue[undefined][i];
|
|
139
|
-
elem.
|
|
140
|
-
|
|
147
|
+
const elem = codeInput.templateNotYetRegisteredQueue[undefined][i];
|
|
148
|
+
elem.templateObject = template;
|
|
149
|
+
elem.connectedCallback();
|
|
141
150
|
// Bind sets elem as first parameter of function
|
|
142
151
|
// So innerHTML can be read
|
|
143
152
|
}
|
|
144
153
|
}
|
|
145
|
-
console.log(`code-input: template: Set template ${templateName} as default`);
|
|
146
154
|
}
|
|
147
|
-
console.log(`code-input: template: Created template ${templateName}`);
|
|
148
155
|
},
|
|
149
156
|
|
|
150
157
|
/**
|
|
@@ -159,7 +166,7 @@ var codeInput = {
|
|
|
159
166
|
* Constructor to create a custom template instance. Pass this into `codeInput.registerTemplate` to use it.
|
|
160
167
|
* I would strongly recommend using the built-in simpler template `codeInput.templates.prism` or `codeInput.templates.hljs`.
|
|
161
168
|
* @param {(codeElement: HTMLCodeElement, codeInput?: codeInput.CodeInput) => void} highlight - a callback to highlight the code, that takes an HTML `<code>` element inside a `<pre>` element as a parameter
|
|
162
|
-
* @param {boolean} preElementStyled - is the `<pre>` element CSS-styled
|
|
169
|
+
* @param {boolean} preElementStyled - is the `<pre>` element CSS-styled (if so set to true), or the `<code>` element (false)?
|
|
163
170
|
* @param {boolean} isCode - is this for writing code? If true, the code-input's lang HTML attribute can be used, and the `<code>` element will be given the class name 'language-[lang attribute's value]'.
|
|
164
171
|
* @param {boolean} includeCodeInputInHighlightFunc - Setting this to true passes the `<code-input>` element as a second argument to the highlight function.
|
|
165
172
|
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.Plugin`
|
|
@@ -209,6 +216,7 @@ var codeInput = {
|
|
|
209
216
|
plugins = [];
|
|
210
217
|
},
|
|
211
218
|
|
|
219
|
+
// ESM-SUPPORT-START-TEMPLATES-BLOCK-1 Do not (re)move this - it's needed for ESM generation!
|
|
212
220
|
/**
|
|
213
221
|
* For creating a custom template from scratch, please
|
|
214
222
|
* use `new codeInput.Template(...)`
|
|
@@ -222,38 +230,19 @@ var codeInput = {
|
|
|
222
230
|
* For adding small pieces of functionality, please see `codeInput.plugins`.
|
|
223
231
|
*/
|
|
224
232
|
templates: {
|
|
233
|
+
// (Source code for class templates after var codeInput = ... so they can extend the codeInput.Template class)
|
|
225
234
|
/**
|
|
226
|
-
*
|
|
227
|
-
* @param {Object} prism Import Prism.js, then after that import pass the `Prism` object as this parameter.
|
|
228
|
-
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
|
|
229
|
-
* @returns {codeInput.Template} template object
|
|
235
|
+
* @deprecated Please use `new codeInput.templates.Prism(...)`
|
|
230
236
|
*/
|
|
231
237
|
prism(prism, plugins = []) { // Dependency: Prism.js (https://prismjs.com/)
|
|
232
|
-
return new codeInput.
|
|
233
|
-
prism.highlightElement, // highlight
|
|
234
|
-
true, // preElementStyled
|
|
235
|
-
true, // isCode
|
|
236
|
-
false, // includeCodeInputInHighlightFunc
|
|
237
|
-
plugins
|
|
238
|
-
);
|
|
238
|
+
return new codeInput.templates.Prism(prism, plugins);
|
|
239
239
|
},
|
|
240
|
+
|
|
240
241
|
/**
|
|
241
|
-
*
|
|
242
|
-
* @param {Object} hljs Import highlight.js, then after that import pass the `hljs` object as this parameter.
|
|
243
|
-
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
|
|
244
|
-
* @returns {codeInput.Template} template object
|
|
242
|
+
* @deprecated Please use `new codeInput.templates.Hljs(...)`
|
|
245
243
|
*/
|
|
246
244
|
hljs(hljs, plugins = []) { // Dependency: Highlight.js (https://highlightjs.org/)
|
|
247
|
-
return new codeInput.
|
|
248
|
-
function(codeElement) {
|
|
249
|
-
codeElement.removeAttribute("data-highlighted");
|
|
250
|
-
hljs.highlightElement(codeElement);
|
|
251
|
-
}, // highlight
|
|
252
|
-
false, // preElementStyled
|
|
253
|
-
true, // isCode
|
|
254
|
-
false, // includeCodeInputInHighlightFunc
|
|
255
|
-
plugins
|
|
256
|
-
);
|
|
245
|
+
return new codeInput.templates.Hljs(hljs, plugins);
|
|
257
246
|
},
|
|
258
247
|
|
|
259
248
|
/**
|
|
@@ -318,7 +307,7 @@ var codeInput = {
|
|
|
318
307
|
},
|
|
319
308
|
|
|
320
309
|
/**
|
|
321
|
-
* @deprecated Please use `new codeInput.Template()`
|
|
310
|
+
* @deprecated Please use `new codeInput.Template(...)`
|
|
322
311
|
*/
|
|
323
312
|
custom(highlight = function () { }, preElementStyled = true, isCode = true, includeCodeInputInHighlightFunc = false, plugins = []) {
|
|
324
313
|
return {
|
|
@@ -330,6 +319,7 @@ var codeInput = {
|
|
|
330
319
|
};
|
|
331
320
|
},
|
|
332
321
|
},
|
|
322
|
+
// ESM-SUPPORT-END-TEMPLATES-BLOCK-1 Do not (re)move this - it's needed for ESM generation!
|
|
333
323
|
|
|
334
324
|
/* ------------------------------------
|
|
335
325
|
* ------------Plugins-----------------
|
|
@@ -370,7 +360,6 @@ var codeInput = {
|
|
|
370
360
|
* modifications to the `codeInput.Plugin.attributeChanged` method.
|
|
371
361
|
*/
|
|
372
362
|
constructor(observedAttributes) {
|
|
373
|
-
console.log("code-input: plugin: Created plugin");
|
|
374
363
|
|
|
375
364
|
observedAttributes.forEach((attribute) => {
|
|
376
365
|
codeInput.observedAttributes.push(attribute);
|
|
@@ -378,9 +367,9 @@ var codeInput = {
|
|
|
378
367
|
}
|
|
379
368
|
|
|
380
369
|
/**
|
|
381
|
-
* Replace the
|
|
370
|
+
* Replace the values in destination with those from source where the keys match, in-place.
|
|
382
371
|
* @param {Object} destination Where to place the translated strings, already filled with the keys pointing to English strings.
|
|
383
|
-
* @param {Object} source The same keys, or some of them, mapped to translated strings.
|
|
372
|
+
* @param {Object} source The same keys, or some of them, mapped to translated strings. Keys not present here will retain the values they are maapped to in destination.
|
|
384
373
|
*/
|
|
385
374
|
addTranslations(destination, source) {
|
|
386
375
|
for(const key in source) {
|
|
@@ -423,13 +412,20 @@ var codeInput = {
|
|
|
423
412
|
* ------------------------------------ */
|
|
424
413
|
|
|
425
414
|
/**
|
|
426
|
-
* A code-input element
|
|
415
|
+
* A `<code-input>` element, an instance of an `HTMLElement`, and the result
|
|
416
|
+
* of `document.createElement("code-input")`. Attributes are only set when
|
|
417
|
+
* the element's template has been registered, and before this are null.
|
|
427
418
|
*/
|
|
428
419
|
CodeInput: class extends HTMLElement {
|
|
429
420
|
constructor() {
|
|
430
421
|
super(); // Element
|
|
431
422
|
}
|
|
432
423
|
|
|
424
|
+
/**
|
|
425
|
+
* When the code-input's template is registered, this contains its codeInput.Template object.
|
|
426
|
+
* Should be treated as read-only by external code.
|
|
427
|
+
*/
|
|
428
|
+
templateObject = null;
|
|
433
429
|
/**
|
|
434
430
|
* Exposed child textarea element for user to input code in
|
|
435
431
|
*/
|
|
@@ -446,8 +442,8 @@ var codeInput = {
|
|
|
446
442
|
codeElement = null;
|
|
447
443
|
|
|
448
444
|
/**
|
|
449
|
-
* Exposed non-scrolling element designed to contain dialog boxes etc.
|
|
450
|
-
* with the code-input element.
|
|
445
|
+
* Exposed non-scrolling element designed to contain dialog boxes etc. from plugins,
|
|
446
|
+
* that shouldn't scroll with the code-input element.
|
|
451
447
|
*/
|
|
452
448
|
dialogContainerElement = null;
|
|
453
449
|
|
|
@@ -472,8 +468,8 @@ var codeInput = {
|
|
|
472
468
|
* @param {Array} args - the arguments to pass into the event callback in the template after the code-input element. Normally left empty
|
|
473
469
|
*/
|
|
474
470
|
pluginEvt(eventName, args) {
|
|
475
|
-
for (let i in this.
|
|
476
|
-
let plugin = this.
|
|
471
|
+
for (let i in this.templateObject.plugins) {
|
|
472
|
+
let plugin = this.templateObject.plugins[i];
|
|
477
473
|
if (eventName in plugin) {
|
|
478
474
|
if (args === undefined) {
|
|
479
475
|
plugin[eventName](this);
|
|
@@ -493,7 +489,6 @@ var codeInput = {
|
|
|
493
489
|
* to syntax-highlight it. */
|
|
494
490
|
|
|
495
491
|
needsHighlight = false; // Just inputted
|
|
496
|
-
handleEventsFromTextarea = true; // Turn to false when unusual internal events are called on the textarea
|
|
497
492
|
originalAriaDescription;
|
|
498
493
|
|
|
499
494
|
/**
|
|
@@ -529,19 +524,11 @@ var codeInput = {
|
|
|
529
524
|
this.pluginEvt("beforeHighlight");
|
|
530
525
|
|
|
531
526
|
// Syntax Highlight
|
|
532
|
-
if (this.
|
|
533
|
-
else this.
|
|
527
|
+
if (this.templateObject.includeCodeInputInHighlightFunc) this.templateObject.highlight(resultElement, this);
|
|
528
|
+
else this.templateObject.highlight(resultElement);
|
|
534
529
|
|
|
535
530
|
this.syncSize();
|
|
536
531
|
|
|
537
|
-
// If editing here, scroll to the caret by focusing, though this shouldn't count as a focus event
|
|
538
|
-
if(this.textareaElement === document.activeElement) {
|
|
539
|
-
this.handleEventsFromTextarea = false;
|
|
540
|
-
this.textareaElement.blur();
|
|
541
|
-
this.textareaElement.focus();
|
|
542
|
-
this.handleEventsFromTextarea = true;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
532
|
this.pluginEvt("afterHighlight");
|
|
546
533
|
}
|
|
547
534
|
|
|
@@ -550,7 +537,7 @@ var codeInput = {
|
|
|
550
537
|
*/
|
|
551
538
|
syncSize() {
|
|
552
539
|
// Synchronise the size of the pre/code and textarea elements
|
|
553
|
-
if(this.
|
|
540
|
+
if(this.templateObject.preElementStyled) {
|
|
554
541
|
this.style.backgroundColor = getComputedStyle(this.preElement).backgroundColor;
|
|
555
542
|
this.textareaElement.style.height = getComputedStyle(this.preElement).height;
|
|
556
543
|
this.textareaElement.style.width = getComputedStyle(this.preElement).width;
|
|
@@ -624,21 +611,45 @@ var codeInput = {
|
|
|
624
611
|
setup() {
|
|
625
612
|
if(this.textareaElement != null) return; // Already set up
|
|
626
613
|
|
|
614
|
+
this.mutationObserver = new MutationObserver(this.mutationObserverCallback.bind(this));
|
|
615
|
+
this.mutationObserver.observe(this, {
|
|
616
|
+
attributes: true,
|
|
617
|
+
attributeOldValue: true
|
|
618
|
+
});
|
|
619
|
+
|
|
627
620
|
this.classList.add("code-input_registered"); // Remove register message
|
|
628
|
-
if (this.
|
|
621
|
+
if (this.templateObject.preElementStyled) this.classList.add("code-input_pre-element-styled");
|
|
629
622
|
|
|
630
623
|
this.pluginEvt("beforeElementsAdded");
|
|
631
624
|
|
|
625
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
626
|
+
let value;
|
|
627
|
+
if(fallbackTextarea) {
|
|
628
|
+
// Fallback textarea exists
|
|
629
|
+
// Sync attributes; existing code-input attributes take priority
|
|
630
|
+
let textareaAttributeNames = fallbackTextarea.getAttributeNames();
|
|
631
|
+
for(let i = 0; i < textareaAttributeNames.length; i++) {
|
|
632
|
+
const attr = textareaAttributeNames[i];
|
|
633
|
+
if(!this.hasAttribute(attr)) {
|
|
634
|
+
this.setAttribute(attr, fallbackTextarea.getAttribute(attr));
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
// Sync value
|
|
638
|
+
value = fallbackTextarea.value;
|
|
639
|
+
} else {
|
|
640
|
+
value = this.unescapeHtml(this.innerHTML);
|
|
641
|
+
}
|
|
642
|
+
value = value || this.getAttribute("value") || "";
|
|
643
|
+
|
|
632
644
|
// First-time attribute sync
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
// Value attribute deprecated, but included for compatibility
|
|
645
|
+
const lang = this.getAttribute("language") || this.getAttribute("lang");
|
|
646
|
+
const placeholder = this.getAttribute("placeholder") || lang || "";
|
|
647
|
+
|
|
637
648
|
|
|
638
649
|
this.initialValue = value; // For form reset
|
|
639
650
|
|
|
640
651
|
// Create textarea
|
|
641
|
-
|
|
652
|
+
const textarea = document.createElement("textarea");
|
|
642
653
|
textarea.placeholder = placeholder;
|
|
643
654
|
if(value != "") {
|
|
644
655
|
textarea.value = value;
|
|
@@ -657,9 +668,7 @@ var codeInput = {
|
|
|
657
668
|
this.classList.add("code-input_mouse-focused");
|
|
658
669
|
});
|
|
659
670
|
textarea.addEventListener("blur", () => {
|
|
660
|
-
|
|
661
|
-
this.classList.remove("code-input_mouse-focused");
|
|
662
|
-
}
|
|
671
|
+
this.classList.remove("code-input_mouse-focused");
|
|
663
672
|
});
|
|
664
673
|
|
|
665
674
|
this.innerHTML = ""; // Clear Content
|
|
@@ -691,7 +700,7 @@ var codeInput = {
|
|
|
691
700
|
pre.append(code);
|
|
692
701
|
this.append(pre);
|
|
693
702
|
|
|
694
|
-
if (this.
|
|
703
|
+
if (this.templateObject.isCode) {
|
|
695
704
|
if (lang != undefined && lang != "") {
|
|
696
705
|
code.classList.add("language-" + lang.toLowerCase());
|
|
697
706
|
}
|
|
@@ -722,19 +731,34 @@ var codeInput = {
|
|
|
722
731
|
}
|
|
723
732
|
|
|
724
733
|
/**
|
|
725
|
-
* @deprecated
|
|
734
|
+
* @deprecated This shouldn't have been accessed as part of the library's public interface (to enable more flexibility in backwards-compatible versions), but is still here just in case it was.
|
|
726
735
|
*/
|
|
727
736
|
escape_html(text) {
|
|
728
737
|
return this.escapeHtml(text);
|
|
729
738
|
}
|
|
730
739
|
|
|
731
740
|
/**
|
|
732
|
-
* @deprecated
|
|
741
|
+
* @deprecated This shouldn't have been accessed as part of the library's public interface (to enable more flexibility in backwards-compatible versions), but is still here just in case it was.
|
|
733
742
|
*/
|
|
734
743
|
get_template() {
|
|
735
744
|
return this.getTemplate();
|
|
736
745
|
}
|
|
737
746
|
|
|
747
|
+
/**
|
|
748
|
+
* @deprecated Present for backwards compatibility; use CodeInput.templateObject.
|
|
749
|
+
*/
|
|
750
|
+
get template() {
|
|
751
|
+
return this.templateObject;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* @deprecated The Vue framework may try to set the template
|
|
756
|
+
* property to the value of the template attribute, a string.
|
|
757
|
+
* This should not happen. Intentional use of this should
|
|
758
|
+
* also not happen since templates are changed by changing
|
|
759
|
+
* the template attribute to the name of one registered.
|
|
760
|
+
*/
|
|
761
|
+
set template(value) { }
|
|
738
762
|
|
|
739
763
|
/* ------------------------------------
|
|
740
764
|
* -----------Callbacks----------------
|
|
@@ -747,19 +771,14 @@ var codeInput = {
|
|
|
747
771
|
* find its template and set up the element.
|
|
748
772
|
*/
|
|
749
773
|
connectedCallback() {
|
|
750
|
-
|
|
751
|
-
|
|
774
|
+
// Stored in templateObject because some frameworks will override
|
|
775
|
+
// template property with the string value of the attribute
|
|
776
|
+
this.templateObject = this.getTemplate();
|
|
777
|
+
if (this.templateObject != undefined) {
|
|
752
778
|
this.classList.add("code-input_registered");
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
}, this);
|
|
757
|
-
}
|
|
758
|
-
this.mutationObserver = new MutationObserver(this.mutationObserverCallback.bind(this));
|
|
759
|
-
this.mutationObserver.observe(this, {
|
|
760
|
-
attributes: true,
|
|
761
|
-
attributeOldValue: true
|
|
762
|
-
});
|
|
779
|
+
this.setup();
|
|
780
|
+
this.classList.add("code-input_loaded");
|
|
781
|
+
}
|
|
763
782
|
}
|
|
764
783
|
|
|
765
784
|
mutationObserverCallback(mutationList, observer) {
|
|
@@ -799,8 +818,8 @@ var codeInput = {
|
|
|
799
818
|
this.value = newValue;
|
|
800
819
|
break;
|
|
801
820
|
case "template":
|
|
802
|
-
this.
|
|
803
|
-
if (this.
|
|
821
|
+
this.templateObject = codeInput.usedTemplates[newValue || codeInput.defaultTemplate];
|
|
822
|
+
if (this.templateObject.preElementStyled) this.classList.add("code-input_pre-element-styled");
|
|
804
823
|
else this.classList.remove("code-input_pre-element-styled");
|
|
805
824
|
// Syntax Highlight
|
|
806
825
|
this.scheduleHighlight();
|
|
@@ -885,22 +904,20 @@ var codeInput = {
|
|
|
885
904
|
this.boundEventCallbacks[listener] = boundCallback;
|
|
886
905
|
|
|
887
906
|
if (codeInput.textareaSyncEvents.includes(type)) {
|
|
888
|
-
// Synchronise with textarea
|
|
889
|
-
|
|
890
|
-
let conditionalBoundCallback = function(evt) { if(this.handleEventsFromTextarea) boundCallback(evt); }.bind(this);
|
|
891
|
-
this.boundEventCallbacks[listener] = conditionalBoundCallback;
|
|
907
|
+
// Synchronise with textarea
|
|
908
|
+
this.boundEventCallbacks[listener] = boundCallback;
|
|
892
909
|
|
|
893
910
|
if (options === undefined) {
|
|
894
911
|
if(this.textareaElement == null) {
|
|
895
912
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback); });
|
|
896
913
|
} else {
|
|
897
|
-
this.textareaElement.addEventListener(type,
|
|
914
|
+
this.textareaElement.addEventListener(type, boundCallback);
|
|
898
915
|
}
|
|
899
916
|
} else {
|
|
900
917
|
if(this.textareaElement == null) {
|
|
901
918
|
this.addEventListener("code-input_load", () => { this.textareaElement.addEventListener(type, boundCallback, options); });
|
|
902
919
|
} else {
|
|
903
|
-
this.textareaElement.addEventListener(type,
|
|
920
|
+
this.textareaElement.addEventListener(type, boundCallback, options);
|
|
904
921
|
}
|
|
905
922
|
}
|
|
906
923
|
} else {
|
|
@@ -949,8 +966,18 @@ var codeInput = {
|
|
|
949
966
|
* Get the text contents of the code-input element.
|
|
950
967
|
*/
|
|
951
968
|
get value() {
|
|
952
|
-
|
|
953
|
-
|
|
969
|
+
if(this.textareaElement) {
|
|
970
|
+
// Get from editable textarea element
|
|
971
|
+
return this.textareaElement.value;
|
|
972
|
+
} else {
|
|
973
|
+
// Unregistered
|
|
974
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
975
|
+
if(fallbackTextarea) {
|
|
976
|
+
return fallbackTextarea.value;
|
|
977
|
+
} else {
|
|
978
|
+
return this.innerHTML;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
954
981
|
}
|
|
955
982
|
/**
|
|
956
983
|
* Set the text contents of the code-input element.
|
|
@@ -960,11 +987,28 @@ var codeInput = {
|
|
|
960
987
|
if (val === null || val === undefined) {
|
|
961
988
|
val = "";
|
|
962
989
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
990
|
+
if(this.textareaElement) {
|
|
991
|
+
// Save in editable textarea element
|
|
992
|
+
this.textareaElement.value = val;
|
|
993
|
+
// Trigger highlight
|
|
994
|
+
this.scheduleHighlight();
|
|
995
|
+
} else {
|
|
996
|
+
// Unregistered
|
|
997
|
+
const fallbackTextarea = this.querySelector("textarea[data-code-input-fallback]");
|
|
998
|
+
if(fallbackTextarea) {
|
|
999
|
+
fallbackTextarea.value = val;
|
|
1000
|
+
} else {
|
|
1001
|
+
this.innerHTML = val;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
// Synchronise blur and focus
|
|
1007
|
+
focus(options={}) {
|
|
1008
|
+
return this.textareaElement.focus(options);
|
|
1009
|
+
}
|
|
1010
|
+
blur(options={}) {
|
|
1011
|
+
return this.textareaElement.blur(options);
|
|
968
1012
|
}
|
|
969
1013
|
|
|
970
1014
|
/**
|
|
@@ -1032,7 +1076,7 @@ var codeInput = {
|
|
|
1032
1076
|
|
|
1033
1077
|
/**
|
|
1034
1078
|
* Allows plugins to store data in the scope of a single element.
|
|
1035
|
-
* Key - name of the plugin
|
|
1079
|
+
* Key - name of the plugin, in camelCase
|
|
1036
1080
|
* Value - object of data to be stored; different plugins may use this differently.
|
|
1037
1081
|
*/
|
|
1038
1082
|
pluginData = {};
|
|
@@ -1043,19 +1087,66 @@ var codeInput = {
|
|
|
1043
1087
|
formResetCallback() {
|
|
1044
1088
|
this.value = this.initialValue;
|
|
1045
1089
|
};
|
|
1046
|
-
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1047
1092
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1093
|
+
// ESM-SUPPORT-START-TEMPLATES-BLOCK-2 Do not (re)move this - it's needed for ESM generation!
|
|
1094
|
+
{
|
|
1095
|
+
// Templates are defined here after the codeInput variable is set, because they reference it by extending codeInput.Template.
|
|
1096
|
+
|
|
1097
|
+
// ESM-SUPPORT-START-TEMPLATE-prism Do not (re)move this - it's needed for ESM generation!
|
|
1098
|
+
/**
|
|
1099
|
+
* A template that uses Prism.js syntax highlighting (https://prismjs.com/).
|
|
1100
|
+
*/
|
|
1101
|
+
class Prism extends codeInput.Template { // Dependency: Prism.js (https://prismjs.com/)
|
|
1102
|
+
/**
|
|
1103
|
+
* Constructor to create a template that uses Prism.js syntax highlighting (https://prismjs.com/)
|
|
1104
|
+
* @param {Object} prism Import Prism.js, then after that import pass the `Prism` object as this parameter.
|
|
1105
|
+
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
|
|
1106
|
+
* @param {boolean} preElementStyled - Defaults to true, which should be right for most themes. If the styling is broken, change to false. (See `codeInput.Template` constructor's definition.)
|
|
1107
|
+
* @returns {codeInput.Template} template object
|
|
1108
|
+
*/
|
|
1109
|
+
constructor(prism, plugins = [], preElementStyled = true) {
|
|
1110
|
+
super(
|
|
1111
|
+
prism.highlightElement, // highlight
|
|
1112
|
+
preElementStyled, // preElementStyled
|
|
1113
|
+
true, // isCode
|
|
1114
|
+
false, // includeCodeInputInHighlightFunc
|
|
1115
|
+
plugins
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
// ESM-SUPPORT-END-TEMPLATE-prism Do not (re)move this - it's needed for ESM generation!
|
|
1120
|
+
codeInput.templates.Prism = Prism;
|
|
1121
|
+
|
|
1122
|
+
// ESM-SUPPORT-START-TEMPLATE-hljs Do not (re)move this - it's needed for ESM generation!
|
|
1123
|
+
/**
|
|
1124
|
+
* A template that uses highlight.js syntax highlighting (https://highlightjs.org/).
|
|
1051
1125
|
*/
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1126
|
+
class Hljs extends codeInput.Template { // Dependency: Highlight.js (https://highlightjs.org/)
|
|
1127
|
+
/**
|
|
1128
|
+
* Constructor to create a template that uses highlight.js syntax highlighting (https://highlightjs.org/)
|
|
1129
|
+
* @param {Object} hljs Import highlight.js, then after that import pass the `hljs` object as this parameter.
|
|
1130
|
+
* @param {codeInput.Plugin[]} plugins - An array of plugin objects to add extra features - see `codeInput.plugins`
|
|
1131
|
+
* @param {boolean} preElementStyled - Defaults to false, which should be right for most themes. If the styling is broken, change to true. (See `codeInput.Template` constructor's definition.)
|
|
1132
|
+
* @returns {codeInput.Template} template object
|
|
1133
|
+
*/
|
|
1134
|
+
constructor(hljs, plugins = [], preElementStyled = false) {
|
|
1135
|
+
super(
|
|
1136
|
+
function(codeElement) {
|
|
1137
|
+
codeElement.removeAttribute("data-highlighted");
|
|
1138
|
+
hljs.highlightElement(codeElement);
|
|
1139
|
+
}, // highlight
|
|
1140
|
+
preElementStyled, // preElementStyled
|
|
1141
|
+
true, // isCode
|
|
1142
|
+
false, // includeCodeInputInHighlightFunc
|
|
1143
|
+
plugins
|
|
1144
|
+
);
|
|
1057
1145
|
}
|
|
1058
|
-
}
|
|
1146
|
+
};
|
|
1147
|
+
// ESM-SUPPORT-END-TEMPLATE-hljs Do not (re)move this - it's needed for ESM generation!
|
|
1148
|
+
codeInput.templates.Hljs = Hljs;
|
|
1059
1149
|
}
|
|
1150
|
+
// ESM-SUPPORT-END-TEMPLATES-BLOCK-2 Do not (re)move this - it's needed for ESM generation!
|
|
1060
1151
|
|
|
1061
1152
|
customElements.define("code-input", codeInput.CodeInput);
|
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;margin:8px;--padding:16px;height:250px;font-size:inherit;font-family:monospace;line-height:1.5;tab-size:2;caret-color:#a9a9a9;white-space:pre;padding:0!important;display:grid;grid-template-columns:100%;grid-template-rows:100%}code-input:not(.code-input_loaded){padding:var(--padding,16px)!important}code-input textarea,code-input.code-input_pre-element-styled pre,code-input:not(.code-input_pre-element-styled) pre code{margin:0!important;padding:var(--padding,16px)!important;border:0;min-width:calc(100% - var(--padding) * 2);min-height:calc(100% - var(--padding) * 2);box-sizing:content-box;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;
|
|
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;line-height:1.5;tab-size:2;caret-color:#a9a9a9;white-space:pre;padding:0!important;display:grid;grid-template-columns:100%;grid-template-rows:100%}code-input:not(.code-input_loaded){padding:var(--padding,16px)!important}code-input textarea,code-input.code-input_pre-element-styled pre,code-input:not(.code-input_pre-element-styled) pre code{margin:0!important;padding:var(--padding,16px)!important;border:0;min-width:calc(100% - var(--padding,16px) * 2);min-height:calc(100% - var(--padding,16px) * 2);box-sizing:content-box;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:not(.code-input_registered){overflow:hidden;display:block;box-sizing:border-box}code-input:not(.code-input_registered)::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,16px);width:calc(100% - 2 * var(--padding,16px));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_registered) textarea{min-height:calc(100% - var(--padding,16px) * 2 - 2em)}code-input:not(.code-input_loaded) pre,code-input:not(.code-input_loaded) textarea:not([data-code-input-fallback]){opacity:0}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}code-input.code-input_pre-element-styled .code-input_dialog-container{width:calc(100% + 2 * var(--padding,16px))}[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;margin:0;text-wrap:balance;overflow:hidden;text-overflow:ellipsis;width:100%;box-sizing:border-box;max-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,16px) + 3em)!important}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{min-height:calc(100% - var(--padding,16px) * 2 - 3em)}code-input textarea[data-code-input-fallback]{overflow:auto;background-color:inherit;color:inherit;height:max-content}
|