@webcoder49/code-input 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/plugins/indent.js CHANGED
@@ -1,154 +1,154 @@
1
- /**
2
- * Adds indentation using the `Tab` key, and auto-indents after a newline, as well as making it
3
- * possible to indent/unindent multiple lines using Tab/Shift+Tab
4
- * Files: indent.js
5
- */
6
- codeInput.plugins.Indent = class extends codeInput.Plugin {
7
- constructor() {
8
- super();
9
- }
10
-
11
- /* Add keystroke events */
12
- afterElementsAdded(codeInput) {
13
- let textarea = codeInput.querySelector("textarea");
14
- textarea.addEventListener('keydown', (event) => { this.check_tab(codeInput, event); this.check_enter(codeInput, event); });
15
- }
16
-
17
- /* Event handlers */
18
- check_tab(codeInput, event) {
19
- if(event.key != "Tab") {
20
- return;
21
- }
22
- let input_element = codeInput.querySelector("textarea");
23
- let code = input_element.value;
24
- event.preventDefault(); // stop normal
25
-
26
- if(!event.shiftKey && input_element.selectionStart == input_element.selectionEnd) {
27
- // Just place a tab here.
28
- document.execCommand("insertText", false, "\t");
29
-
30
- } else {
31
- let lines = input_element.value.split("\n");
32
- let letter_i = 0;
33
-
34
- let selection_start = input_element.selectionStart; // where cursor moves after tab - moving forward by 1 indent
35
- let selection_end = input_element.selectionEnd; // where cursor moves after tab - moving forward by 1 indent
36
-
37
- let number_indents = 0;
38
- let first_line_indents = 0;
39
-
40
- for (let i = 0; i < lines.length; i++) {
41
- // console.log(lines[i], ": start", selection_start, letter_i + lines[i].length + 1, "&& end", selection_end , letter_i + 1)
42
- if((selection_start <= letter_i+lines[i].length && selection_end >= letter_i + 1)
43
- || (selection_start == selection_end && selection_start <= letter_i+lines[i].length+1 && selection_end >= letter_i)) { // + 1 so newlines counted
44
- // Starts before or at last char and ends after or at first char
45
- if(event.shiftKey) {
46
- if(lines[i][0] == "\t") {
47
- // Remove first tab
48
- input_element.selectionStart = letter_i;
49
- input_element.selectionEnd = letter_i+1;
50
- document.execCommand("delete", false, "");
51
-
52
- // Change selection
53
- if(selection_start > letter_i) { // Indented outside selection
54
- selection_start--;
55
- }
56
- selection_end--;
57
- letter_i--;
58
- }
59
- } else {
60
- // Add tab at start
61
- input_element.selectionStart = letter_i;
62
- input_element.selectionEnd = letter_i;
63
- document.execCommand("insertText", false, "\t");
64
-
65
- // Change selection
66
- if(selection_start > letter_i) { // Indented outside selection
67
- selection_start++;
68
- }
69
- selection_end++;
70
- letter_i++;
71
- }
72
- }
73
-
74
- letter_i += lines[i].length+1; // newline counted
75
- }
76
- // input_element.value = lines.join("\n");
77
-
78
- // move cursor
79
- input_element.selectionStart = selection_start;
80
- input_element.selectionEnd = selection_end;
81
- }
82
-
83
- codeInput.update(input_element.value);
84
- }
85
-
86
- check_enter(codeInput, event) {
87
- if(event.key != "Enter") {
88
- return;
89
- }
90
- event.preventDefault(); // stop normal
91
-
92
- let input_element = codeInput.querySelector("textarea");
93
- let lines = input_element.value.split("\n");
94
- let letter_i = 0;
95
- let current_line = lines.length - 1;
96
- let new_line = "";
97
- let number_indents = 0;
98
-
99
- // find the index of the line our cursor is currently on
100
- for (let i = 0; i < lines.length; i++) {
101
- letter_i += lines[i].length + 1;
102
- if(input_element.selectionEnd <= letter_i) {
103
- current_line = i;
104
- break;
105
- }
106
- }
107
-
108
- // count the number of indents the current line starts with (up to our cursor position in the line)
109
- let cursor_pos_in_line = lines[current_line].length - (letter_i - input_element.selectionEnd) + 1;
110
- for (let i = 0; i < cursor_pos_in_line; i++) {
111
- if (lines[current_line][i] == "\t") {
112
- number_indents++;
113
- } else {
114
- break;
115
- }
116
- }
117
-
118
- // determine the text before and after the cursor and chop the current line at the new line break
119
- let text_after_cursor = "";
120
- if (cursor_pos_in_line != lines[current_line].length) {
121
- text_after_cursor = lines[current_line].substring(cursor_pos_in_line);
122
- lines[current_line] = lines[current_line].substring(0, cursor_pos_in_line);
123
- }
124
-
125
- // insert our indents and any text from the previous line that might have been after the line break
126
- for (let i = 0; i < number_indents; i++) {
127
- new_line += "\t";
128
- }
129
-
130
- // save the current cursor position
131
- let selection_start = input_element.selectionStart;
132
- let selection_end = input_element.selectionEnd;
133
-
134
- document.execCommand("insertText", false, "\n" + new_line); // Write new line, including auto-indentation
135
-
136
- // move cursor to new position
137
- input_element.selectionStart = selection_start + number_indents + 1; // count the indent level and the newline character
138
- input_element.selectionEnd = selection_start + number_indents + 1;
139
-
140
- codeInput.update(input_element.value);
141
-
142
-
143
- // Update scrolls
144
- input_element.scrollLeft = 0;
145
- // Move down 1 line
146
- let lineHeight = Number(getComputedStyle(input_element).lineHeight.split(0, -2));
147
- // console.log(getComputedStyle(input_element).lineHeight);
148
- if(lineHeight == NaN && getComputedStyle(input_element).lineHeight.split(-2) == "px") {
149
- input_element.scrollTop += lineHeight;
150
- } else {
151
- input_element.scrollTop += 20; // px
152
- }
153
- }
1
+ /**
2
+ * Adds indentation using the `Tab` key, and auto-indents after a newline, as well as making it
3
+ * possible to indent/unindent multiple lines using Tab/Shift+Tab
4
+ * Files: indent.js
5
+ */
6
+ codeInput.plugins.Indent = class extends codeInput.Plugin {
7
+ constructor() {
8
+ super();
9
+ }
10
+
11
+ /* Add keystroke events */
12
+ afterElementsAdded(codeInput) {
13
+ let textarea = codeInput.querySelector("textarea");
14
+ textarea.addEventListener('keydown', (event) => { this.check_tab(codeInput, event); this.check_enter(codeInput, event); });
15
+ }
16
+
17
+ /* Event handlers */
18
+ check_tab(codeInput, event) {
19
+ if(event.key != "Tab") {
20
+ return;
21
+ }
22
+ let input_element = codeInput.querySelector("textarea");
23
+ let code = input_element.value;
24
+ event.preventDefault(); // stop normal
25
+
26
+ if(!event.shiftKey && input_element.selectionStart == input_element.selectionEnd) {
27
+ // Just place a tab here.
28
+ document.execCommand("insertText", false, "\t");
29
+
30
+ } else {
31
+ let lines = input_element.value.split("\n");
32
+ let letter_i = 0;
33
+
34
+ let selection_start = input_element.selectionStart; // where cursor moves after tab - moving forward by 1 indent
35
+ let selection_end = input_element.selectionEnd; // where cursor moves after tab - moving forward by 1 indent
36
+
37
+ let number_indents = 0;
38
+ let first_line_indents = 0;
39
+
40
+ for (let i = 0; i < lines.length; i++) {
41
+ // console.log(lines[i], ": start", selection_start, letter_i + lines[i].length + 1, "&& end", selection_end , letter_i + 1)
42
+ if((selection_start <= letter_i+lines[i].length && selection_end >= letter_i + 1)
43
+ || (selection_start == selection_end && selection_start <= letter_i+lines[i].length+1 && selection_end >= letter_i)) { // + 1 so newlines counted
44
+ // Starts before or at last char and ends after or at first char
45
+ if(event.shiftKey) {
46
+ if(lines[i][0] == "\t") {
47
+ // Remove first tab
48
+ input_element.selectionStart = letter_i;
49
+ input_element.selectionEnd = letter_i+1;
50
+ document.execCommand("delete", false, "");
51
+
52
+ // Change selection
53
+ if(selection_start > letter_i) { // Indented outside selection
54
+ selection_start--;
55
+ }
56
+ selection_end--;
57
+ letter_i--;
58
+ }
59
+ } else {
60
+ // Add tab at start
61
+ input_element.selectionStart = letter_i;
62
+ input_element.selectionEnd = letter_i;
63
+ document.execCommand("insertText", false, "\t");
64
+
65
+ // Change selection
66
+ if(selection_start > letter_i) { // Indented outside selection
67
+ selection_start++;
68
+ }
69
+ selection_end++;
70
+ letter_i++;
71
+ }
72
+ }
73
+
74
+ letter_i += lines[i].length+1; // newline counted
75
+ }
76
+ // input_element.value = lines.join("\n");
77
+
78
+ // move cursor
79
+ input_element.selectionStart = selection_start;
80
+ input_element.selectionEnd = selection_end;
81
+ }
82
+
83
+ codeInput.update(input_element.value);
84
+ }
85
+
86
+ check_enter(codeInput, event) {
87
+ if(event.key != "Enter") {
88
+ return;
89
+ }
90
+ event.preventDefault(); // stop normal
91
+
92
+ let input_element = codeInput.querySelector("textarea");
93
+ let lines = input_element.value.split("\n");
94
+ let letter_i = 0;
95
+ let current_line = lines.length - 1;
96
+ let new_line = "";
97
+ let number_indents = 0;
98
+
99
+ // find the index of the line our cursor is currently on
100
+ for (let i = 0; i < lines.length; i++) {
101
+ letter_i += lines[i].length + 1;
102
+ if(input_element.selectionEnd <= letter_i) {
103
+ current_line = i;
104
+ break;
105
+ }
106
+ }
107
+
108
+ // count the number of indents the current line starts with (up to our cursor position in the line)
109
+ let cursor_pos_in_line = lines[current_line].length - (letter_i - input_element.selectionEnd) + 1;
110
+ for (let i = 0; i < cursor_pos_in_line; i++) {
111
+ if (lines[current_line][i] == "\t") {
112
+ number_indents++;
113
+ } else {
114
+ break;
115
+ }
116
+ }
117
+
118
+ // determine the text before and after the cursor and chop the current line at the new line break
119
+ let text_after_cursor = "";
120
+ if (cursor_pos_in_line != lines[current_line].length) {
121
+ text_after_cursor = lines[current_line].substring(cursor_pos_in_line);
122
+ lines[current_line] = lines[current_line].substring(0, cursor_pos_in_line);
123
+ }
124
+
125
+ // insert our indents and any text from the previous line that might have been after the line break
126
+ for (let i = 0; i < number_indents; i++) {
127
+ new_line += "\t";
128
+ }
129
+
130
+ // save the current cursor position
131
+ let selection_start = input_element.selectionStart;
132
+ let selection_end = input_element.selectionEnd;
133
+
134
+ document.execCommand("insertText", false, "\n" + new_line); // Write new line, including auto-indentation
135
+
136
+ // move cursor to new position
137
+ input_element.selectionStart = selection_start + number_indents + 1; // count the indent level and the newline character
138
+ input_element.selectionEnd = selection_start + number_indents + 1;
139
+
140
+ codeInput.update(input_element.value);
141
+
142
+
143
+ // Update scrolls
144
+ input_element.scrollLeft = 0;
145
+ // Move down 1 line
146
+ let lineHeight = Number(getComputedStyle(input_element).lineHeight.split(0, -2));
147
+ // console.log(getComputedStyle(input_element).lineHeight);
148
+ if(lineHeight == NaN && getComputedStyle(input_element).lineHeight.split(-2) == "px") {
149
+ input_element.scrollTop += lineHeight;
150
+ } else {
151
+ input_element.scrollTop += 20; // px
152
+ }
153
+ }
154
154
  }
@@ -1 +1 @@
1
- codeInput.plugins.Indent=class extends codeInput.Plugin{constructor(){super()}afterElementsAdded(a){let b=a.querySelector("textarea");b.addEventListener("keydown",b=>{this.check_tab(a,b),this.check_enter(a,b)})}check_tab(a,b){if("Tab"!=b.key)return;let c=a.querySelector("textarea"),d=c.value;if(b.preventDefault(),!b.shiftKey&&c.selectionStart==c.selectionEnd)document.execCommand("insertText",!1,"\t");else{let a=c.value.split("\n"),d=0,e=c.selectionStart,f=c.selectionEnd;for(let g=0;g<a.length;g++)(e<=d+a[g].length&&f>=d+1||e==f&&e<=d+a[g].length+1&&f>=d)&&(b.shiftKey?"\t"==a[g][0]&&(c.selectionStart=d,c.selectionEnd=d+1,document.execCommand("delete",!1,""),e>d&&e--,f--,d--):(c.selectionStart=d,c.selectionEnd=d,document.execCommand("insertText",!1,"\t"),e>d&&e++,f++,d++)),d+=a[g].length+1;c.selectionStart=e,c.selectionEnd=f}a.update(c.value)}check_enter(a,b){if("Enter"!=b.key)return;b.preventDefault();let c=a.querySelector("textarea"),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&&"\t"==d[f][c];c++)h++;let k="";j!=d[f].length&&(k=d[f].substring(j),d[f]=d[f].substring(0,j));for(let c=0;c<h;c++)g+="\t";let l=c.selectionStart;document.execCommand("insertText",!1,"\n"+g),c.selectionStart=l+h+1,c.selectionEnd=l+h+1,a.update(c.value),c.scrollLeft=0;let m=+getComputedStyle(c).lineHeight.split(0,-2);c.scrollTop+=m==NaN&&"px"==getComputedStyle(c).lineHeight.split(-2)?m:20}};
1
+ codeInput.plugins.Indent=class extends codeInput.Plugin{constructor(){super()}afterElementsAdded(a){let b=a.querySelector("textarea");b.addEventListener("keydown",b=>{this.check_tab(a,b),this.check_enter(a,b)})}check_tab(a,b){if("Tab"!=b.key)return;let c=a.querySelector("textarea"),d=c.value;if(b.preventDefault(),!b.shiftKey&&c.selectionStart==c.selectionEnd)document.execCommand("insertText",!1,"\t");else{let a=c.value.split("\n"),d=0,e=c.selectionStart,f=c.selectionEnd;for(let g=0;g<a.length;g++)(e<=d+a[g].length&&f>=d+1||e==f&&e<=d+a[g].length+1&&f>=d)&&(b.shiftKey?"\t"==a[g][0]&&(c.selectionStart=d,c.selectionEnd=d+1,document.execCommand("delete",!1,""),e>d&&e--,f--,d--):(c.selectionStart=d,c.selectionEnd=d,document.execCommand("insertText",!1,"\t"),e>d&&e++,f++,d++)),d+=a[g].length+1;c.selectionStart=e,c.selectionEnd=f}a.update(c.value)}check_enter(a,b){if("Enter"!=b.key)return;b.preventDefault();let c=a.querySelector("textarea"),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&&"\t"==d[f][c];c++)h++;let k="";j!=d[f].length&&(k=d[f].substring(j),d[f]=d[f].substring(0,j));for(let c=0;c<h;c++)g+="\t";let l=c.selectionStart,m=c.selectionEnd;document.execCommand("insertText",!1,"\n"+g),c.selectionStart=l+h+1,c.selectionEnd=l+h+1,a.update(c.value),c.scrollLeft=0;let n=+getComputedStyle(c).lineHeight.split(0,-2);c.scrollTop+=n==NaN&&"px"==getComputedStyle(c).lineHeight.split(-2)?n:20}};
@@ -1,20 +1,20 @@
1
- /**
2
- * Allows code-input elements to be used with the Prism.js line-numbers plugin, as long as the code-input element
3
- * or a parent element of it has the CSS class `line-numbers`.
4
- * https://prismjs.com/plugins/line-numbers/
5
- * Files: prism-line-numbers.css
6
- */
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 {
10
- padding-top: 1em!important;
11
- padding-bottom: 1em!important;
12
- padding-right: 1em!important;
13
- padding-left: 3.8em!important;
14
- }
15
-
16
- /* Remove unnecessary, interfering padding values */
17
- code-input.line-numbers, code-input.line-numbers.code-input_pre-element-styled code,
18
- .line-numbers code-input, .line-numbers code-input.code-input_pre-element-styled code{
19
- padding: 0;
1
+ /**
2
+ * Allows code-input elements to be used with the Prism.js line-numbers plugin, as long as the code-input element
3
+ * or a parent element of it has the CSS class `line-numbers`.
4
+ * https://prismjs.com/plugins/line-numbers/
5
+ * Files: prism-line-numbers.css
6
+ */
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 {
10
+ padding-top: 1em!important;
11
+ padding-bottom: 1em!important;
12
+ padding-right: 1em!important;
13
+ padding-left: 3.8em!important;
14
+ }
15
+
16
+ /* Remove unnecessary, interfering padding values */
17
+ code-input.line-numbers, code-input.line-numbers.code-input_pre-element-styled code,
18
+ .line-numbers code-input, .line-numbers code-input.code-input_pre-element-styled code{
19
+ padding: 0;
20
20
  }
@@ -1,98 +1,98 @@
1
- /**
2
- * Render special characters and control characters as a symbol with their hex code.
3
- * Files: special-chars.js, special-chars.css
4
- */
5
-
6
- /* Main styling */
7
-
8
- :root, body { /* Font for hex chars */
9
- --code-input_special-chars_0: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdjZGBgYPj///9/RhCAMcA0bg6yHgAPmh/6BoxTcQAAAABJRU5ErkJgggAA');
10
- --code-input_special-chars_1: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdjZGBgYPj///9/RhAggwMAitIUBr9U6sYAAAAASUVORK5CYII=');
11
- --code-input_special-chars_2: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGCEMUCCjCgyYBFGRrAKFBkAuLYT9kYcIu0AAAAASUVORK5CYII=');
12
- --code-input_special-chars_3: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABhJREFUGFdj/P///38GKGCEMUCCjMTJAACYiBPyG8sfAgAAAABJRU5ErkJggg==');
13
- --code-input_special-chars_4: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///39GRkZGMI3BYYACRhgDrAKZAwAYxhvyz0DRIQAAAABJRU5ErkJggg==');
14
- --code-input_special-chars_5: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACJJREFUGFdj/P///38GKGAEcRgZGRlBfDAHLgNjgFUgywAAuR4T9hxJl2YAAAAASUVORK5CYII=');
15
- --code-input_special-chars_6: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdj/P///38GKGAEcRgZGRlBfDAHQwasAlkGABcdF/Y4yco2AAAAAElFTkSuQmCC');
16
- --code-input_special-chars_7: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdj/P///38GKGCEMUCCRHIAWMgT8kue3bQAAAAASUVORK5CYII=');
17
- --code-input_special-chars_8: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GKGAEcRgZGSE0cTIAvHcb8v+mIfAAAAAASUVORK5CYII=');
18
- --code-input_special-chars_9: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGAEcRgZGSE0igxMCVgGmQMAPqcX8hWL1K0AAAAASUVORK5CYII=');
19
- --code-input_special-chars_A: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdjZGBgYPj///9/RhCAMcA0iADJggCmDEw5ALdxH/aGuYHqAAAAAElFTkSuQmCC');
20
- --code-input_special-chars_B: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GBgYGRhAAceA0cTIAvc0b/vRDnVoAAAAASUVORK5CYII=');
21
- --code-input_special-chars_C: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdjZGBgYPj///9/EM0IYjAyMjIS4CDrAQC57hP+uLwvFQAAAABJRU5ErkJggg==');
22
- --code-input_special-chars_D: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdj/P///38GBgYGRhAAceA0fg5MDwAveh/6ToN9VwAAAABJRU5ErkJggg==');
23
- --code-input_special-chars_E: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABxJREFUGFdj/P///38GKGAEcRgZGRlBfDCHsAwA2UwT+mVIH1MAAAAASUVORK5CYII=');
24
- --code-input_special-chars_F: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///38GKGAEcRgZGRlBfDAHtwxMGQDZZhP+BnB1kwAAAABJRU5ErkJggg==');
25
- }
26
-
27
- .code-input_special-char_container { /* pre element */
28
- font-size: 20px;
29
- }
30
-
31
- .code-input_special-char {
32
- display: inline-block;
33
- position: relative;
34
- top: 0;
35
- left: 0;
36
- height: 1em;
37
- /* width: set by JS */
38
- overflow: hidden;
39
- text-decoration: none;
40
- text-shadow: none;
41
- vertical-align: middle;
42
- outline: 0.1px solid currentColor;
43
-
44
- --hex-0: var(
45
- --code-input_special-chars_0);
46
- --hex-1: var(
47
- --code-input_special-chars_0);
48
- --hex-2: var(
49
- --code-input_special-chars_0);
50
- --hex-3: var(
51
- --code-input_special-chars_0);
52
- }
53
-
54
- /* Default - Two bytes - 4 hex chars */
55
-
56
- .code-input_special-char::before {
57
- margin-left: 50%;
58
- transform: translate(-50%, 0);
59
- content: " ";
60
-
61
- background-color: var(--code-input_special-char_color, currentColor);
62
- image-rendering: pixelated;
63
- display: inline-block;
64
- width: calc(100%-2px);
65
- height: 100%;
66
-
67
- mask-image: var(--hex-0), var(--hex-1), var(--hex-2), var(--hex-3);
68
- mask-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
69
- mask-size: 40%, 40%, 40%, 40%;
70
- mask-position: 10% 10%, 90% 10%, 10% 90%, 90% 90%;
71
-
72
- -webkit-mask-image: var(--hex-0), var(--hex-1), var(--hex-2), var(--hex-3);
73
- -webkit-mask-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
74
- -webkit-mask-size: min(40%, 0.25em), min(40%, 0.25em), min(40%, 0.25em), min(40%, 0.25em);
75
- -webkit-mask-position: 10% 10%, min(90%, 0.5em) 10%, 10% 90%, min(90%, 0.5em) 90%;
76
- }
77
-
78
- .code-input_special-char_zero-width {
79
- z-index: 1;
80
- width: 1em;
81
- margin-left: -0.5em;
82
- margin-right: -0.5em;
83
- position: relative;
84
-
85
- opacity: 0.75;
86
- }
87
-
88
- /* One byte - 2 hex chars */
89
- .code-input_special-char_one-byte::before {
90
- height: 1.5em;
91
- top: -1em;
92
- content: attr(data-hex2);
93
- }
94
- .code-input_special-char_one-byte::after {
95
- height: 1.5em;
96
- bottom: -1em;
97
- content: attr(data-hex3);
1
+ /**
2
+ * Render special characters and control characters as a symbol with their hex code.
3
+ * Files: special-chars.js, special-chars.css
4
+ */
5
+
6
+ /* Main styling */
7
+
8
+ :root, body { /* Font for hex chars */
9
+ --code-input_special-chars_0: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdjZGBgYPj///9/RhCAMcA0bg6yHgAPmh/6BoxTcQAAAABJRU5ErkJgggAA');
10
+ --code-input_special-chars_1: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdjZGBgYPj///9/RhAggwMAitIUBr9U6sYAAAAASUVORK5CYII=');
11
+ --code-input_special-chars_2: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGCEMUCCjCgyYBFGRrAKFBkAuLYT9kYcIu0AAAAASUVORK5CYII=');
12
+ --code-input_special-chars_3: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABhJREFUGFdj/P///38GKGCEMUCCjMTJAACYiBPyG8sfAgAAAABJRU5ErkJggg==');
13
+ --code-input_special-chars_4: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///39GRkZGMI3BYYACRhgDrAKZAwAYxhvyz0DRIQAAAABJRU5ErkJggg==');
14
+ --code-input_special-chars_5: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACJJREFUGFdj/P///38GKGAEcRgZGRlBfDAHLgNjgFUgywAAuR4T9hxJl2YAAAAASUVORK5CYII=');
15
+ --code-input_special-chars_6: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdj/P///38GKGAEcRgZGRlBfDAHQwasAlkGABcdF/Y4yco2AAAAAElFTkSuQmCC');
16
+ --code-input_special-chars_7: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABZJREFUGFdj/P///38GKGCEMUCCRHIAWMgT8kue3bQAAAAASUVORK5CYII=');
17
+ --code-input_special-chars_8: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GKGAEcRgZGSE0cTIAvHcb8v+mIfAAAAAASUVORK5CYII=');
18
+ --code-input_special-chars_9: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB9JREFUGFdj/P///38GKGAEcRgZGSE0igxMCVgGmQMAPqcX8hWL1K0AAAAASUVORK5CYII=');
19
+ --code-input_special-chars_A: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAACBJREFUGFdjZGBgYPj///9/RhCAMcA0iADJggCmDEw5ALdxH/aGuYHqAAAAAElFTkSuQmCC');
20
+ --code-input_special-chars_B: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABlJREFUGFdj/P///38GBgYGRhAAceA0cTIAvc0b/vRDnVoAAAAASUVORK5CYII=');
21
+ --code-input_special-chars_C: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdjZGBgYPj///9/EM0IYjAyMjIS4CDrAQC57hP+uLwvFQAAAABJRU5ErkJggg==');
22
+ --code-input_special-chars_D: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABtJREFUGFdj/P///38GBgYGRhAAceA0fg5MDwAveh/6ToN9VwAAAABJRU5ErkJggg==');
23
+ --code-input_special-chars_E: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAABxJREFUGFdj/P///38GKGAEcRgZGRlBfDCHsAwA2UwT+mVIH1MAAAAASUVORK5CYII=');
24
+ --code-input_special-chars_F: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///38GKGAEcRgZGRlBfDAHtwxMGQDZZhP+BnB1kwAAAABJRU5ErkJggg==');
25
+ }
26
+
27
+ .code-input_special-char_container { /* pre element */
28
+ font-size: 20px;
29
+ }
30
+
31
+ .code-input_special-char {
32
+ display: inline-block;
33
+ position: relative;
34
+ top: 0;
35
+ left: 0;
36
+ height: 1em;
37
+ /* width: set by JS */
38
+ overflow: hidden;
39
+ text-decoration: none;
40
+ text-shadow: none;
41
+ vertical-align: middle;
42
+ outline: 0.1px solid currentColor;
43
+
44
+ --hex-0: var(
45
+ --code-input_special-chars_0);
46
+ --hex-1: var(
47
+ --code-input_special-chars_0);
48
+ --hex-2: var(
49
+ --code-input_special-chars_0);
50
+ --hex-3: var(
51
+ --code-input_special-chars_0);
52
+ }
53
+
54
+ /* Default - Two bytes - 4 hex chars */
55
+
56
+ .code-input_special-char::before {
57
+ margin-left: 50%;
58
+ transform: translate(-50%, 0);
59
+ content: " ";
60
+
61
+ background-color: var(--code-input_special-char_color, currentColor);
62
+ image-rendering: pixelated;
63
+ display: inline-block;
64
+ width: calc(100%-2px);
65
+ height: 100%;
66
+
67
+ mask-image: var(--hex-0), var(--hex-1), var(--hex-2), var(--hex-3);
68
+ mask-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
69
+ mask-size: 40%, 40%, 40%, 40%;
70
+ mask-position: 10% 10%, 90% 10%, 10% 90%, 90% 90%;
71
+
72
+ -webkit-mask-image: var(--hex-0), var(--hex-1), var(--hex-2), var(--hex-3);
73
+ -webkit-mask-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
74
+ -webkit-mask-size: min(40%, 0.25em), min(40%, 0.25em), min(40%, 0.25em), min(40%, 0.25em);
75
+ -webkit-mask-position: 10% 10%, min(90%, 0.5em) 10%, 10% 90%, min(90%, 0.5em) 90%;
76
+ }
77
+
78
+ .code-input_special-char_zero-width {
79
+ z-index: 1;
80
+ width: 1em;
81
+ margin-left: -0.5em;
82
+ margin-right: -0.5em;
83
+ position: relative;
84
+
85
+ opacity: 0.75;
86
+ }
87
+
88
+ /* One byte - 2 hex chars */
89
+ .code-input_special-char_one-byte::before {
90
+ height: 1.5em;
91
+ top: -1em;
92
+ content: attr(data-hex2);
93
+ }
94
+ .code-input_special-char_one-byte::after {
95
+ height: 1.5em;
96
+ bottom: -1em;
97
+ content: attr(data-hex3);
98
98
  }