@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.
@@ -1,219 +1,219 @@
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
- // INCOMPLETE: TODO Optimise regex - compile at start; Update CSS for character display; clean up + comment
7
-
8
- codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
9
- specialCharRegExp;
10
-
11
- cachedColors; // ascii number > [background color, text color]
12
- cachedWidths; // font > {character > character width}
13
- canvasContext;
14
-
15
- /**
16
- * Create a special characters plugin instance
17
- * @param {Boolean} colorInSpecialChars Whether or not to give special characters custom background colors based on their hex code
18
- * @param {Boolean} inheritTextColor If `colorInSpecialChars` is false, forces the color of the hex code to inherit from syntax highlighting. Otherwise, the base colour of the `pre code` element is used to give contrast to the small characters.
19
- * @param {RegExp} specialCharRegExp The regular expression which matches special characters
20
- */
21
- 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
22
- super();
23
-
24
- this.specialCharRegExp = specialCharRegExp;
25
- this.colorInSpecialChars = colorInSpecialChars;
26
- this.inheritTextColor = inheritTextColor;
27
-
28
- this.cachedColors = {};
29
- this.cachedWidths = {};
30
-
31
- let canvas = document.createElement("canvas");
32
- this.canvasContext = canvas.getContext("2d");
33
- }
34
-
35
- /* Runs before elements are added into a `code-input`; Params: codeInput element) */
36
- beforeElementsAdded(codeInput) {
37
- codeInput.classList.add("code-input_special-char_container");
38
- }
39
-
40
- /* Runs after elements are added into a `code-input` (useful for adding events to the textarea); Params: codeInput element) */
41
- afterElementsAdded(codeInput) {
42
- // For some reason, special chars aren't synced the first time - TODO is there a cleaner way to do this?
43
- setTimeout(() => { codeInput.update(codeInput.value); }, 100);
44
- }
45
-
46
- /* Runs after code is highlighted; Params: codeInput element) */
47
- afterHighlight(codeInput) {
48
- let result_element = codeInput.querySelector("pre code");
49
-
50
- // Reset data each highlight so can change if font size, etc. changes
51
- codeInput.pluginData.specialChars = {};
52
- codeInput.pluginData.specialChars.textarea = codeInput.getElementsByTagName("textarea")[0];
53
- codeInput.pluginData.specialChars.contrastColor = window.getComputedStyle(result_element).color;
54
-
55
- this.recursivelyReplaceText(codeInput, result_element);
56
-
57
- this.lastFont = window.getComputedStyle(codeInput.pluginData.specialChars.textarea).font;
58
- }
59
-
60
- recursivelyReplaceText(codeInput, element) {
61
- for(let i = 0; i < element.childNodes.length; i++) {
62
-
63
- let nextNode = element.childNodes[i];
64
- if(nextNode.nodeName == "#text" && nextNode.nodeValue != "") {
65
- // Replace in here
66
- let oldValue = nextNode.nodeValue;
67
-
68
- this.specialCharRegExp.lastIndex = 0;
69
- let searchResult = this.specialCharRegExp.exec(oldValue);
70
- if(searchResult != null) {
71
- let charIndex = searchResult.index; // Start as returns end
72
-
73
- nextNode = nextNode.splitText(charIndex+1).previousSibling;
74
-
75
- if(charIndex > 0) {
76
- nextNode = nextNode.splitText(charIndex); // Keep those before in difft. span
77
- }
78
-
79
- if(nextNode.textContent != "") {
80
- let replacementElement = this.specialCharReplacer(codeInput, nextNode.textContent);
81
- nextNode.parentNode.insertBefore(replacementElement, nextNode);
82
- nextNode.textContent = "";
83
- }
84
- }
85
- } else if(nextNode.nodeType == 1) {
86
- if(nextNode.className != "code-input_special-char" && nextNode.nodeValue != "") {
87
- // Element - recurse
88
- this.recursivelyReplaceText(codeInput, nextNode);
89
- }
90
- }
91
- }
92
- }
93
-
94
- specialCharReplacer(codeInput, match_char) {
95
- let hex_code = match_char.codePointAt(0);
96
-
97
- let colors;
98
- if(this.colorInSpecialChars) colors = this.getCharacterColor(hex_code);
99
-
100
- hex_code = hex_code.toString(16);
101
- hex_code = ("0000" + hex_code).substring(hex_code.length); // So 2 chars with leading 0
102
- hex_code = hex_code.toUpperCase();
103
-
104
- let char_width = this.getCharacterWidth(codeInput, match_char);
105
-
106
- // Create element with hex code
107
- let result = document.createElement("span");
108
- result.classList.add("code-input_special-char");
109
- result.style.setProperty("--hex-0", "var(--code-input_special-chars_" + hex_code[0] + ")");
110
- result.style.setProperty("--hex-1", "var(--code-input_special-chars_" + hex_code[1] + ")");
111
- result.style.setProperty("--hex-2", "var(--code-input_special-chars_" + hex_code[2] + ")");
112
- result.style.setProperty("--hex-3", "var(--code-input_special-chars_" + hex_code[3] + ")");
113
-
114
- // Handle zero-width chars
115
- if(char_width == 0) result.classList.add("code-input_special-char_zero-width");
116
- else result.style.width = char_width + "px";
117
-
118
- if(this.colorInSpecialChars) {
119
- result.style.backgroundColor = "#" + colors[0];
120
- result.style.setProperty("--code-input_special-char_color", colors[1]);
121
- } else if(!this.inheritTextColor) {
122
- result.style.setProperty("--code-input_special-char_color", codeInput.pluginData.specialChars.contrastColor);
123
- }
124
- return result;
125
- }
126
-
127
- getCharacterColor(ascii_code) {
128
- // Choose colors based on character code - lazy load and return [background color, text color]
129
- let background_color;
130
- let text_color;
131
- if(!(ascii_code in this.cachedColors)) {
132
- // Get background color - arbitrary bit manipulation to get a good range of colours
133
- background_color = ascii_code^(ascii_code << 3)^(ascii_code << 7)^(ascii_code << 14)^(ascii_code << 16); // Arbitrary
134
- background_color = background_color^0x1fc627; // Arbitrary
135
- background_color = background_color.toString(16);
136
- background_color = ("000000" + background_color).substring(background_color.length); // So 6 chars with leading 0
137
-
138
- // Get most suitable text color - white or black depending on background brightness
139
- let color_brightness = 0;
140
- let luminance_coefficients = [0.299, 0.587, 0.114];
141
- for(let i = 0; i < 6; i += 2) {
142
- color_brightness += parseInt(background_color.substring(i, i+2), 16) * luminance_coefficients[i/2];
143
- }
144
- // Calculate darkness
145
- text_color = color_brightness < 128 ? "white" : "black";
146
-
147
- // console.log(background_color, color_brightness, text_color);
148
-
149
- this.cachedColors[ascii_code] = [background_color, text_color];
150
- return [background_color, text_color];
151
- } else {
152
- return this.cachedColors[ascii_code];
153
- }
154
- }
155
-
156
- getCharacterWidth(codeInput, char) { // TODO: Check StackOverflow question
157
- // Force zero-width characters
158
- if(new RegExp("\u00AD|\u02de|[\u0300-\u036F]|[\u0483-\u0489]|\u200b").test(char) ) { return 0 }
159
- // Non-renderable ASCII characters should all be rendered at same size
160
- if(char != "\u0096" && new RegExp("[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]", "g").test(char)) {
161
- let fallbackWidth = this.getCharacterWidth("\u0096");
162
- return fallbackWidth;
163
- }
164
-
165
- let font = window.getComputedStyle(codeInput.pluginData.specialChars.textarea).font;
166
-
167
- // Lazy-load - TODO: Get a cleaner way of doing this
168
- if(this.cachedWidths[font] == undefined) {
169
- this.cachedWidths[font] = {}; // Create new cached widths for this font
170
- }
171
- if(this.cachedWidths[font][char] != undefined) { // Use cached width
172
- return this.cachedWidths[font][char];
173
- }
174
-
175
- // Ensure font the same
176
- // console.log(font);
177
- this.canvasContext.font = font;
178
-
179
- // Try to get width from canvas
180
- let width = this.canvasContext.measureText(char).width;
181
- if(width > Number(font.split("px")[0])) {
182
- width /= 2; // Fix double-width-in-canvas Firefox bug
183
- } else if(width == 0 && char != "\u0096") {
184
- let fallbackWidth = this.getCharacterWidth("\u0096");
185
- return fallbackWidth; // In Firefox some control chars don't render, but all control chars are the same width
186
- }
187
-
188
- this.cachedWidths[font][char] = width;
189
-
190
- // console.log(this.cachedWidths);
191
- return width;
192
- }
193
-
194
- // getCharacterWidth(char) { // Doesn't work for now - from StackOverflow suggestion https://stackoverflow.com/a/76146120/21785620
195
- // let textarea = codeInput.pluginData.specialChars.textarea;
196
-
197
- // // Create a temporary element to measure the width of the character
198
- // const span = document.createElement('span');
199
- // span.textContent = char;
200
-
201
- // // Copy the textarea's font to the temporary element
202
- // span.style.fontSize = window.getComputedStyle(textarea).fontSize;
203
- // span.style.fontFamily = window.getComputedStyle(textarea).fontFamily;
204
- // span.style.fontWeight = window.getComputedStyle(textarea).fontWeight;
205
- // span.style.visibility = 'hidden';
206
- // span.style.position = 'absolute';
207
-
208
- // // Add the temporary element to the document so we can measure its width
209
- // document.body.appendChild(span);
210
-
211
- // // Get the width of the character in pixels
212
- // const width = span.offsetWidth;
213
-
214
- // // Remove the temporary element from the document
215
- // document.body.removeChild(span);
216
-
217
- // return width;
218
- // }
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
+ // INCOMPLETE: TODO Optimise regex - compile at start; Update CSS for character display; clean up + comment
7
+
8
+ codeInput.plugins.SpecialChars = class extends codeInput.Plugin {
9
+ specialCharRegExp;
10
+
11
+ cachedColors; // ascii number > [background color, text color]
12
+ cachedWidths; // font > {character > character width}
13
+ canvasContext;
14
+
15
+ /**
16
+ * Create a special characters plugin instance
17
+ * @param {Boolean} colorInSpecialChars Whether or not to give special characters custom background colors based on their hex code
18
+ * @param {Boolean} inheritTextColor If `colorInSpecialChars` is false, forces the color of the hex code to inherit from syntax highlighting. Otherwise, the base colour of the `pre code` element is used to give contrast to the small characters.
19
+ * @param {RegExp} specialCharRegExp The regular expression which matches special characters
20
+ */
21
+ 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
22
+ super();
23
+
24
+ this.specialCharRegExp = specialCharRegExp;
25
+ this.colorInSpecialChars = colorInSpecialChars;
26
+ this.inheritTextColor = inheritTextColor;
27
+
28
+ this.cachedColors = {};
29
+ this.cachedWidths = {};
30
+
31
+ let canvas = document.createElement("canvas");
32
+ this.canvasContext = canvas.getContext("2d");
33
+ }
34
+
35
+ /* Runs before elements are added into a `code-input`; Params: codeInput element) */
36
+ beforeElementsAdded(codeInput) {
37
+ codeInput.classList.add("code-input_special-char_container");
38
+ }
39
+
40
+ /* Runs after elements are added into a `code-input` (useful for adding events to the textarea); Params: codeInput element) */
41
+ afterElementsAdded(codeInput) {
42
+ // For some reason, special chars aren't synced the first time - TODO is there a cleaner way to do this?
43
+ setTimeout(() => { codeInput.update(codeInput.value); }, 100);
44
+ }
45
+
46
+ /* Runs after code is highlighted; Params: codeInput element) */
47
+ afterHighlight(codeInput) {
48
+ let result_element = codeInput.querySelector("pre code");
49
+
50
+ // Reset data each highlight so can change if font size, etc. changes
51
+ codeInput.pluginData.specialChars = {};
52
+ codeInput.pluginData.specialChars.textarea = codeInput.getElementsByTagName("textarea")[0];
53
+ codeInput.pluginData.specialChars.contrastColor = window.getComputedStyle(result_element).color;
54
+
55
+ this.recursivelyReplaceText(codeInput, result_element);
56
+
57
+ this.lastFont = window.getComputedStyle(codeInput.pluginData.specialChars.textarea).font;
58
+ }
59
+
60
+ recursivelyReplaceText(codeInput, element) {
61
+ for(let i = 0; i < element.childNodes.length; i++) {
62
+
63
+ let nextNode = element.childNodes[i];
64
+ if(nextNode.nodeName == "#text" && nextNode.nodeValue != "") {
65
+ // Replace in here
66
+ let oldValue = nextNode.nodeValue;
67
+
68
+ this.specialCharRegExp.lastIndex = 0;
69
+ let searchResult = this.specialCharRegExp.exec(oldValue);
70
+ if(searchResult != null) {
71
+ let charIndex = searchResult.index; // Start as returns end
72
+
73
+ nextNode = nextNode.splitText(charIndex+1).previousSibling;
74
+
75
+ if(charIndex > 0) {
76
+ nextNode = nextNode.splitText(charIndex); // Keep those before in difft. span
77
+ }
78
+
79
+ if(nextNode.textContent != "") {
80
+ let replacementElement = this.specialCharReplacer(codeInput, nextNode.textContent);
81
+ nextNode.parentNode.insertBefore(replacementElement, nextNode);
82
+ nextNode.textContent = "";
83
+ }
84
+ }
85
+ } else if(nextNode.nodeType == 1) {
86
+ if(nextNode.className != "code-input_special-char" && nextNode.nodeValue != "") {
87
+ // Element - recurse
88
+ this.recursivelyReplaceText(codeInput, nextNode);
89
+ }
90
+ }
91
+ }
92
+ }
93
+
94
+ specialCharReplacer(codeInput, match_char) {
95
+ let hex_code = match_char.codePointAt(0);
96
+
97
+ let colors;
98
+ if(this.colorInSpecialChars) colors = this.getCharacterColor(hex_code);
99
+
100
+ hex_code = hex_code.toString(16);
101
+ hex_code = ("0000" + hex_code).substring(hex_code.length); // So 2 chars with leading 0
102
+ hex_code = hex_code.toUpperCase();
103
+
104
+ let char_width = this.getCharacterWidth(codeInput, match_char);
105
+
106
+ // Create element with hex code
107
+ let result = document.createElement("span");
108
+ result.classList.add("code-input_special-char");
109
+ result.style.setProperty("--hex-0", "var(--code-input_special-chars_" + hex_code[0] + ")");
110
+ result.style.setProperty("--hex-1", "var(--code-input_special-chars_" + hex_code[1] + ")");
111
+ result.style.setProperty("--hex-2", "var(--code-input_special-chars_" + hex_code[2] + ")");
112
+ result.style.setProperty("--hex-3", "var(--code-input_special-chars_" + hex_code[3] + ")");
113
+
114
+ // Handle zero-width chars
115
+ if(char_width == 0) result.classList.add("code-input_special-char_zero-width");
116
+ else result.style.width = char_width + "px";
117
+
118
+ if(this.colorInSpecialChars) {
119
+ result.style.backgroundColor = "#" + colors[0];
120
+ result.style.setProperty("--code-input_special-char_color", colors[1]);
121
+ } else if(!this.inheritTextColor) {
122
+ result.style.setProperty("--code-input_special-char_color", codeInput.pluginData.specialChars.contrastColor);
123
+ }
124
+ return result;
125
+ }
126
+
127
+ getCharacterColor(ascii_code) {
128
+ // Choose colors based on character code - lazy load and return [background color, text color]
129
+ let background_color;
130
+ let text_color;
131
+ if(!(ascii_code in this.cachedColors)) {
132
+ // Get background color - arbitrary bit manipulation to get a good range of colours
133
+ background_color = ascii_code^(ascii_code << 3)^(ascii_code << 7)^(ascii_code << 14)^(ascii_code << 16); // Arbitrary
134
+ background_color = background_color^0x1fc627; // Arbitrary
135
+ background_color = background_color.toString(16);
136
+ background_color = ("000000" + background_color).substring(background_color.length); // So 6 chars with leading 0
137
+
138
+ // Get most suitable text color - white or black depending on background brightness
139
+ let color_brightness = 0;
140
+ let luminance_coefficients = [0.299, 0.587, 0.114];
141
+ for(let i = 0; i < 6; i += 2) {
142
+ color_brightness += parseInt(background_color.substring(i, i+2), 16) * luminance_coefficients[i/2];
143
+ }
144
+ // Calculate darkness
145
+ text_color = color_brightness < 128 ? "white" : "black";
146
+
147
+ // console.log(background_color, color_brightness, text_color);
148
+
149
+ this.cachedColors[ascii_code] = [background_color, text_color];
150
+ return [background_color, text_color];
151
+ } else {
152
+ return this.cachedColors[ascii_code];
153
+ }
154
+ }
155
+
156
+ getCharacterWidth(codeInput, char) { // TODO: Check StackOverflow question
157
+ // Force zero-width characters
158
+ if(new RegExp("\u00AD|\u02de|[\u0300-\u036F]|[\u0483-\u0489]|\u200b").test(char) ) { return 0 }
159
+ // Non-renderable ASCII characters should all be rendered at same size
160
+ if(char != "\u0096" && new RegExp("[\u{0000}-\u{001F}]|[\u{007F}-\u{009F}]", "g").test(char)) {
161
+ let fallbackWidth = this.getCharacterWidth("\u0096");
162
+ return fallbackWidth;
163
+ }
164
+
165
+ let font = window.getComputedStyle(codeInput.pluginData.specialChars.textarea).font;
166
+
167
+ // Lazy-load - TODO: Get a cleaner way of doing this
168
+ if(this.cachedWidths[font] == undefined) {
169
+ this.cachedWidths[font] = {}; // Create new cached widths for this font
170
+ }
171
+ if(this.cachedWidths[font][char] != undefined) { // Use cached width
172
+ return this.cachedWidths[font][char];
173
+ }
174
+
175
+ // Ensure font the same
176
+ // console.log(font);
177
+ this.canvasContext.font = font;
178
+
179
+ // Try to get width from canvas
180
+ let width = this.canvasContext.measureText(char).width;
181
+ if(width > Number(font.split("px")[0])) {
182
+ width /= 2; // Fix double-width-in-canvas Firefox bug
183
+ } else if(width == 0 && char != "\u0096") {
184
+ let fallbackWidth = this.getCharacterWidth("\u0096");
185
+ return fallbackWidth; // In Firefox some control chars don't render, but all control chars are the same width
186
+ }
187
+
188
+ this.cachedWidths[font][char] = width;
189
+
190
+ // console.log(this.cachedWidths);
191
+ return width;
192
+ }
193
+
194
+ // getCharacterWidth(char) { // Doesn't work for now - from StackOverflow suggestion https://stackoverflow.com/a/76146120/21785620
195
+ // let textarea = codeInput.pluginData.specialChars.textarea;
196
+
197
+ // // Create a temporary element to measure the width of the character
198
+ // const span = document.createElement('span');
199
+ // span.textContent = char;
200
+
201
+ // // Copy the textarea's font to the temporary element
202
+ // span.style.fontSize = window.getComputedStyle(textarea).fontSize;
203
+ // span.style.fontFamily = window.getComputedStyle(textarea).fontFamily;
204
+ // span.style.fontWeight = window.getComputedStyle(textarea).fontWeight;
205
+ // span.style.visibility = 'hidden';
206
+ // span.style.position = 'absolute';
207
+
208
+ // // Add the temporary element to the document so we can measure its width
209
+ // document.body.appendChild(span);
210
+
211
+ // // Get the width of the character in pixels
212
+ // const width = span.offsetWidth;
213
+
214
+ // // Remove the temporary element from the document
215
+ // document.body.removeChild(span);
216
+
217
+ // return width;
218
+ // }
219
219
  }
@@ -1,5 +1,5 @@
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_container{font-size:20px}.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(
2
- --code-input_special-chars_0);--hex-1:var(
3
- --code-input_special-chars_0);--hex-2:var(
4
- --code-input_special-chars_0);--hex-3: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_container{font-size:20px}.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(
2
+ --code-input_special-chars_0);--hex-1:var(
3
+ --code-input_special-chars_0);--hex-2:var(
4
+ --code-input_special-chars_0);--hex-3:var(
5
5
  --code-input_special-chars_0)}.code-input_special-char::before{margin-left:50%;transform:translate(-50%,0);content:" ";background-color:var(--code-input_special-char_color,currentColor);image-rendering:pixelated;display:inline-block;width:calc(100%-2px);height:100%;mask-image:var(--hex-0),var(--hex-1),var(--hex-2),var(--hex-3);mask-repeat:no-repeat,no-repeat,no-repeat,no-repeat;mask-size:40%,40%,40%,40%;mask-position:10% 10%,90% 10%,10% 90%,90% 90%;-webkit-mask-image:var(--hex-0),var(--hex-1),var(--hex-2),var(--hex-3);-webkit-mask-repeat:no-repeat,no-repeat,no-repeat,no-repeat;-webkit-mask-size:min(40%,.25em),min(40%,.25em),min(40%,.25em),min(40%,.25em);-webkit-mask-position:10% 10%,min(90%,.5em) 10%,10% 90%,min(90%,.5em) 90%}.code-input_special-char_zero-width{z-index:1;width:1em;margin-left:-.5em;margin-right:-.5em;position:relative;opacity:.75}.code-input_special-char_one-byte::before{height:1.5em;top:-1em;content:attr(data-hex2)}.code-input_special-char_one-byte::after{height:1.5em;bottom:-1em;content:attr(data-hex3)}
package/plugins/test.js CHANGED
@@ -1,38 +1,38 @@
1
- /**
2
- * Copy this to create a plugin, which brings extra,
3
- * non-central optional functionality to code-input.
4
- * Instances of plugins can be passed in in an array
5
- * to the `plugins` argument when registering a template,
6
- * for example like this:
7
- * ```javascript
8
- * codeInput.registerTemplate("syntax-highlighted", codeInput.templates.hljs(hljs, [new codeInput.plugins.Test()]));
9
- * ```
10
- */
11
- codeInput.plugins.Test = class extends codeInput.Plugin {
12
- constructor() {
13
- super();
14
- }
15
- /* Runs before code is highlighted; Params: codeInput element) */
16
- beforeHighlight(codeInput) {
17
- console.log(codeInput, "before highlight");
18
- }
19
- /* Runs after code is highlighted; Params: codeInput element) */
20
- afterHighlight(codeInput) {
21
- console.log(codeInput, "after highlight");
22
- }
23
- /* Runs before elements are added into a `code-input`; Params: codeInput element) */
24
- beforeElementsAdded(codeInput) {
25
- console.log(codeInput, "before elements added");
26
- }
27
- /* Runs after elements are added into a `code-input` (useful for adding events to the textarea); Params: codeInput element) */
28
- afterElementsAdded(codeInput) {
29
- console.log(codeInput, "after elements added");
30
- }
31
- /* Runs when an attribute of a `code-input` is changed (you must add the attribute name to observedAttributes); Params: codeInput element, name attribute name, oldValue previous value of attribute, newValue changed value of attribute) */
32
- attributeChanged(codeInput, name, oldValue, newValue) {
33
- if(name == "testattr") {
34
- console.log(codeInput, "testattr:", oldValue, ">", newValue);
35
- }
36
- }
37
- observedAttributes = ["testattr"]
1
+ /**
2
+ * Copy this to create a plugin, which brings extra,
3
+ * non-central optional functionality to code-input.
4
+ * Instances of plugins can be passed in in an array
5
+ * to the `plugins` argument when registering a template,
6
+ * for example like this:
7
+ * ```javascript
8
+ * codeInput.registerTemplate("syntax-highlighted", codeInput.templates.hljs(hljs, [new codeInput.plugins.Test()]));
9
+ * ```
10
+ */
11
+ codeInput.plugins.Test = class extends codeInput.Plugin {
12
+ constructor() {
13
+ super();
14
+ }
15
+ /* Runs before code is highlighted; Params: codeInput element) */
16
+ beforeHighlight(codeInput) {
17
+ console.log(codeInput, "before highlight");
18
+ }
19
+ /* Runs after code is highlighted; Params: codeInput element) */
20
+ afterHighlight(codeInput) {
21
+ console.log(codeInput, "after highlight");
22
+ }
23
+ /* Runs before elements are added into a `code-input`; Params: codeInput element) */
24
+ beforeElementsAdded(codeInput) {
25
+ console.log(codeInput, "before elements added");
26
+ }
27
+ /* Runs after elements are added into a `code-input` (useful for adding events to the textarea); Params: codeInput element) */
28
+ afterElementsAdded(codeInput) {
29
+ console.log(codeInput, "after elements added");
30
+ }
31
+ /* Runs when an attribute of a `code-input` is changed (you must add the attribute name to observedAttributes); Params: codeInput element, name attribute name, oldValue previous value of attribute, newValue changed value of attribute) */
32
+ attributeChanged(codeInput, name, oldValue, newValue) {
33
+ if(name == "testattr") {
34
+ console.log(codeInput, "testattr:", oldValue, ">", newValue);
35
+ }
36
+ }
37
+ observedAttributes = ["testattr"]
38
38
  }