@webcoder49/code-input 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +9 -126
- package/code-input.css +71 -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/.code-input.mjs.kate-swp +0 -0
- package/esm/README.md +23 -0
- package/esm/code-input.mjs +2 -0
- package/package.json +83 -7
- package/plugins/README.md +2 -0
- package/plugins/auto-close-brackets.js +25 -7
- 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 +34 -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 +43 -6
- package/plugins/go-to-line.min.css +1 -1
- package/plugins/go-to-line.min.js +1 -1
- package/plugins/indent.js +29 -4
- 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 -593
- package/tests/tester.min.js +0 -21
package/plugins/go-to-line.css
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
.code-input_go-to-line_dialog {
|
|
12
12
|
position: absolute;
|
|
13
13
|
top: 0; right: 14px;
|
|
14
|
-
height: 28px;
|
|
15
14
|
padding: 6px;
|
|
16
15
|
padding-top: 8px;
|
|
17
16
|
border: solid 1px #00000044;
|
|
@@ -48,10 +47,6 @@
|
|
|
48
47
|
color: #ff0000aa;
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
.code-input_go-to-line_dialog input:focus {
|
|
52
|
-
outline: none;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
50
|
/* Cancel icon */
|
|
56
51
|
.code-input_go-to-line_dialog span {
|
|
57
52
|
display: inline-block;
|
|
@@ -75,3 +70,13 @@
|
|
|
75
70
|
opacity: .8;
|
|
76
71
|
background-color: #00000018;
|
|
77
72
|
}
|
|
73
|
+
|
|
74
|
+
/* For backwards compatibility, p element on the same level as buttons rather than
|
|
75
|
+
buttons being nested inside other element like in FindAndReplace. */
|
|
76
|
+
.code-input_go-to-line_dialog p {
|
|
77
|
+
font-family: monospace;
|
|
78
|
+
width: 264px;
|
|
79
|
+
margin: 0;
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
white-space: wrap;
|
|
82
|
+
}
|
package/plugins/go-to-line.js
CHANGED
|
@@ -2,17 +2,24 @@
|
|
|
2
2
|
* Add basic Go-To-Line (Ctrl+G by default) functionality to the code editor.
|
|
3
3
|
* Files: go-to-line.js / go-to-line.css
|
|
4
4
|
*/
|
|
5
|
+
"use strict";
|
|
6
|
+
|
|
5
7
|
codeInput.plugins.GoToLine = class extends codeInput.Plugin {
|
|
6
8
|
useCtrlG = false;
|
|
7
9
|
|
|
8
10
|
instructions = {
|
|
9
11
|
closeDialog: "Close Dialog and Return to Editor",
|
|
10
12
|
input: "Line:Column / Line no. then Enter",
|
|
13
|
+
guidanceFormat: "Wrong format. Enter a line number (e.g. 1) or a line number then colon then column number (e.g. 1:3).",
|
|
14
|
+
guidanceLineRange: (current, max) => `Line number (currently ${current}) should be between 1 and ${max} inclusive.`,
|
|
15
|
+
guidanceColumnRange: (line, current, max) => `On line ${line}, column number (currently ${current}) should be between 1 and ${max} inclusive.`,
|
|
16
|
+
guidanceValidLine: (line) => `Press Enter to go to line ${line}.`,
|
|
17
|
+
guidanceValidColumn: (line, column) => `Press Enter to go to line ${line}, column ${column}.`,
|
|
11
18
|
};
|
|
12
19
|
|
|
13
20
|
/**
|
|
14
21
|
* Create a go-to-line command plugin to pass into a template
|
|
15
|
-
* @param {boolean} useCtrlG Should Ctrl+G be overriden for go-to-line functionality?
|
|
22
|
+
* @param {boolean} useCtrlG Should Ctrl+G be overriden for go-to-line functionality? Either way, you can trigger it yourself using (instance of this plugin)`.showPrompt(code-input element)`.
|
|
16
23
|
* @param {Object} instructionTranslations: user interface string keys mapped to translated versions for localisation. Look at the go-to-line.js source code for the available keys and English text.
|
|
17
24
|
*/
|
|
18
25
|
constructor(useCtrlG = true, instructionTranslations = {}) {
|
|
@@ -31,6 +38,8 @@ codeInput.plugins.GoToLine = class extends codeInput.Plugin {
|
|
|
31
38
|
|
|
32
39
|
/* Called with a dialog box keyup event to check the validity of the line number entered and submit the dialog if Enter is pressed */
|
|
33
40
|
checkPrompt(dialog, event) {
|
|
41
|
+
if (event.key == 'Escape') return this.cancelPrompt(dialog, event);
|
|
42
|
+
|
|
34
43
|
// Line number(:column number)
|
|
35
44
|
const lines = dialog.textarea.value.split('\n');
|
|
36
45
|
const maxLineNo = lines.length;
|
|
@@ -38,25 +47,42 @@ codeInput.plugins.GoToLine = class extends codeInput.Plugin {
|
|
|
38
47
|
let columnNo = 0; // Means go to start of indented line
|
|
39
48
|
let maxColumnNo = 1;
|
|
40
49
|
const querySplitByColons = dialog.input.value.split(':');
|
|
41
|
-
if(querySplitByColons.length > 2) return dialog.input.classList.add('code-input_go-to-line_error');
|
|
42
50
|
|
|
43
|
-
|
|
51
|
+
// Invalid format
|
|
52
|
+
if(querySplitByColons.length > 2 || !/^[0-9:]*$/.test(dialog.input.value)) {
|
|
53
|
+
dialog.guidance.textContent = this.instructions.guidanceFormat;
|
|
54
|
+
return dialog.input.classList.add('code-input_go-to-line_error');
|
|
55
|
+
}
|
|
44
56
|
|
|
57
|
+
// Number(s) present
|
|
45
58
|
if (dialog.input.value) {
|
|
46
|
-
if (
|
|
59
|
+
if (lineNo < 1 || lineNo > maxLineNo) {
|
|
60
|
+
// Out-of-range line number
|
|
61
|
+
dialog.guidance.textContent = this.instructions.guidanceLineRange(lineNo, maxLineNo);
|
|
47
62
|
return dialog.input.classList.add('code-input_go-to-line_error');
|
|
48
63
|
} else {
|
|
49
|
-
// Check if line:column
|
|
64
|
+
// Check if line:column - if so calculate column number
|
|
50
65
|
if(querySplitByColons.length >= 2) {
|
|
51
66
|
columnNo = Number(querySplitByColons[1]);
|
|
52
|
-
maxColumnNo = lines[lineNo-1].length;
|
|
67
|
+
maxColumnNo = lines[lineNo-1].length+1; // column 1 always works since at start of line
|
|
53
68
|
}
|
|
54
69
|
if(columnNo < 0 || columnNo > maxColumnNo) {
|
|
70
|
+
dialog.guidance.textContent = this.instructions.guidanceColumnRange(lineNo, columnNo, maxColumnNo);
|
|
55
71
|
return dialog.input.classList.add('code-input_go-to-line_error');
|
|
56
72
|
} else {
|
|
73
|
+
if(columnNo === 0) {
|
|
74
|
+
// No column specified, or 0 which for backwards compatibility acts
|
|
75
|
+
// like none selected
|
|
76
|
+
dialog.guidance.textContent = this.instructions.guidanceValidLine(lineNo);
|
|
77
|
+
} else {
|
|
78
|
+
dialog.guidance.textContent = this.instructions.guidanceValidColumn(lineNo, columnNo);
|
|
79
|
+
}
|
|
57
80
|
dialog.input.classList.remove('code-input_go-to-line_error');
|
|
58
81
|
}
|
|
59
82
|
}
|
|
83
|
+
} else {
|
|
84
|
+
// No value
|
|
85
|
+
dialog.guidance.textContent = "";
|
|
60
86
|
}
|
|
61
87
|
|
|
62
88
|
if (event.key == 'Enter') {
|
|
@@ -89,13 +115,23 @@ codeInput.plugins.GoToLine = class extends codeInput.Plugin {
|
|
|
89
115
|
const textarea = codeInput.textareaElement;
|
|
90
116
|
|
|
91
117
|
const dialog = document.createElement('div');
|
|
118
|
+
|
|
92
119
|
const input = document.createElement('input');
|
|
120
|
+
|
|
121
|
+
// TODO: Make a button element (semantic HTML for accessibility) in next major version
|
|
93
122
|
const cancel = document.createElement('span');
|
|
123
|
+
cancel.setAttribute("role", "button");
|
|
124
|
+
cancel.setAttribute("aria-label", this.instructions.closeDialog);
|
|
94
125
|
cancel.setAttribute("tabindex", 0); // Visible to keyboard navigation
|
|
95
126
|
cancel.setAttribute("title", this.instructions.closeDialog);
|
|
96
127
|
|
|
128
|
+
const guidance = document.createElement('p');
|
|
129
|
+
guidance.setAttribute("aria-live", "assertive"); // Screen reader must read the status message.
|
|
130
|
+
guidance.textContent = "";
|
|
131
|
+
|
|
97
132
|
dialog.appendChild(input);
|
|
98
133
|
dialog.appendChild(cancel);
|
|
134
|
+
dialog.appendChild(guidance);
|
|
99
135
|
|
|
100
136
|
dialog.className = 'code-input_go-to-line_dialog';
|
|
101
137
|
input.spellcheck = false;
|
|
@@ -103,6 +139,7 @@ codeInput.plugins.GoToLine = class extends codeInput.Plugin {
|
|
|
103
139
|
dialog.codeInput = codeInput;
|
|
104
140
|
dialog.textarea = textarea;
|
|
105
141
|
dialog.input = input;
|
|
142
|
+
dialog.guidance = guidance;
|
|
106
143
|
|
|
107
144
|
input.addEventListener('keypress', (event) => {
|
|
108
145
|
/* Stop enter from submitting form */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@keyframes code-input_go-to-line_roll-in{0%{opacity:0;transform:translateY(-34px)}100%{opacity:1;transform:translateY(0)}}@keyframes code-input_go-to-line_roll-out{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(-34px)}}.code-input_go-to-line_dialog{position:absolute;top:0;right:14px;
|
|
1
|
+
@keyframes code-input_go-to-line_roll-in{0%{opacity:0;transform:translateY(-34px)}100%{opacity:1;transform:translateY(0)}}@keyframes code-input_go-to-line_roll-out{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(-34px)}}.code-input_go-to-line_dialog{position:absolute;top:0;right:14px;padding:6px;padding-top:8px;border:solid 1px #00000044;background-color:#fff;border-radius:6px;box-shadow:0 .2em 1em .2em rgba(0,0,0,.16)}.code-input_go-to-line_dialog:not(.code-input_go-to-line_hidden-dialog){animation:code-input_go-to-line_roll-in .2s;opacity:1;pointer-events:all}.code-input_go-to-line_dialog.code-input_go-to-line_hidden-dialog{animation:code-input_go-to-line_roll-out .2s;opacity:0;pointer-events:none}.code-input_go-to-line_dialog input::placeholder{font-size:80%}.code-input_go-to-line_dialog input{position:relative;width:240px;height:32px;top:-3px;font-size:large;color:#000000aa;border:0}.code-input_go-to-line_dialog input.code-input_go-to-line_error{color:#ff0000aa}.code-input_go-to-line_dialog span{display:inline-block;width:24px;line-height:24px;font-family:system-ui;font-size:22px;font-weight:500;text-align:center;border-radius:50%;color:#000;opacity:.6;vertical-align:top}.code-input_go-to-line_dialog span:before{content:"\00d7"}.code-input_go-to-line_dialog span:hover{opacity:.8;background-color:#00000018}.code-input_go-to-line_dialog p{font-family:monospace;width:264px;margin:0;overflow:hidden;white-space:wrap}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
codeInput.plugins.GoToLine=class extends codeInput.Plugin{useCtrlG=!1;instructions={closeDialog:"Close Dialog and Return to Editor",input:"Line:Column / Line no. then Enter"};constructor(a=!0,b={}){super([]),this.useCtrlG=a,this.addTranslations(this.instructions,b)}afterElementsAdded(a){const b=a.textareaElement;this.useCtrlG&&b.addEventListener("keydown",b=>{this.checkCtrlG(a,b)})}checkPrompt(a,b){const c=a.textarea.value.split("\n"),d=c.length,e=+a.input.value.split(":")[0];let f=0,g=1;const h=a.input.value.split(":");if(2<h.length)return a.input.classList.add("code-input_go-to-line_error");if(
|
|
1
|
+
"use strict";codeInput.plugins.GoToLine=class extends codeInput.Plugin{useCtrlG=!1;instructions={closeDialog:"Close Dialog and Return to Editor",input:"Line:Column / Line no. then Enter",guidanceFormat:"Wrong format. Enter a line number (e.g. 1) or a line number then colon then column number (e.g. 1:3).",guidanceLineRange:(a,b)=>`Line number (currently ${a}) should be between 1 and ${b} inclusive.`,guidanceColumnRange:(a,b,c)=>`On line ${a}, column number (currently ${b}) should be between 1 and ${c} inclusive.`,guidanceValidLine:a=>`Press Enter to go to line ${a}.`,guidanceValidColumn:(a,b)=>`Press Enter to go to line ${a}, column ${b}.`};constructor(a=!0,b={}){super([]),this.useCtrlG=a,this.addTranslations(this.instructions,b)}afterElementsAdded(a){const b=a.textareaElement;this.useCtrlG&&b.addEventListener("keydown",b=>{this.checkCtrlG(a,b)})}checkPrompt(a,b){if("Escape"==b.key)return this.cancelPrompt(a,b);const c=a.textarea.value.split("\n"),d=c.length,e=+a.input.value.split(":")[0];let f=0,g=1;const h=a.input.value.split(":");if(2<h.length||!/^[0-9:]*$/.test(a.input.value))return a.guidance.textContent=this.instructions.guidanceFormat,a.input.classList.add("code-input_go-to-line_error");if(a.input.value){if(1>e||e>d)return a.guidance.textContent=this.instructions.guidanceLineRange(e,d),a.input.classList.add("code-input_go-to-line_error");if(2<=h.length&&(f=+h[1],g=c[e-1].length+1),0>f||f>g)return a.guidance.textContent=this.instructions.guidanceColumnRange(e,f,g),a.input.classList.add("code-input_go-to-line_error");a.guidance.textContent=0===f?this.instructions.guidanceValidLine(e):this.instructions.guidanceValidColumn(e,f),a.input.classList.remove("code-input_go-to-line_error")}else a.guidance.textContent="";"Enter"==b.key&&(this.goTo(a.textarea,e,f),this.cancelPrompt(a,b))}cancelPrompt(a,b){b.preventDefault(),a.codeInput.handleEventsFromTextarea=!1,a.textarea.focus(),a.codeInput.handleEventsFromTextarea=!0,a.setAttribute("inert",!0),a.setAttribute("tabindex",-1),a.setAttribute("aria-hidden",!0),a.classList.add("code-input_go-to-line_hidden-dialog"),a.input.value=""}showPrompt(a){if(a.pluginData.goToLine==null||a.pluginData.goToLine.dialog==null){const b=a.textareaElement,c=document.createElement("div"),d=document.createElement("input"),e=document.createElement("span");e.setAttribute("role","button"),e.setAttribute("aria-label",this.instructions.closeDialog),e.setAttribute("tabindex",0),e.setAttribute("title",this.instructions.closeDialog);const f=document.createElement("p");f.setAttribute("aria-live","assertive"),f.textContent="",c.appendChild(d),c.appendChild(e),c.appendChild(f),c.className="code-input_go-to-line_dialog",d.spellcheck=!1,d.placeholder=this.instructions.input,c.codeInput=a,c.textarea=b,c.input=d,c.guidance=f,d.addEventListener("keypress",a=>{"Enter"==a.key&&a.preventDefault()}),d.addEventListener("keyup",a=>this.checkPrompt(c,a)),e.addEventListener("click",a=>{this.cancelPrompt(c,a)}),e.addEventListener("keypress",a=>{("Space"==a.key||"Enter"==a.key)&&this.cancelPrompt(c,a)}),a.dialogContainerElement.appendChild(c),a.pluginData.goToLine={dialog:c},d.focus()}else a.pluginData.goToLine.dialog.classList.remove("code-input_go-to-line_hidden-dialog"),a.pluginData.goToLine.dialog.removeAttribute("inert"),a.pluginData.goToLine.dialog.setAttribute("tabindex",0),a.pluginData.goToLine.dialog.removeAttribute("aria-hidden"),a.pluginData.goToLine.dialog.input.focus()}goTo(a,b,c=0){let d,e,f,g,h=-1,i=a.value.split("\n");if(0<b&&b<=i.length){if(a.computedStyleMap?(d=a.computedStyleMap().get("font-size").value,e=d*a.computedStyleMap().get("line-height").value):(d=document.defaultView.getComputedStyle(a,null).getPropertyValue("font-size").split("px")[0],e=document.defaultView.getComputedStyle(a,null).getPropertyValue("line-height").split("px")[0]),f=(3<b?b-3:1)*e,g=(e-d)/2,1<b&&(h=i.slice(0,b-1).join("\n").length),0==c)do h++;while("\n"!=a.value[h]&&/\s/.test(a.value[h]));else h+=1+c-1;a.scrollTop=f-g,a.setSelectionRange(h,h),a.click()}}checkCtrlG(a,b){b.ctrlKey&&"g"==b.key&&(b.preventDefault(),this.showPrompt(a))}};
|
package/plugins/indent.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* possible to indent/unindent multiple lines using Tab/Shift+Tab
|
|
4
4
|
* Files: indent.js
|
|
5
5
|
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
6
8
|
codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
7
9
|
|
|
8
10
|
bracketPairs = {}; // No bracket-auto-indentation used when {}
|
|
@@ -65,7 +67,7 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
65
67
|
let testIndentationWidthPre = document.createElement("pre");
|
|
66
68
|
testIndentationWidthPre.setAttribute("aria-hidden", "true"); // Hide for screen readers
|
|
67
69
|
let testIndentationWidthSpan = document.createElement("span");
|
|
68
|
-
if(codeInput.
|
|
70
|
+
if(codeInput.templateObject.preElementStyled) {
|
|
69
71
|
testIndentationWidthPre.appendChild(testIndentationWidthSpan);
|
|
70
72
|
testIndentationWidthPre.classList.add("code-input_autocomplete_test-indentation-width");
|
|
71
73
|
codeInput.appendChild(testIndentationWidthPre); // Styled like first pre, but first pre found to update
|
|
@@ -81,11 +83,12 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
81
83
|
let indentationWidthPx = testIndentationWidthSpan.offsetWidth;
|
|
82
84
|
codeInput.removeChild(testIndentationWidthPre);
|
|
83
85
|
|
|
84
|
-
codeInput.pluginData.indent = {indentationWidthPx: indentationWidthPx};
|
|
86
|
+
codeInput.pluginData.indent = {automatedKeypresses: false, indentationWidthPx: indentationWidthPx};
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
/* Deal with the Tab key causing indentation, and Tab+Selection indenting / Shift+Tab+Selection unindenting lines, and the mechanism through which Tab can be used to switch focus instead (accessibility). */
|
|
88
90
|
checkTab(codeInput, event) {
|
|
91
|
+
if(codeInput.pluginData.indent.automatedKeypresses) return;
|
|
89
92
|
if(!this.tabIndentationEnabled) return;
|
|
90
93
|
if(this.escTabToChangeFocus) {
|
|
91
94
|
// Accessibility - allow Tab for keyboard navigation when Esc pressed right before it.
|
|
@@ -116,7 +119,12 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
116
119
|
|
|
117
120
|
if(!event.shiftKey && inputElement.selectionStart == inputElement.selectionEnd) {
|
|
118
121
|
// Just place a tab/spaces here.
|
|
122
|
+
// automatedKeypresses property to prevent keypresses being captured
|
|
123
|
+
// by this plugin during automated input as some browsers
|
|
124
|
+
// (e.g. GNOME Web) do.
|
|
125
|
+
codeInput.pluginData.indent.automatedKeypresses = true;
|
|
119
126
|
document.execCommand("insertText", false, this.indentation);
|
|
127
|
+
codeInput.pluginData.indent.automatedKeypresses = false;
|
|
120
128
|
|
|
121
129
|
} else {
|
|
122
130
|
let lines = inputElement.value.split("\n");
|
|
@@ -147,7 +155,12 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
147
155
|
// Add tab at start
|
|
148
156
|
inputElement.selectionStart = letterI;
|
|
149
157
|
inputElement.selectionEnd = letterI;
|
|
158
|
+
// automatedKeypresses property to prevent keypresses being captured
|
|
159
|
+
// by this plugin during automated input as some browsers
|
|
160
|
+
// (e.g. GNOME Web) do.
|
|
161
|
+
codeInput.pluginData.indent.f = true;
|
|
150
162
|
document.execCommand("insertText", false, this.indentation);
|
|
163
|
+
codeInput.pluginData.indent.automatedKeypresses = false;
|
|
151
164
|
|
|
152
165
|
// Change selection
|
|
153
166
|
if(selectionStartI > letterI) { // Indented outside selection
|
|
@@ -191,6 +204,7 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
191
204
|
|
|
192
205
|
/* Deal with new lines retaining indentation */
|
|
193
206
|
checkEnter(codeInput, event) {
|
|
207
|
+
if(codeInput.pluginData.indent.automatedKeypresses) return;
|
|
194
208
|
if(event.key != "Enter") {
|
|
195
209
|
return;
|
|
196
210
|
}
|
|
@@ -206,7 +220,7 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
206
220
|
// find the index of the line our cursor is currently on
|
|
207
221
|
for (let i = 0; i < lines.length; i++) {
|
|
208
222
|
letterI += lines[i].length + 1;
|
|
209
|
-
if(inputElement.selectionEnd
|
|
223
|
+
if(inputElement.selectionEnd < letterI) {
|
|
210
224
|
currentLineI = i;
|
|
211
225
|
break;
|
|
212
226
|
}
|
|
@@ -263,6 +277,10 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
263
277
|
}
|
|
264
278
|
|
|
265
279
|
// insert our indents and any text from the previous line that might have been after the line break
|
|
280
|
+
// negative indents shouldn't exist and would only break future calculations.
|
|
281
|
+
if(numberIndents < 0) {
|
|
282
|
+
numberIndents = 0;
|
|
283
|
+
}
|
|
266
284
|
for (let i = 0; i < numberIndents; i++) {
|
|
267
285
|
newLine += this.indentation;
|
|
268
286
|
}
|
|
@@ -270,11 +288,16 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
270
288
|
// save the current cursor position
|
|
271
289
|
let selectionStartI = inputElement.selectionStart;
|
|
272
290
|
|
|
291
|
+
// automatedKeypresses property to prevent keypresses being captured
|
|
292
|
+
// by this plugin during automated input as some browsers
|
|
293
|
+
// (e.g. GNOME Web) do.
|
|
294
|
+
codeInput.pluginData.indent.automatedKeypresses = true;
|
|
273
295
|
if(bracketThreeLinesTriggered) {
|
|
274
296
|
document.execCommand("insertText", false, "\n" + furtherIndentation); // Write indented line
|
|
275
297
|
numberIndents += 1; // Reflects the new indent
|
|
276
298
|
}
|
|
277
299
|
document.execCommand("insertText", false, "\n" + newLine); // Write new line, including auto-indentation
|
|
300
|
+
codeInput.pluginData.indent.automatedKeypresses = false;
|
|
278
301
|
|
|
279
302
|
// move cursor to new position
|
|
280
303
|
inputElement.selectionStart = selectionStartI + numberIndents*this.indentationNumChars + 1; // count the indent level and the newline character
|
|
@@ -294,6 +317,7 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
294
317
|
|
|
295
318
|
/* Deal with one 'tab' of spaces-based-indentation being deleted by each backspace, rather than one space */
|
|
296
319
|
checkBackspace(codeInput, event) {
|
|
320
|
+
if(codeInput.pluginData.indent.automatedKeypresses) return;
|
|
297
321
|
if(event.key != "Backspace" || this.indentationNumChars == 1) {
|
|
298
322
|
return; // Normal backspace when indentation of 1
|
|
299
323
|
}
|
|
@@ -321,7 +345,8 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
321
345
|
if(codeInput.value.substring(codeInput.textareaElement.selectionStart - this.indentationNumChars, codeInput.textareaElement.selectionStart) == this.indentation) {
|
|
322
346
|
// Indentation before cursor = delete it
|
|
323
347
|
codeInput.textareaElement.selectionStart -= this.indentationNumChars;
|
|
324
|
-
document.execCommand("delete", false, "");
|
|
348
|
+
// document.execCommand("delete", false, "");
|
|
349
|
+
// event.preventDefault();
|
|
325
350
|
}
|
|
326
351
|
}
|
|
327
352
|
}
|
package/plugins/indent.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
codeInput.plugins.Indent=class extends codeInput.Plugin{bracketPairs={};indentation="\t";indentationNumChars=1;tabIndentationEnabled=!0;escTabToChangeFocus=!0;escJustPressed=!1;instructions={tabForIndentation:"Tab and Shift-Tab currently for indentation. Press Esc to enable keyboard navigation.",tabForNavigation:"Tab and Shift-Tab currently for keyboard navigation. Type to return to indentation."};constructor(a=!1,b=4,c={"(":")","[":"]","{":"}"},d=!0,e={}){if(super([]),this.bracketPairs=c,a){this.indentation="";for(let a=0;a<b;a++)this.indentation+=" ";this.indentationNumChars=b}this.escTabToChangeFocus=!0,this.addTranslations(this.instructions,e)}disableTabIndentation(){this.tabIndentationEnabled=!1}enableTabIndentation(){this.tabIndentationEnabled=!0}afterElementsAdded(a){let b=a.textareaElement;b.addEventListener("focus",()=>{this.escTabToChangeFocus&&a.setKeyboardNavInstructions(this.instructions.tabForIndentation,!0)}),b.addEventListener("keydown",b=>{this.checkTab(a,b),this.checkEnter(a,b),this.checkBackspace(a,b)}),b.addEventListener("beforeinput",b=>{this.checkCloseBracket(a,b)});let c=document.createElement("pre");c.setAttribute("aria-hidden","true");let d=document.createElement("span");if(a.
|
|
1
|
+
"use strict";codeInput.plugins.Indent=class extends codeInput.Plugin{bracketPairs={};indentation="\t";indentationNumChars=1;tabIndentationEnabled=!0;escTabToChangeFocus=!0;escJustPressed=!1;instructions={tabForIndentation:"Tab and Shift-Tab currently for indentation. Press Esc to enable keyboard navigation.",tabForNavigation:"Tab and Shift-Tab currently for keyboard navigation. Type to return to indentation."};constructor(a=!1,b=4,c={"(":")","[":"]","{":"}"},d=!0,e={}){if(super([]),this.bracketPairs=c,a){this.indentation="";for(let a=0;a<b;a++)this.indentation+=" ";this.indentationNumChars=b}this.escTabToChangeFocus=!0,this.addTranslations(this.instructions,e)}disableTabIndentation(){this.tabIndentationEnabled=!1}enableTabIndentation(){this.tabIndentationEnabled=!0}afterElementsAdded(a){let b=a.textareaElement;b.addEventListener("focus",()=>{this.escTabToChangeFocus&&a.setKeyboardNavInstructions(this.instructions.tabForIndentation,!0)}),b.addEventListener("keydown",b=>{this.checkTab(a,b),this.checkEnter(a,b),this.checkBackspace(a,b)}),b.addEventListener("beforeinput",b=>{this.checkCloseBracket(a,b)});let c=document.createElement("pre");c.setAttribute("aria-hidden","true");let d=document.createElement("span");if(a.templateObject.preElementStyled)c.appendChild(d),c.classList.add("code-input_autocomplete_test-indentation-width"),a.appendChild(c);else{let b=document.createElement("code");b.appendChild(d),b.classList.add("code-input_autocomplete_test-indentation-width"),c.appendChild(b),a.appendChild(c)}d.innerHTML=a.escapeHtml(this.indentation);let e=d.offsetWidth;a.removeChild(c),a.pluginData.indent={automatedKeypresses:!1,indentationWidthPx:e}}checkTab(a,b){var c=Math.max;if(!a.pluginData.indent.automatedKeypresses&&this.tabIndentationEnabled){if(this.escTabToChangeFocus){if("Escape"==b.key)return this.escJustPressed=!0,void a.setKeyboardNavInstructions(this.instructions.tabForNavigation,!1);if("Tab"!=b.key)return"Shift"==b.key?void 0:(a.setKeyboardNavInstructions(this.instructions.tabForIndentation,!1),void(this.escJustPressed=!1));if(!this.enableTabIndentation||this.escJustPressed)return a.setKeyboardNavInstructions("",!1),void(this.escJustPressed=!1)}else if("Tab"!=b.key)return;let d=a.textareaElement;if(b.preventDefault(),!b.shiftKey&&d.selectionStart==d.selectionEnd)a.pluginData.indent.automatedKeypresses=!0,document.execCommand("insertText",!1,this.indentation),a.pluginData.indent.automatedKeypresses=!1;else{let e=d.value.split("\n"),f=0,g=d.selectionStart,h=d.selectionEnd;for(let j=0;j<e.length;j++)(g<=f+e[j].length&&h>=f+1||g==h&&g<=f+e[j].length+1&&h>=f)&&(b.shiftKey?e[j].substring(0,this.indentationNumChars)==this.indentation&&(d.selectionStart=f,d.selectionEnd=f+this.indentationNumChars,document.execCommand("delete",!1,""),g>f&&(g=c(g-this.indentationNumChars,f)),h-=this.indentationNumChars,f-=this.indentationNumChars):(d.selectionStart=f,d.selectionEnd=f,a.pluginData.indent.f=!0,document.execCommand("insertText",!1,this.indentation),a.pluginData.indent.automatedKeypresses=!1,g>f&&(g+=this.indentationNumChars),h+=this.indentationNumChars,f+=this.indentationNumChars)),f+=e[j].length+1;d.selectionStart=g,d.selectionEnd=h;const i=getComputedStyle(a).direction;"rtl"==i?b.shiftKey?a.scrollBy(a.pluginData.indent.indentationWidthPx,0):a.scrollBy(-a.pluginData.indent.indentationWidthPx,0):b.shiftKey?a.scrollBy(-a.pluginData.indent.indentationWidthPx,0):a.scrollBy(a.pluginData.indent.indentationWidthPx,0)}a.value=d.value}}checkEnter(a,b){if(a.pluginData.indent.automatedKeypresses)return;if("Enter"!=b.key)return;b.preventDefault();let c=a.textareaElement,d=c.value.split("\n"),e=0,f=d.length-1,g="",h=0;for(let g=0;g<d.length;g++)if(e+=d[g].length+1,c.selectionEnd<e){f=g;break}let j=d[f].length-(e-c.selectionEnd)+1;for(let c=0;c<j&&d[f].substring(c,c+this.indentationNumChars)==this.indentation;c+=this.indentationNumChars)h++;let k="";j!=d[f].length&&(k=d[f].substring(j),d[f]=d[f].substring(0,j));let l=!1,m="";if(null!=this.bracketPairs)for(let a in this.bracketPairs)if(d[f][d[f].length-1]==a){let b=this.bracketPairs[a];if(0<k.length&&k[0]==b){l=!0;for(let a=0;a<h+1;a++)m+=this.indentation}else h++;break}else{let b=this.bracketPairs[a];if(0<k.length&&k[0]==b){h--;break}}0>h&&(h=0);for(let c=0;c<h;c++)g+=this.indentation;let n=c.selectionStart;a.pluginData.indent.automatedKeypresses=!0,l&&(document.execCommand("insertText",!1,"\n"+m),h+=1),document.execCommand("insertText",!1,"\n"+g),a.pluginData.indent.automatedKeypresses=!1,c.selectionStart=n+h*this.indentationNumChars+1,c.selectionEnd=c.selectionStart;let o=+getComputedStyle(c).paddingTop.replace("px",""),p=+getComputedStyle(c).lineHeight.replace("px",""),q=+getComputedStyle(a).height.replace("px","");f*p+2*p+o>=c.scrollTop+q&&a.scrollBy(0,+getComputedStyle(c).lineHeight.replace("px","")),a.value=c.value}checkBackspace(a,b){if(!a.pluginData.indent.automatedKeypresses&&"Backspace"==b.key&&1!=this.indentationNumChars){let c=a.textareaElement;c.selectionStart==c.selectionEnd&&a.value.substring(c.selectionStart-this.indentationNumChars,c.selectionStart)==this.indentation&&(c.selectionStart-=this.indentationNumChars,b.preventDefault(),document.execCommand("delete",!1,""))}}checkCloseBracket(a,b){if(a.textareaElement.selectionStart==a.textareaElement.selectionEnd)for(let c in this.bracketPairs){let d=this.bracketPairs[c];b.data==d&&a.value.substring(a.textareaElement.selectionStart-this.indentationNumChars,a.textareaElement.selectionStart)==this.indentation&&(a.textareaElement.selectionStart-=this.indentationNumChars)}}};
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Files: prism-line-numbers.css
|
|
6
6
|
*/
|
|
7
7
|
/* Update padding to match line-numbers plugin */
|
|
8
|
-
code-input.line-numbers textarea, code-input.line-numbers.code-input_pre-element-styled pre,
|
|
9
|
-
.line-numbers code-input textarea, .line-numbers code-input.code-input_pre-element-styled pre {
|
|
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
|
+
.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
10
|
padding-left: max(3.8em, var(--padding, 16px))!important;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -15,7 +15,16 @@ code-input.line-numbers, .line-numbers code-input {
|
|
|
15
15
|
grid-template-columns: calc(100% - max(0em, calc(3.8em - var(--padding, 16px))));
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/*
|
|
19
|
-
code-input .
|
|
20
|
-
|
|
18
|
+
/* Override Prism styles so there's no display:inline, relatively-positioned code element which breaks offsetTop, used in FindAndReplace, in Firefox. */
|
|
19
|
+
code-input pre[class*=language-].line-numbers>code {
|
|
20
|
+
position: static;
|
|
21
|
+
}
|
|
22
|
+
/* Line numbers now positioned relative to the pre element not the code element. */
|
|
23
|
+
code-input .line-numbers .line-numbers-rows {
|
|
24
|
+
left: 0;
|
|
25
|
+
top: var(--padding);
|
|
26
|
+
}
|
|
27
|
+
/* Things with padding when instructions are present */
|
|
28
|
+
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);
|
|
21
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.line-numbers code-input textarea,.line-numbers code-input.code-input_pre-element-styled pre,code-input.line-numbers textarea,code-input.line-numbers.code-input_pre-element-styled pre{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 .code-
|
|
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)}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* gain a CSS class while selected, or trigger JavaScript callbacks.
|
|
4
4
|
* Files: select-token-callbacks.js
|
|
5
5
|
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
6
8
|
codeInput.plugins.SelectTokenCallbacks = class extends codeInput.Plugin {
|
|
7
9
|
/**
|
|
8
10
|
* Set up the behaviour of tokens text-selected in the `<code-input>` element, and the exact definition of a token being text-selected.
|
|
@@ -286,4 +288,4 @@ codeInput.plugins.SelectTokenCallbacks.SelectedTokenState = class {
|
|
|
286
288
|
endIndex -= childText.length;
|
|
287
289
|
}
|
|
288
290
|
}
|
|
289
|
-
}
|
|
291
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
codeInput.plugins.SelectTokenCallbacks=class extends codeInput.Plugin{constructor(a=codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks.createClassSynchronisation(),b=!1,c=!0,d=!0,e=!1,f=!0,g=!0){super([]),this.tokenSelectorCallbacks=a,this.onlyCaretNotSelection=b,this.caretAtStartIsSelected=c,this.caretAtEndIsSelected=d,this.createSubTokens=e,this.partiallySelectedTokensAreSelected=f,this.parentTokensAreSelected=g}afterHighlight(a){this.syncSelection(a)}afterElementsAdded(a){a.pluginData.selectTokenCallbacks={},a.pluginData.selectTokenCallbacks.lastSelectionStart=a.textareaElement.selectionStart,a.pluginData.selectTokenCallbacks.lastSelectionEnd=a.textareaElement.selectionEnd,a.pluginData.selectTokenCallbacks.selectedTokenState=new codeInput.plugins.SelectTokenCallbacks.SelectedTokenState(a.codeElement,this.tokenSelectorCallbacks,this.onlyCaretNotSelection,this.caretAtStartIsSelected,this.caretAtEndIsSelected,this.createSubTokens,this.partiallySelectedTokensAreSelected,this.parentTokensAreSelected),this.syncSelection(a),a.textareaElement.addEventListener("selectionchange",()=>{this.checkSelectionChanged(a)}),a.textareaElement.addEventListener("select",()=>{this.checkSelectionChanged(a)}),a.textareaElement.addEventListener("keypress",()=>{this.checkSelectionChanged(a)}),a.textareaElement.addEventListener("mousedown",()=>{this.checkSelectionChanged(a)})}checkSelectionChanged(a){(a.textareaElement.selectionStart!=a.pluginData.selectTokenCallbacks.lastSelectionStart||a.textareaElement.selectionEnd!=a.pluginData.selectTokenCallbacks.lastSelectionEnd)&&(this.syncSelection(a),a.pluginData.selectTokenCallbacks.lastSelectionStart=a.textareaElement.selectionStart,a.pluginData.selectTokenCallbacks.lastSelectionEnd=a.textareaElement.selectionEnd)}syncSelection(a){a.pluginData.selectTokenCallbacks.selectedTokenState.updateSelection(a.textareaElement.selectionStart,a.textareaElement.selectionEnd)}},codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks=class{constructor(a,b){this.tokenSelectedCallback=a,this.selectChangedCallback=b}static createClassSynchronisation(a="code-input_select-token-callbacks_selected"){return new codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks(b=>{b.classList.add(a)},b=>{for(let c=b.getElementsByClassName(a);0<c.length;)c[0].classList.remove(a)})}},codeInput.plugins.SelectTokenCallbacks.SelectedTokenState=class{constructor(a,b,c,d,e,f,g,h){this.tokenContainer=a,this.tokenSelectorCallbacks=b,this.onlyCaretNotSelection=c,this.caretAtStartIsSelected=d,this.caretAtEndIsSelected=e,this.createSubTokens=f,this.partiallySelectedTokensAreSelected=g,this.parentTokensAreSelected=h}updateSelection(a,b){this.selectChanged(),this.onlyCaretNotSelection&&a!=b||this.updateSelectedTokens(this.tokenContainer,a,b)}selectChanged(){if(this.createSubTokens)for(let a=this.tokenContainer.getElementsByClassName("code-input_select-token-callbacks_temporary-span");0<a.length;)a[0].parentElement.replaceChild(new Text(a[0].textContent),a[0]);this.tokenSelectorCallbacks.selectChangedCallback(this.tokenContainer)}updateSelectedTokens(a,b,c){if(!(0>c)&&(0!=c||this.caretAtStartIsSelected)){this.parentTokensAreSelected&&a!==this.tokenContainer&&this.tokenSelectorCallbacks.tokenSelectedCallback(a);for(let d=0;d<a.childNodes.length;d++){let e=a.childNodes[d],f=e.textContent,g=!1;if(3==e.nodeType)if(this.createSubTokens){if(d+1<a.childNodes.length&&3==a.childNodes[d+1].nodeType){a.childNodes[d+1].textContent=e.textContent+a.childNodes[d+1].textContent,a.removeChild(e),d--;continue}g=!0;let b=document.createElement("span");b.textContent=f,b.classList.add("code-input_select-token-callbacks_temporary-span"),a.replaceChild(b,e),e=b}else{b-=f.length,c-=f.length;continue}if(0>=b){if(f.length>c){if(this.partiallySelectedTokensAreSelected)if(g){if(this.createSubTokens&&b!=c){let a=document.createElement("span");this.tokenSelectorCallbacks.tokenSelectedCallback(a),a.classList.add("code-input_select-token-callbacks_temporary-span"),a.textContent=f.substring(0,c);let b=f.substring(c);e.textContent=b,e.insertAdjacentElement("beforebegin",a),d++}(this.parentTokensAreSelected||!this.createSubTokens)&&this.tokenSelectorCallbacks.tokenSelectedCallback(e)}else this.updateSelectedTokens(e,0,c);return}this.tokenSelectorCallbacks.tokenSelectedCallback(e)}else if(this.caretAtEndIsSelected&&f.length>=b||f.length>b){if(this.partiallySelectedTokensAreSelected)if(g){if(this.createSubTokens&&b!=c)if(f.length>c){let a=document.createElement("span");a.classList.add("code-input_select-token-callbacks_temporary-span"),a.textContent=f.substring(0,b);let g=f.substring(b,c);e.textContent=g,this.tokenSelectorCallbacks.tokenSelectedCallback(e);let h=document.createElement("span");h.classList.add("code-input_select-token-callbacks_temporary-span"),h.textContent=f.substring(c),e.insertAdjacentElement("beforebegin",a),e.insertAdjacentElement("afterend",h),d++}else{let a=f.substring(0,b);e.textContent=a;let c=document.createElement("span");this.tokenSelectorCallbacks.tokenSelectedCallback(c),c.classList.add("code-input_select-token-callbacks_temporary-span"),c.textContent=f.substring(b),e.insertAdjacentElement("afterend",c),d++}(this.parentTokensAreSelected||!this.createSubTokens)&&this.tokenSelectorCallbacks.tokenSelectedCallback(e)}else this.updateSelectedTokens(e,b,c);if(this.caretAtStartIsSelected){if(f.length>c)return;}else if(f.length>=c)return}b-=f.length,c-=f.length}}}};
|
|
1
|
+
"use strict";codeInput.plugins.SelectTokenCallbacks=class extends codeInput.Plugin{constructor(a=codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks.createClassSynchronisation(),b=!1,c=!0,d=!0,e=!1,f=!0,g=!0){super([]),this.tokenSelectorCallbacks=a,this.onlyCaretNotSelection=b,this.caretAtStartIsSelected=c,this.caretAtEndIsSelected=d,this.createSubTokens=e,this.partiallySelectedTokensAreSelected=f,this.parentTokensAreSelected=g}afterHighlight(a){this.syncSelection(a)}afterElementsAdded(a){a.pluginData.selectTokenCallbacks={},a.pluginData.selectTokenCallbacks.lastSelectionStart=a.textareaElement.selectionStart,a.pluginData.selectTokenCallbacks.lastSelectionEnd=a.textareaElement.selectionEnd,a.pluginData.selectTokenCallbacks.selectedTokenState=new codeInput.plugins.SelectTokenCallbacks.SelectedTokenState(a.codeElement,this.tokenSelectorCallbacks,this.onlyCaretNotSelection,this.caretAtStartIsSelected,this.caretAtEndIsSelected,this.createSubTokens,this.partiallySelectedTokensAreSelected,this.parentTokensAreSelected),this.syncSelection(a),a.textareaElement.addEventListener("selectionchange",()=>{this.checkSelectionChanged(a)}),a.textareaElement.addEventListener("select",()=>{this.checkSelectionChanged(a)}),a.textareaElement.addEventListener("keypress",()=>{this.checkSelectionChanged(a)}),a.textareaElement.addEventListener("mousedown",()=>{this.checkSelectionChanged(a)})}checkSelectionChanged(a){(a.textareaElement.selectionStart!=a.pluginData.selectTokenCallbacks.lastSelectionStart||a.textareaElement.selectionEnd!=a.pluginData.selectTokenCallbacks.lastSelectionEnd)&&(this.syncSelection(a),a.pluginData.selectTokenCallbacks.lastSelectionStart=a.textareaElement.selectionStart,a.pluginData.selectTokenCallbacks.lastSelectionEnd=a.textareaElement.selectionEnd)}syncSelection(a){a.pluginData.selectTokenCallbacks.selectedTokenState.updateSelection(a.textareaElement.selectionStart,a.textareaElement.selectionEnd)}},codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks=class{constructor(a,b){this.tokenSelectedCallback=a,this.selectChangedCallback=b}static createClassSynchronisation(a="code-input_select-token-callbacks_selected"){return new codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks(b=>{b.classList.add(a)},b=>{for(let c=b.getElementsByClassName(a);0<c.length;)c[0].classList.remove(a)})}},codeInput.plugins.SelectTokenCallbacks.SelectedTokenState=class{constructor(a,b,c,d,e,f,g,h){this.tokenContainer=a,this.tokenSelectorCallbacks=b,this.onlyCaretNotSelection=c,this.caretAtStartIsSelected=d,this.caretAtEndIsSelected=e,this.createSubTokens=f,this.partiallySelectedTokensAreSelected=g,this.parentTokensAreSelected=h}updateSelection(a,b){this.selectChanged(),this.onlyCaretNotSelection&&a!=b||this.updateSelectedTokens(this.tokenContainer,a,b)}selectChanged(){if(this.createSubTokens)for(let a=this.tokenContainer.getElementsByClassName("code-input_select-token-callbacks_temporary-span");0<a.length;)a[0].parentElement.replaceChild(new Text(a[0].textContent),a[0]);this.tokenSelectorCallbacks.selectChangedCallback(this.tokenContainer)}updateSelectedTokens(a,b,c){if(!(0>c)&&(0!=c||this.caretAtStartIsSelected)){this.parentTokensAreSelected&&a!==this.tokenContainer&&this.tokenSelectorCallbacks.tokenSelectedCallback(a);for(let d=0;d<a.childNodes.length;d++){let e=a.childNodes[d],f=e.textContent,g=!1;if(3==e.nodeType)if(this.createSubTokens){if(d+1<a.childNodes.length&&3==a.childNodes[d+1].nodeType){a.childNodes[d+1].textContent=e.textContent+a.childNodes[d+1].textContent,a.removeChild(e),d--;continue}g=!0;let b=document.createElement("span");b.textContent=f,b.classList.add("code-input_select-token-callbacks_temporary-span"),a.replaceChild(b,e),e=b}else{b-=f.length,c-=f.length;continue}if(0>=b){if(f.length>c){if(this.partiallySelectedTokensAreSelected)if(g){if(this.createSubTokens&&b!=c){let a=document.createElement("span");this.tokenSelectorCallbacks.tokenSelectedCallback(a),a.classList.add("code-input_select-token-callbacks_temporary-span"),a.textContent=f.substring(0,c);let b=f.substring(c);e.textContent=b,e.insertAdjacentElement("beforebegin",a),d++}(this.parentTokensAreSelected||!this.createSubTokens)&&this.tokenSelectorCallbacks.tokenSelectedCallback(e)}else this.updateSelectedTokens(e,0,c);return}this.tokenSelectorCallbacks.tokenSelectedCallback(e)}else if(this.caretAtEndIsSelected&&f.length>=b||f.length>b){if(this.partiallySelectedTokensAreSelected)if(g){if(this.createSubTokens&&b!=c)if(f.length>c){let a=document.createElement("span");a.classList.add("code-input_select-token-callbacks_temporary-span"),a.textContent=f.substring(0,b);let g=f.substring(b,c);e.textContent=g,this.tokenSelectorCallbacks.tokenSelectedCallback(e);let h=document.createElement("span");h.classList.add("code-input_select-token-callbacks_temporary-span"),h.textContent=f.substring(c),e.insertAdjacentElement("beforebegin",a),e.insertAdjacentElement("afterend",h),d++}else{let a=f.substring(0,b);e.textContent=a;let c=document.createElement("span");this.tokenSelectorCallbacks.tokenSelectedCallback(c),c.classList.add("code-input_select-token-callbacks_temporary-span"),c.textContent=f.substring(b),e.insertAdjacentElement("afterend",c),d++}(this.parentTokensAreSelected||!this.createSubTokens)&&this.tokenSelectorCallbacks.tokenSelectedCallback(e)}else this.updateSelectedTokens(e,b,c);if(this.caretAtStartIsSelected){if(f.length>c)return;}else if(f.length>=c)return}b-=f.length,c-=f.length}}}};
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Render special characters and control characters as a symbol with their hex code.
|
|
3
3
|
* Files: special-chars.js, special-chars.css
|
|
4
|
+
*
|
|
5
|
+
* WARNING:
|
|
6
|
+
*
|
|
7
|
+
* This plugin is currently unstable when used with other plugins,
|
|
8
|
+
* Unicode characters, or highlight.js. I hope to fix much of this by
|
|
9
|
+
* major version 3, and if you could help that would be amazing!
|
|
10
|
+
*
|
|
11
|
+
* See https://github.com/WebCoder49/code-input/issues?q=is%3Aissue%20state%3Aopen%20specialchars
|
|
4
12
|
*/
|
|
5
13
|
|
|
6
14
|
/* Main styling */
|
|
@@ -37,6 +45,10 @@
|
|
|
37
45
|
vertical-align: middle;
|
|
38
46
|
outline: 0.1px solid currentColor;
|
|
39
47
|
|
|
48
|
+
/* Contain character for use by other plugins, but hide it */
|
|
49
|
+
color: transparent;
|
|
50
|
+
font-size: 0;
|
|
51
|
+
|
|
40
52
|
--hex-0: var(
|
|
41
53
|
--code-input_special-chars_0);
|
|
42
54
|
--hex-1: var(
|
|
@@ -91,4 +103,4 @@
|
|
|
91
103
|
height: 1.5em;
|
|
92
104
|
bottom: -1em;
|
|
93
105
|
content: attr(data-hex3);
|
|
94
|
-
}
|
|
106
|
+
}
|
package/plugins/special-chars.js
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Render special characters and control characters as a symbol with their hex code.
|
|
3
3
|
* Files: special-chars.js, special-chars.css
|
|
4
|
+
*
|
|
5
|
+
* WARNING:
|
|
6
|
+
*
|
|
7
|
+
* This plugin is currently unstable when used with other plugins,
|
|
8
|
+
* Unicode characters, or highlight.js. I hope to fix much of this by
|
|
9
|
+
* major version 3, and if you could help that would be amazing!
|
|
10
|
+
*
|
|
11
|
+
* See https://github.com/WebCoder49/code-input/issues?q=is%3Aissue%20state%3Aopen%20specialchars
|
|
4
12
|
*/
|
|
13
|
+
"use strict";
|
|
5
14
|
|
|
6
15
|
codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
|
|
7
16
|
specialCharRegExp;
|
|
@@ -13,9 +22,9 @@ codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
|
|
|
13
22
|
/**
|
|
14
23
|
* Create a special characters plugin instance.
|
|
15
24
|
* Default = covers many non-renderable ASCII characters.
|
|
16
|
-
* @param {Boolean} colorInSpecialChars Whether or not to give special characters custom background colors based on their hex code
|
|
17
|
-
* @param {Boolean} inheritTextColor If
|
|
18
|
-
* @param {RegExp} specialCharRegExp The regular expression which matches special characters
|
|
25
|
+
* @param {Boolean} colorInSpecialChars Whether or not to give special characters custom background colors based on their hex code. Defaults to false.
|
|
26
|
+
* @param {Boolean} inheritTextColor If true, forces the color of the hex code to inherit from syntax highlighting. If false, the base color of the `pre code` element is used to give contrast to the small characters. Defaults to false.
|
|
27
|
+
* @param {RegExp} specialCharRegExp The regular expression which matches special characters. Defaults to many non-renderable ASCII characters (which characters are renderable depends on the browser and OS).
|
|
19
28
|
*/
|
|
20
29
|
constructor(colorInSpecialChars = false, inheritTextColor = false, specialCharRegExp = /(?!\n)(?!\t)[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]|[\u{0200}-\u{FFFF}]/ug) { // By default, covers many non-renderable ASCII characters
|
|
21
30
|
super([]); // No observed attributes
|
|
@@ -100,6 +109,7 @@ codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
|
|
|
100
109
|
|
|
101
110
|
// Create element with hex code
|
|
102
111
|
let result = document.createElement("span");
|
|
112
|
+
result.textContent = matchChar;
|
|
103
113
|
result.classList.add("code-input_special-char");
|
|
104
114
|
result.style.setProperty("--hex-0", "var(--code-input_special-chars_" + hexCode[0] + ")");
|
|
105
115
|
result.style.setProperty("--hex-1", "var(--code-input_special-chars_" + hexCode[1] + ")");
|
|
@@ -189,4 +199,4 @@ codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
|
|
|
189
199
|
|
|
190
200
|
return width;
|
|
191
201
|
}
|
|
192
|
-
}
|
|
202
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
:root,body{--code-input_special-chars_0:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdjZGBgYPj///9/RhCAMcA0bg6yHgAPmh/6BoxTcQAAAABJRU5ErkJgggAA');--code-input_special-chars_1:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdjZGBgYPj///9/RhAggwMAitIUBr9U6sYAAAAASUVORK5CYII=');--code-input_special-chars_2:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGCEMUCCjCgyYBFGRrAKFBkAuLYT9kYcIu0AAAAASUVORK5CYII=');--code-input_special-chars_3:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABhJREFUGFdj/P///38GKGCEMUCCjMTJAACYiBPyG8sfAgAAAABJRU5ErkJggg==');--code-input_special-chars_4:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///39GRkZGMI3BYYACRhgDrAKZAwAYxhvyz0DRIQAAAABJRU5ErkJggg==');--code-input_special-chars_5:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACJJREFUGFdj/P///38GKGAEcRgZGRlBfDAHLgNjgFUgywAAuR4T9hxJl2YAAAAASUVORK5CYII=');--code-input_special-chars_6:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdj/P///38GKGAEcRgZGRlBfDAHQwasAlkGABcdF/Y4yco2AAAAAElFTkSuQmCC');--code-input_special-chars_7:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdj/P///38GKGCEMUCCRHIAWMgT8kue3bQAAAAASUVORK5CYII=');--code-input_special-chars_8:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GKGAEcRgZGSE0cTIAvHcb8v+mIfAAAAAASUVORK5CYII=');--code-input_special-chars_9:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGAEcRgZGSE0igxMCVgGmQMAPqcX8hWL1K0AAAAASUVORK5CYII=');--code-input_special-chars_A:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdjZGBgYPj///9/RhCAMcA0iADJggCmDEw5ALdxH/aGuYHqAAAAAElFTkSuQmCC');--code-input_special-chars_B:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GBgYGRhAAceA0cTIAvc0b/vRDnVoAAAAASUVORK5CYII=');--code-input_special-chars_C:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdjZGBgYPj///9/EM0IYjAyMjIS4CDrAQC57hP+uLwvFQAAAABJRU5ErkJggg==');--code-input_special-chars_D:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdj/P///38GBgYGRhAAceA0fg5MDwAveh/6ToN9VwAAAABJRU5ErkJggg==');--code-input_special-chars_E:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABxJREFUGFdj/P///38GKGAEcRgZGRlBfDCHsAwA2UwT+mVIH1MAAAAASUVORK5CYII=');--code-input_special-chars_F:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///38GKGAEcRgZGRlBfDAHtwxMGQDZZhP+BnB1kwAAAABJRU5ErkJggg==')}.code-input_special-char{display:inline-block;position:relative;top:0;left:0;height:1em;overflow:hidden;text-decoration:none;text-shadow:none;vertical-align:middle;outline:.1px solid currentColor;--hex-0:var(
|
|
1
|
+
:root,body{--code-input_special-chars_0:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdjZGBgYPj///9/RhCAMcA0bg6yHgAPmh/6BoxTcQAAAABJRU5ErkJgggAA');--code-input_special-chars_1:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdjZGBgYPj///9/RhAggwMAitIUBr9U6sYAAAAASUVORK5CYII=');--code-input_special-chars_2:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGCEMUCCjCgyYBFGRrAKFBkAuLYT9kYcIu0AAAAASUVORK5CYII=');--code-input_special-chars_3:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABhJREFUGFdj/P///38GKGCEMUCCjMTJAACYiBPyG8sfAgAAAABJRU5ErkJggg==');--code-input_special-chars_4:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///39GRkZGMI3BYYACRhgDrAKZAwAYxhvyz0DRIQAAAABJRU5ErkJggg==');--code-input_special-chars_5:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACJJREFUGFdj/P///38GKGAEcRgZGRlBfDAHLgNjgFUgywAAuR4T9hxJl2YAAAAASUVORK5CYII=');--code-input_special-chars_6:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdj/P///38GKGAEcRgZGRlBfDAHQwasAlkGABcdF/Y4yco2AAAAAElFTkSuQmCC');--code-input_special-chars_7:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdj/P///38GKGCEMUCCRHIAWMgT8kue3bQAAAAASUVORK5CYII=');--code-input_special-chars_8:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GKGAEcRgZGSE0cTIAvHcb8v+mIfAAAAAASUVORK5CYII=');--code-input_special-chars_9:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGAEcRgZGSE0igxMCVgGmQMAPqcX8hWL1K0AAAAASUVORK5CYII=');--code-input_special-chars_A:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdjZGBgYPj///9/RhCAMcA0iADJggCmDEw5ALdxH/aGuYHqAAAAAElFTkSuQmCC');--code-input_special-chars_B:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GBgYGRhAAceA0cTIAvc0b/vRDnVoAAAAASUVORK5CYII=');--code-input_special-chars_C:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdjZGBgYPj///9/EM0IYjAyMjIS4CDrAQC57hP+uLwvFQAAAABJRU5ErkJggg==');--code-input_special-chars_D:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdj/P///38GBgYGRhAAceA0fg5MDwAveh/6ToN9VwAAAABJRU5ErkJggg==');--code-input_special-chars_E:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABxJREFUGFdj/P///38GKGAEcRgZGRlBfDCHsAwA2UwT+mVIH1MAAAAASUVORK5CYII=');--code-input_special-chars_F:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///38GKGAEcRgZGRlBfDAHtwxMGQDZZhP+BnB1kwAAAABJRU5ErkJggg==')}.code-input_special-char{display:inline-block;position:relative;top:0;left:0;height:1em;overflow:hidden;text-decoration:none;text-shadow:none;vertical-align:middle;outline:.1px solid currentColor;color:transparent;font-size:0;--hex-0:var(
|
|
2
2
|
--code-input_special-chars_0);--hex-1:var(
|
|
3
3
|
--code-input_special-chars_0);--hex-2:var(
|
|
4
4
|
--code-input_special-chars_0);--hex-3:var(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
codeInput.plugins.SpecialChars=class extends codeInput.Plugin{specialCharRegExp;cachedColors;cachedWidths;canvasContext;constructor(a=!1,b=!1,c=/(?!\n)(?!\t)[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]|[\u{0200}-\u{FFFF}]/ug){super([]),this.specialCharRegExp=c,this.colorInSpecialChars=a,this.inheritTextColor=b,this.cachedColors={},this.cachedWidths={};let d=document.createElement("canvas");this.canvasContext=d.getContext("2d")}afterElementsAdded(a){setTimeout(()=>{a.value=a.value},100)}afterHighlight(a){let b=a.codeElement;a.pluginData.specialChars={},a.pluginData.specialChars.contrastColor=window.getComputedStyle(b).color,this.recursivelyReplaceText(a,b),this.lastFont=window.getComputedStyle(a.textareaElement).font}recursivelyReplaceText(a,b){for(let c,d=0;d<b.childNodes.length;d++)if(c=b.childNodes[d],3==c.nodeType){let b=c.nodeValue;this.specialCharRegExp.lastIndex=0;let d=this.specialCharRegExp.exec(b);if(null!=d){let b=d.index;if(c=c.splitText(b+1).previousSibling,0<b&&(c=c.splitText(b)),""!=c.textContent){let b=this.getStylisedSpecialChar(a,c.textContent);c.parentNode.insertBefore(b,c),c.textContent=""}}}else 1==c.nodeType&&"code-input_special-char"!=c.className&&""!=c.nodeValue&&this.recursivelyReplaceText(a,c)}getStylisedSpecialChar(a,b){let c,d=b.codePointAt(0);this.colorInSpecialChars&&(c=this.getCharacterColors(d)),d=d.toString(16),d=("0000"+d).substring(d.length),d=d.toUpperCase();let e=this.getCharacterWidthEm(a,b),f=document.createElement("span");return f.classList.add("code-input_special-char"),f.style.setProperty("--hex-0","var(--code-input_special-chars_"+d[0]+")"),f.style.setProperty("--hex-1","var(--code-input_special-chars_"+d[1]+")"),f.style.setProperty("--hex-2","var(--code-input_special-chars_"+d[2]+")"),f.style.setProperty("--hex-3","var(--code-input_special-chars_"+d[3]+")"),0==e?f.classList.add("code-input_special-char_zero-width"):f.style.width=e+"em",this.colorInSpecialChars?(f.style.backgroundColor="#"+c[0],f.style.setProperty("--code-input_special-char_color",c[1])):!this.inheritTextColor&&f.style.setProperty("--code-input_special-char_color",a.pluginData.specialChars.contrastColor),f}getCharacterColors(a){let b;if(!(a in this.cachedColors)){let c=a.toString(16),d="";for(let a=0;a<c.length;a++)d+=c[a]+c[a];d=("000000"+d).substring(d.length);let e=0;const f=[.299,.587,.114];for(let a=0;6>a;a+=2)e+=parseInt(d.substring(a,a+2),16)*f[a/2];return b=128>e?"white":"black",this.cachedColors[a]=[d,b],[d,b]}return this.cachedColors[a]}getCharacterWidthEm(a,b){if(/|˞|[̀-ͯ]|[҃-҉]|[-]|/.test(b))return 0;if("\x96"!=b&&/[\0-]|[-]/g.test(b)){let b=this.getCharacterWidthEm(a,"\x96");return b}let c=getComputedStyle(a.textareaElement).fontFamily+" "+getComputedStyle(a.textareaElement).fontStretch+" "+getComputedStyle(a.textareaElement).fontStyle+" "+getComputedStyle(a.textareaElement).fontVariant+" "+getComputedStyle(a.textareaElement).fontWeight+" "+getComputedStyle(a.textareaElement).lineHeight;if(null==this.cachedWidths[c]&&(this.cachedWidths[c]={}),null!=this.cachedWidths[c][b])return this.cachedWidths[c][b];this.canvasContext.font=getComputedStyle(a.textareaElement).font.replace(getComputedStyle(a.textareaElement).fontSize,"20px");let d=this.canvasContext.measureText(b).width/20;if(1<d)d/=2;else if(0==d&&"\x96"!=b){let b=this.getCharacterWidthEm(a,"\x96");return b}if(navigator.userAgent.includes("Mozilla")&&!navigator.userAgent.includes("Chrome")&&!navigator.userAgent.includes("Safari")){let b=+getComputedStyle(a.textareaElement).fontSize.substring(0,getComputedStyle(a.textareaElement).fontSize.length-2);20>b&&(d*=20/b)}return this.cachedWidths[c][b]=d,d}};
|
|
1
|
+
"use strict";codeInput.plugins.SpecialChars=class extends codeInput.Plugin{specialCharRegExp;cachedColors;cachedWidths;canvasContext;constructor(a=!1,b=!1,c=/(?!\n)(?!\t)[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]|[\u{0200}-\u{FFFF}]/ug){super([]),this.specialCharRegExp=c,this.colorInSpecialChars=a,this.inheritTextColor=b,this.cachedColors={},this.cachedWidths={};let d=document.createElement("canvas");this.canvasContext=d.getContext("2d")}afterElementsAdded(a){setTimeout(()=>{a.value=a.value},100)}afterHighlight(a){let b=a.codeElement;a.pluginData.specialChars={},a.pluginData.specialChars.contrastColor=window.getComputedStyle(b).color,this.recursivelyReplaceText(a,b),this.lastFont=window.getComputedStyle(a.textareaElement).font}recursivelyReplaceText(a,b){for(let c,d=0;d<b.childNodes.length;d++)if(c=b.childNodes[d],3==c.nodeType){let b=c.nodeValue;this.specialCharRegExp.lastIndex=0;let d=this.specialCharRegExp.exec(b);if(null!=d){let b=d.index;if(c=c.splitText(b+1).previousSibling,0<b&&(c=c.splitText(b)),""!=c.textContent){let b=this.getStylisedSpecialChar(a,c.textContent);c.parentNode.insertBefore(b,c),c.textContent=""}}}else 1==c.nodeType&&"code-input_special-char"!=c.className&&""!=c.nodeValue&&this.recursivelyReplaceText(a,c)}getStylisedSpecialChar(a,b){let c,d=b.codePointAt(0);this.colorInSpecialChars&&(c=this.getCharacterColors(d)),d=d.toString(16),d=("0000"+d).substring(d.length),d=d.toUpperCase();let e=this.getCharacterWidthEm(a,b),f=document.createElement("span");return f.textContent=b,f.classList.add("code-input_special-char"),f.style.setProperty("--hex-0","var(--code-input_special-chars_"+d[0]+")"),f.style.setProperty("--hex-1","var(--code-input_special-chars_"+d[1]+")"),f.style.setProperty("--hex-2","var(--code-input_special-chars_"+d[2]+")"),f.style.setProperty("--hex-3","var(--code-input_special-chars_"+d[3]+")"),0==e?f.classList.add("code-input_special-char_zero-width"):f.style.width=e+"em",this.colorInSpecialChars?(f.style.backgroundColor="#"+c[0],f.style.setProperty("--code-input_special-char_color",c[1])):!this.inheritTextColor&&f.style.setProperty("--code-input_special-char_color",a.pluginData.specialChars.contrastColor),f}getCharacterColors(a){let b;if(!(a in this.cachedColors)){let c=a.toString(16),d="";for(let a=0;a<c.length;a++)d+=c[a]+c[a];d=("000000"+d).substring(d.length);let e=0;const f=[.299,.587,.114];for(let a=0;6>a;a+=2)e+=parseInt(d.substring(a,a+2),16)*f[a/2];return b=128>e?"white":"black",this.cachedColors[a]=[d,b],[d,b]}return this.cachedColors[a]}getCharacterWidthEm(a,b){if(/|˞|[̀-ͯ]|[҃-҉]|[-]|/.test(b))return 0;if("\x96"!=b&&/[\0-]|[-]/g.test(b)){let b=this.getCharacterWidthEm(a,"\x96");return b}let c=getComputedStyle(a.textareaElement).fontFamily+" "+getComputedStyle(a.textareaElement).fontStretch+" "+getComputedStyle(a.textareaElement).fontStyle+" "+getComputedStyle(a.textareaElement).fontVariant+" "+getComputedStyle(a.textareaElement).fontWeight+" "+getComputedStyle(a.textareaElement).lineHeight;if(null==this.cachedWidths[c]&&(this.cachedWidths[c]={}),null!=this.cachedWidths[c][b])return this.cachedWidths[c][b];this.canvasContext.font=getComputedStyle(a.textareaElement).font.replace(getComputedStyle(a.textareaElement).fontSize,"20px");let d=this.canvasContext.measureText(b).width/20;if(1<d)d/=2;else if(0==d&&"\x96"!=b){let b=this.getCharacterWidthEm(a,"\x96");return b}if(navigator.userAgent.includes("Mozilla")&&!navigator.userAgent.includes("Chrome")&&!navigator.userAgent.includes("Safari")){let b=+getComputedStyle(a.textareaElement).fontSize.substring(0,getComputedStyle(a.textareaElement).fontSize.length-2);20>b&&(d*=20/b)}return this.cachedWidths[c][b]=d,d}};
|
package/plugins/test.js
CHANGED
|
@@ -8,29 +8,44 @@
|
|
|
8
8
|
* codeInput.registerTemplate("syntax-highlighted", codeInput.templates.hljs(hljs, [new codeInput.plugins.Test()]));
|
|
9
9
|
* ```
|
|
10
10
|
*/
|
|
11
|
+
"use strict";
|
|
12
|
+
|
|
11
13
|
codeInput.plugins.Test = class extends codeInput.Plugin {
|
|
12
|
-
|
|
14
|
+
instructions = {
|
|
15
|
+
beforeHighlight: "before highlight",
|
|
16
|
+
afterHighlight: "after highlight",
|
|
17
|
+
beforeElementsAdded: "before elements added",
|
|
18
|
+
afterElementsAdded: "after elements added",
|
|
19
|
+
attributeChanged: (name, oldValue, newValue) => `${name}: '${oldValue}'>'${newValue}'`
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
constructor(instructionTranslations = {}) {
|
|
13
23
|
super(["testattr"]);
|
|
14
24
|
// Array of observed attributes as parameter
|
|
25
|
+
|
|
26
|
+
// instructionTranslations, instructions, and the addTranslations
|
|
27
|
+
// call need not be present if this plugin uses no localisable
|
|
28
|
+
// text.
|
|
29
|
+
this.addTranslations(this.instructions, instructionTranslations);
|
|
15
30
|
}
|
|
16
31
|
/* Runs before code is highlighted; Params: codeInput element) */
|
|
17
32
|
beforeHighlight(codeInput) {
|
|
18
|
-
console.log(codeInput,
|
|
33
|
+
console.log(codeInput, this.instructions.beforeHighlight);
|
|
19
34
|
}
|
|
20
35
|
/* Runs after code is highlighted; Params: codeInput element) */
|
|
21
36
|
afterHighlight(codeInput) {
|
|
22
|
-
console.log(codeInput,
|
|
37
|
+
console.log(codeInput, this.instructions.afterHighlight);
|
|
23
38
|
}
|
|
24
39
|
/* Runs before elements are added into a `code-input`; Params: codeInput element) */
|
|
25
40
|
beforeElementsAdded(codeInput) {
|
|
26
|
-
console.log(codeInput,
|
|
41
|
+
console.log(codeInput, this.instructions.beforeElementsAdded);
|
|
27
42
|
}
|
|
28
43
|
/* Runs after elements are added into a `code-input` (useful for adding events to the textarea); Params: codeInput element) */
|
|
29
44
|
afterElementsAdded(codeInput) {
|
|
30
|
-
console.log(codeInput,
|
|
45
|
+
console.log(codeInput, this.instructions.afterElementsAdded);
|
|
31
46
|
}
|
|
32
47
|
/* Runs when an observed attribute of a `code-input` is changed (you must add the attribute name in the constructor); Params: codeInput element, name attribute name, oldValue previous value of attribute, newValue changed value of attribute) */
|
|
33
48
|
attributeChanged(codeInput, name, oldValue, newValue) {
|
|
34
|
-
console.log(codeInput, name,
|
|
49
|
+
console.log(codeInput, this.instructions.attriibuteChanged(name, oldValue, newValue));
|
|
35
50
|
}
|
|
36
|
-
}
|
|
51
|
+
}
|
package/plugins/test.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
codeInput.plugins.Test=class extends codeInput.Plugin{constructor(){super(["testattr"])}beforeHighlight(a){console.log(a,
|
|
1
|
+
"use strict";codeInput.plugins.Test=class extends codeInput.Plugin{instructions={beforeHighlight:"before highlight",afterHighlight:"after highlight",beforeElementsAdded:"before elements added",afterElementsAdded:"after elements added",attributeChanged:(a,b,c)=>`${a}: '${b}'>'${c}'`};constructor(a={}){super(["testattr"]),this.addTranslations(this.instructions,a)}beforeHighlight(a){console.log(a,this.instructions.beforeHighlight)}afterHighlight(a){console.log(a,this.instructions.afterHighlight)}beforeElementsAdded(a){console.log(a,this.instructions.beforeElementsAdded)}afterElementsAdded(a){console.log(a,this.instructions.afterElementsAdded)}attributeChanged(a,b,c,d){console.log(a,this.instructions.attriibuteChanged(b,c,d))}};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
name: Auto-minify
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- main
|
|
6
|
-
jobs:
|
|
7
|
-
Minify:
|
|
8
|
-
runs-on: ubuntu-latest
|
|
9
|
-
steps:
|
|
10
|
-
# Checks-out your repository under $GITHUB_WORKSPACE, so auto-minify job can access it
|
|
11
|
-
- uses: actions/checkout@v2
|
|
12
|
-
|
|
13
|
-
- name: Auto Minify
|
|
14
|
-
uses: nizarmah/auto-minify@v2.1
|
|
15
|
-
|
|
16
|
-
# Auto commits minified files to the repository
|
|
17
|
-
# Ignore it if you don't want to commit the files to the repository
|
|
18
|
-
- name: Auto committing minified files
|
|
19
|
-
uses: stefanzweifel/git-auto-commit-action@v4
|
|
20
|
-
with:
|
|
21
|
-
commit_message: "Auto Minified JS and CSS files"
|
|
22
|
-
branch: ${{ github.ref }}
|