@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/.github/workflows/minify.yml +21 -21
- package/.github/workflows/npm-publish.yml +21 -0
- package/LICENSE +21 -21
- package/README.md +112 -115
- package/code-input.css +100 -100
- package/code-input.js +759 -422
- package/code-input.min.js +1 -1
- package/package.json +1 -1
- package/plugins/README.md +68 -68
- package/plugins/autocomplete.css +14 -14
- package/plugins/autocomplete.js +79 -79
- package/plugins/autodetect.js +28 -28
- package/plugins/debounce-update.js +40 -40
- package/plugins/indent.js +153 -153
- package/plugins/indent.min.js +1 -1
- package/plugins/prism-line-numbers.css +19 -19
- package/plugins/special-chars.css +97 -97
- package/plugins/special-chars.js +218 -218
- package/plugins/special-chars.min.css +4 -4
- package/plugins/test.js +37 -37
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
|
}
|
package/plugins/indent.min.js
CHANGED
|
@@ -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
|
|
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
|
}
|