@webcoder49/code-input 2.2.1 → 2.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/README.md +10 -4
- package/code-input.css +92 -19
- package/code-input.d.ts +94 -13
- package/code-input.js +114 -40
- package/code-input.min.css +1 -1
- package/code-input.min.js +1 -1
- package/package.json +1 -1
- package/plugins/README.md +7 -0
- package/plugins/auto-close-brackets.js +23 -7
- package/plugins/auto-close-brackets.min.js +1 -1
- package/plugins/autocomplete.js +4 -2
- package/plugins/autocomplete.min.js +1 -1
- package/plugins/find-and-replace.js +142 -42
- package/plugins/find-and-replace.min.js +1 -1
- package/plugins/go-to-line.js +24 -2
- package/plugins/go-to-line.min.js +1 -1
- package/plugins/indent.js +121 -7
- package/plugins/indent.min.js +1 -1
- package/plugins/prism-line-numbers.css +10 -9
- package/plugins/prism-line-numbers.min.css +1 -1
- package/plugins/select-token-callbacks.js +289 -0
- package/plugins/select-token-callbacks.min.js +1 -0
- package/plugins/special-chars.css +1 -1
- package/plugins/special-chars.js +10 -8
- package/plugins/special-chars.min.css +1 -1
- package/plugins/special-chars.min.js +1 -1
- package/tests/hljs.html +2 -1
- package/tests/i18n.html +197 -0
- package/tests/prism-match-braces-compatibility.js +215 -0
- package/tests/prism-match-braces-compatibility.min.js +1 -0
- package/tests/prism.html +7 -8
- package/tests/tester.js +90 -19
- package/tests/tester.min.js +7 -4
package/tests/tester.js
CHANGED
|
@@ -123,6 +123,7 @@ function beginTest(isHLJS) {
|
|
|
123
123
|
new codeInput.plugins.FindAndReplace(),
|
|
124
124
|
new codeInput.plugins.GoToLine(),
|
|
125
125
|
new codeInput.plugins.Indent(true, 2),
|
|
126
|
+
new codeInput.plugins.SelectTokenCallbacks(codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks.createClassSynchronisation("in-selection"), false, true, true, true, true, false),
|
|
126
127
|
new codeInput.plugins.SpecialChars(true),
|
|
127
128
|
]));
|
|
128
129
|
} else {
|
|
@@ -140,6 +141,7 @@ function beginTest(isHLJS) {
|
|
|
140
141
|
new codeInput.plugins.FindAndReplace(),
|
|
141
142
|
new codeInput.plugins.GoToLine(),
|
|
142
143
|
new codeInput.plugins.Indent(true, 2),
|
|
144
|
+
new codeInput.plugins.SelectTokenCallbacks(new codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks(selectBrace, deselectAllBraces), true),
|
|
143
145
|
new codeInput.plugins.SpecialChars(true),
|
|
144
146
|
]));
|
|
145
147
|
}
|
|
@@ -160,12 +162,17 @@ function startLoad(codeInputElem, isHLJS) {
|
|
|
160
162
|
}
|
|
161
163
|
|
|
162
164
|
/* Make input events work and be trusted in the inputElement - thanks for this SO answer: https://stackoverflow.com/a/49519772/21785620 */
|
|
163
|
-
function allowInputEvents(inputElement) {
|
|
165
|
+
function allowInputEvents(inputElement, codeInputElement=undefined) {
|
|
164
166
|
inputElement.addEventListener('input', function(e){
|
|
165
167
|
if(!e.isTrusted){
|
|
166
168
|
e.preventDefault();
|
|
167
169
|
// Manually trigger
|
|
170
|
+
// Prevent auto-close-brackets plugin recapturing the event
|
|
171
|
+
// Needed because this interception is hacky.
|
|
172
|
+
// TODO: Potentially plugin-agnostic way, probably automatedKeypresses var in core, won't be needed much but may be helpful extra feature.
|
|
173
|
+
if(codeInputElement !== undefined) codeInputElement.pluginData.autoCloseBrackets.automatedKeypresses = true;
|
|
168
174
|
document.execCommand("insertText", false, e.data);
|
|
175
|
+
if(codeInputElement !== undefined) codeInputElement.pluginData.autoCloseBrackets.automatedKeypresses = false;
|
|
169
176
|
}
|
|
170
177
|
}, false);
|
|
171
178
|
}
|
|
@@ -173,9 +180,9 @@ function allowInputEvents(inputElement) {
|
|
|
173
180
|
/* Start the tests using the textarea inside the code-input element and whether highlight.js is being used (as the Autodetect plugin only works with highlight.js, for example) */
|
|
174
181
|
async function startTests(textarea, isHLJS) {
|
|
175
182
|
textarea.focus();
|
|
176
|
-
allowInputEvents(textarea);
|
|
177
183
|
|
|
178
184
|
codeInputElement = textarea.parentElement;
|
|
185
|
+
allowInputEvents(textarea, codeInputElement);
|
|
179
186
|
|
|
180
187
|
/*--- Tests for core functionality ---*/
|
|
181
188
|
|
|
@@ -187,7 +194,8 @@ async function startTests(textarea, isHLJS) {
|
|
|
187
194
|
let renderedValue = codeInputElement.codeElement.innerHTML.replace(/<[^>]+>/g, "");
|
|
188
195
|
assertEqual("Core", "Initial Rendered Value", renderedValue, `console.log("Hello, World!");
|
|
189
196
|
// A second line
|
|
190
|
-
// A third line with <html> tags
|
|
197
|
+
// A third line with <html> tags
|
|
198
|
+
`); // Extra newline so line numbers visible if enabled
|
|
191
199
|
|
|
192
200
|
|
|
193
201
|
// Update code-input value with JavaScript, new value and num events should be correct.
|
|
@@ -206,19 +214,24 @@ console.log("I've got another line!", 2 < 3, "should be true.");`);
|
|
|
206
214
|
assertEqual("Core", "JS-updated Rendered Value", renderedValue, `console.log("Hello, World!");
|
|
207
215
|
// A second line
|
|
208
216
|
// A third line with <html> tags
|
|
209
|
-
console.log("I've got another line!", 2 < 3, "should be true.")
|
|
217
|
+
console.log("I've got another line!", 2 < 3, "should be true.");
|
|
218
|
+
`); // Extra newline so line numbers visible if enabled
|
|
210
219
|
|
|
211
|
-
// Event Tests
|
|
220
|
+
// Event Listener Tests
|
|
221
|
+
// Function type listeners
|
|
212
222
|
let numTimesInputCalled = 0;
|
|
213
223
|
let numTimesChangeCalled = 0;
|
|
214
|
-
|
|
224
|
+
|
|
225
|
+
let inputListener = (evt) => {
|
|
215
226
|
if(!evt.isTrusted) { // To prevent duplicate calling due to allowInputEvents hack
|
|
216
227
|
numTimesInputCalled++;
|
|
217
228
|
}
|
|
218
|
-
}
|
|
219
|
-
codeInputElement.addEventListener("
|
|
229
|
+
};
|
|
230
|
+
codeInputElement.addEventListener("input", inputListener);
|
|
231
|
+
let changeListener = () => {
|
|
220
232
|
numTimesChangeCalled++;
|
|
221
|
-
}
|
|
233
|
+
};
|
|
234
|
+
codeInputElement.addEventListener("change", changeListener);
|
|
222
235
|
|
|
223
236
|
let inputDeletedListenerCalled = false;
|
|
224
237
|
let deletedListener = () => {
|
|
@@ -233,17 +246,49 @@ console.log("I've got another line!", 2 < 3, "should be true.");`);
|
|
|
233
246
|
textarea.blur(); // Unfocus textarea - calls change event
|
|
234
247
|
textarea.focus();
|
|
235
248
|
|
|
236
|
-
assertEqual("Core", "
|
|
237
|
-
assertEqual("Core", "
|
|
238
|
-
testAssertion("Core", "
|
|
249
|
+
assertEqual("Core", "Function Event Listeners: Input Called Right Number of Times", numTimesInputCalled, 6);
|
|
250
|
+
assertEqual("Core", "Function Event Listeners: Change Called Right Number of Times", numTimesChangeCalled, 1);
|
|
251
|
+
testAssertion("Core", "Function Event Listeners: Input Removed Listener Not Called", !inputDeletedListenerCalled, "(code-input element).removeEventListener did not work.");
|
|
252
|
+
|
|
253
|
+
codeInputElement.removeEventListener("input", inputListener);
|
|
254
|
+
codeInputElement.removeEventListener("change", changeListener);
|
|
255
|
+
|
|
256
|
+
// Repeat for Object type listeners
|
|
257
|
+
numTimesInputCalled = 0;
|
|
258
|
+
numTimesChangeCalled = 0;
|
|
259
|
+
codeInputElement.addEventListener("input", {handleEvent: (evt) => {
|
|
260
|
+
if(!evt.isTrusted) { // To prevent duplicate calling due to allowInputEvents hack
|
|
261
|
+
numTimesInputCalled++;
|
|
262
|
+
}
|
|
263
|
+
}});
|
|
264
|
+
codeInputElement.addEventListener("change", {handleEvent: () => {
|
|
265
|
+
numTimesChangeCalled++;
|
|
266
|
+
}});
|
|
267
|
+
|
|
268
|
+
inputDeletedListenerCalled = false;
|
|
269
|
+
deletedListener = {handleEvent: () => {
|
|
270
|
+
inputDeletedListenerCalled = true;
|
|
271
|
+
}};
|
|
272
|
+
codeInputElement.addEventListener("input", deletedListener);
|
|
273
|
+
codeInputElement.removeEventListener("input", deletedListener);
|
|
274
|
+
|
|
275
|
+
// Make listeners be called
|
|
276
|
+
textarea.focus(); // Focus textarea
|
|
277
|
+
addText(textarea, " // Hi");
|
|
278
|
+
textarea.blur(); // Unfocus textarea - calls change event
|
|
279
|
+
textarea.focus();
|
|
280
|
+
|
|
281
|
+
assertEqual("Core", "Object Event Listeners: Input Called Right Number of Times", numTimesInputCalled, 6);
|
|
282
|
+
assertEqual("Core", "Object Event Listeners: Change Called Right Number of Times", numTimesChangeCalled, 1);
|
|
283
|
+
testAssertion("Core", "Object Event Listeners: Input Removed Listener Not Called", !inputDeletedListenerCalled, "(code-input element).removeEventListener did not work.");
|
|
239
284
|
|
|
240
285
|
// Changing language should be correct
|
|
241
286
|
if(!isHLJS) {
|
|
242
287
|
// Highlight.js has autodetect plugin that should make this fail, so don't run these tests with it.
|
|
243
288
|
testAssertion("Core", "Language attribute Initial value",
|
|
244
|
-
codeInputElement.codeElement.classList.contains("language-javascript")
|
|
289
|
+
!codeInputElement.codeElement.classList.contains("language-javascript")
|
|
245
290
|
&& !codeInputElement.codeElement.classList.contains("language-html"),
|
|
246
|
-
`Language
|
|
291
|
+
`Language unset but code element's class name is ${codeInputElement.codeElement.className}.`);
|
|
247
292
|
|
|
248
293
|
codeInputElement.setAttribute("language", "HTML");
|
|
249
294
|
|
|
@@ -278,7 +323,8 @@ console.log("I've got another line!", 2 < 3, "should be true.");`);
|
|
|
278
323
|
renderedValue = codeInputElement.codeElement.innerHTML.replace(/<[^>]+>/g, "");
|
|
279
324
|
assertEqual("Core", "Form Reset resets Rendered Value", renderedValue, `console.log("Hello, World!");
|
|
280
325
|
// A second line
|
|
281
|
-
// A third line with <html> tags
|
|
326
|
+
// A third line with <html> tags
|
|
327
|
+
`); // Extra newline so line numbers visible if enabled.
|
|
282
328
|
|
|
283
329
|
/*--- Tests for plugins ---*/
|
|
284
330
|
// AutoCloseBrackets
|
|
@@ -397,7 +443,7 @@ console.log("I've got another line!", 2 < 3, "should be true.");`);
|
|
|
397
443
|
findInput.focus();
|
|
398
444
|
allowInputEvents(findInput);
|
|
399
445
|
addText(findInput, "hello");
|
|
400
|
-
await waitAsync(
|
|
446
|
+
await waitAsync(200); // Wait for highlighting so matches update
|
|
401
447
|
|
|
402
448
|
replaceInput.value = "hi";
|
|
403
449
|
replaceAllButton.click();
|
|
@@ -484,8 +530,33 @@ console.log("I've got another line!", 2 < 3, "should be true.");`);
|
|
|
484
530
|
backspace(textarea);
|
|
485
531
|
|
|
486
532
|
testAddingText("Indent-AutoCloseBrackets", textarea, function(textarea) {
|
|
487
|
-
addText(textarea, `function printTriples(max) {\nfor(let i = 0; i < max-2; i++) {\nfor(let j = 0; j < max-1; j++) {\nfor(let k = 0; k < max; k++) {\nconsole.log(i,j,k);\n}\n//Hmmm
|
|
488
|
-
|
|
533
|
+
addText(textarea, `function printTriples(max) {\nfor(let i = 0; i < max-2; i++) {\nfor(let j = 0; j < max-1; j++) {\nfor(let k = 0; k < max; k++) {\nconsole.log(i,j,k);\n}\n//Hmmm...\n}//Test auto-unindent\n{`, true);
|
|
534
|
+
move(textarea, 1); // Move after created closing bracket
|
|
535
|
+
backspace(textarea); // Remove created closing bracket
|
|
536
|
+
}, 'function printTriples(max) {\n for(let i = 0; i < max-2; i++) {\n for(let j = 0; j < max-1; j++) {\n for(let k = 0; k < max; k++) {\n console.log(i,j,k);\n }\n //Hmmm...\n }//Test auto-unindent\n {\n }\n }\n }\n}', 221, 221);
|
|
537
|
+
|
|
538
|
+
// SelectTokenCallbacks
|
|
539
|
+
if(isHLJS) {
|
|
540
|
+
addText(textarea, "\nlet x = 1;\nlet y = 2;\nconsole.log(`${x} + ${y} = ${x+y}`);");
|
|
541
|
+
move(textarea, -4); // Ends at |: "${x+y|}`);"
|
|
542
|
+
textarea.selectionStart -= 35; // Starts at |: "let y = |2;"
|
|
543
|
+
await waitAsync(50); // Wait for highlighting so text updates
|
|
544
|
+
assertEqual("SelectTokenCallbacks", "Number of Selected Tokens", codeInputElement.querySelectorAll(".in-selection").length, 13);
|
|
545
|
+
assertEqual("SelectTokenCallbacks", "Number of Selected .hljs-string Tokens", codeInputElement.querySelectorAll(".hljs-string.in-selection").length, 0); // Since parentTokensAreSelected set to false
|
|
546
|
+
assertEqual("SelectTokenCallbacks", "Number of Selected .hljs-subst Tokens", codeInputElement.querySelectorAll(".hljs-subst.in-selection").length, 2);
|
|
547
|
+
} else {
|
|
548
|
+
// Combined with compatiblity-added match-braces plugin
|
|
549
|
+
addText(textarea, "\n[(),((),'Hi')]");
|
|
550
|
+
await waitAsync(50); // Wait for highlighting so text updates
|
|
551
|
+
// Move back 2 characters so just after 'Hi'
|
|
552
|
+
move(textarea, -2);
|
|
553
|
+
await waitAsync(50); // Wait for highlighting so text updates
|
|
554
|
+
assertEqual("SelectTokenCallbacks", "Number of Selected Braces 1", codeInputElement.getElementsByClassName("brace-hover").length, 2);
|
|
555
|
+
// Move forward 1 character so between )]
|
|
556
|
+
move(textarea, 1);
|
|
557
|
+
await waitAsync(50); // Wait for highlighting so text updates
|
|
558
|
+
assertEqual("SelectTokenCallbacks", "Number of Selected Braces 2", codeInputElement.getElementsByClassName("brace-hover").length, 4);
|
|
559
|
+
}
|
|
489
560
|
|
|
490
561
|
// SpecialChars
|
|
491
562
|
// Clear all code
|
|
@@ -526,4 +597,4 @@ console.log("I've got another line!", 2 < 3, "should be true.");`);
|
|
|
526
597
|
document.querySelector("h2").style.backgroundColor = "lightgreen";
|
|
527
598
|
document.querySelector("h2").textContent = "All Tests have Passed.";
|
|
528
599
|
}
|
|
529
|
-
}
|
|
600
|
+
}
|
package/tests/tester.min.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
var testsFailed=!1;function testData(a,b,c){let d=document.getElementById("test-results"),e=d.querySelector("#test-"+a);e==null&&(e=document.createElement("span"),e.innerHTML=`Group <b>${a}</b>:\n`,e.id="test-"+a,d.append(e)),e.innerHTML+=`\t${b}: ${c}\n`}function testAssertion(a,b,c,d){let e=document.getElementById("test-results"),f=e.querySelector("#test-"+a);f==null&&(f=document.createElement("span"),f.innerHTML=`Group <b>${a}</b>:\n`,f.id="test-"+a,e.append(f)),f.innerHTML+=`\t${b}: ${c?"<b style=\"color: darkgreen;\">passed</b>":"<b style=\"color: red;\">failed</b> ("+d+")"}\n`,c||(testsFailed=!0)}function assertEqual(a,b,c,d){let e=c==d;testAssertion(a,b,e,"see console output"),e||console.error(a,b,c,"should be",d)}function testAddingText(a,b,c,d,e,f){let g=b.selectionStart,h=b.value.substring(0,b.selectionStart),i=b.value.substring(b.selectionEnd);c(b);let j=h+d+i;assertEqual(a,"Text Output",b.value,j),assertEqual(a,"Code-Input Value JS Property Output",b.parentElement.value,j),assertEqual(a,"Selection Start",b.selectionStart,g+e),assertEqual(a,"Selection End",b.selectionEnd,g+f)}function addText(a,b,c=!1){for(let d=0;d<b.length;d++)if(c&&"\n"==b[d])a.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"}));else{let c=new InputEvent("beforeinput",{cancelable:!0,data:b[d]});a.dispatchEvent(c),c.defaultPrevented||a.dispatchEvent(new InputEvent("input",{data:b[d]}))}}function backspace(a){let b=new KeyboardEvent("keydown",{cancelable:!0,key:"Backspace"});a.dispatchEvent(b);let c=new KeyboardEvent("keyup",{cancelable:!0,key:"Backspace"});a.dispatchEvent(c),b.defaultPrevented||(a.selectionEnd==a.selectionStart&&(a.selectionEnd=a.selectionStart,a.selectionStart--),document.execCommand("delete",!1,null))}function move(a,b){a.selectionStart+=b,a.selectionEnd=a.selectionStart}function waitAsync(a){return new Promise(b=>{setTimeout(()=>{b()},a)})}function beginTest(a){let b=document.querySelector("code-input");a?codeInput.registerTemplate("code-editor",codeInput.templates.hljs(hljs,[new codeInput.plugins.AutoCloseBrackets,new codeInput.plugins.Autocomplete(function(a,b,c){"popup"==b.value.substring(c-5,c)?(a.style.display="block",a.innerHTML="Here's your popup!"):a.style.display="none"}),new codeInput.plugins.Autodetect,new codeInput.plugins.FindAndReplace,new codeInput.plugins.GoToLine,new codeInput.plugins.Indent(!0,2),new codeInput.plugins.SpecialChars(!0)])):codeInput.registerTemplate("code-editor",codeInput.templates.prism(Prism,[new codeInput.plugins.AutoCloseBrackets,new codeInput.plugins.Autocomplete(function(a,b,c){"popup"==b.value.substring(c-5,c)?(a.style.display="block",a.innerHTML="Here's your popup!"):a.style.display="none"}),new codeInput.plugins.FindAndReplace,new codeInput.plugins.GoToLine,new codeInput.plugins.Indent(!0,2),new codeInput.plugins.SpecialChars(!0)])),startLoad(b,a)}function startLoad(a,b){let c,d=0,e=window.setInterval(()=>{c=a.querySelector("textarea"),null!=c&&window.clearInterval(e),d+=10,testData("TimeTaken","Textarea Appears",d+"ms (nearest 10)"),startTests(c,b)},10)}function allowInputEvents(a){a.addEventListener("input",function(a){a.isTrusted||(a.preventDefault(),document.execCommand("insertText",!1,a.data))},!1)}async function startTests(a,b){a.focus(),
|
|
1
|
+
var testsFailed=!1;function testData(a,b,c){let d=document.getElementById("test-results"),e=d.querySelector("#test-"+a);e==null&&(e=document.createElement("span"),e.innerHTML=`Group <b>${a}</b>:\n`,e.id="test-"+a,d.append(e)),e.innerHTML+=`\t${b}: ${c}\n`}function testAssertion(a,b,c,d){let e=document.getElementById("test-results"),f=e.querySelector("#test-"+a);f==null&&(f=document.createElement("span"),f.innerHTML=`Group <b>${a}</b>:\n`,f.id="test-"+a,e.append(f)),f.innerHTML+=`\t${b}: ${c?"<b style=\"color: darkgreen;\">passed</b>":"<b style=\"color: red;\">failed</b> ("+d+")"}\n`,c||(testsFailed=!0)}function assertEqual(a,b,c,d){let e=c==d;testAssertion(a,b,e,"see console output"),e||console.error(a,b,c,"should be",d)}function testAddingText(a,b,c,d,e,f){let g=b.selectionStart,h=b.value.substring(0,b.selectionStart),i=b.value.substring(b.selectionEnd);c(b);let j=h+d+i;assertEqual(a,"Text Output",b.value,j),assertEqual(a,"Code-Input Value JS Property Output",b.parentElement.value,j),assertEqual(a,"Selection Start",b.selectionStart,g+e),assertEqual(a,"Selection End",b.selectionEnd,g+f)}function addText(a,b,c=!1){for(let d=0;d<b.length;d++)if(c&&"\n"==b[d])a.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"}));else{let c=new InputEvent("beforeinput",{cancelable:!0,data:b[d]});a.dispatchEvent(c),c.defaultPrevented||a.dispatchEvent(new InputEvent("input",{data:b[d]}))}}function backspace(a){let b=new KeyboardEvent("keydown",{cancelable:!0,key:"Backspace"});a.dispatchEvent(b);let c=new KeyboardEvent("keyup",{cancelable:!0,key:"Backspace"});a.dispatchEvent(c),b.defaultPrevented||(a.selectionEnd==a.selectionStart&&(a.selectionEnd=a.selectionStart,a.selectionStart--),document.execCommand("delete",!1,null))}function move(a,b){a.selectionStart+=b,a.selectionEnd=a.selectionStart}function waitAsync(a){return new Promise(b=>{setTimeout(()=>{b()},a)})}function beginTest(a){let b=document.querySelector("code-input");a?codeInput.registerTemplate("code-editor",codeInput.templates.hljs(hljs,[new codeInput.plugins.AutoCloseBrackets,new codeInput.plugins.Autocomplete(function(a,b,c){"popup"==b.value.substring(c-5,c)?(a.style.display="block",a.innerHTML="Here's your popup!"):a.style.display="none"}),new codeInput.plugins.Autodetect,new codeInput.plugins.FindAndReplace,new codeInput.plugins.GoToLine,new codeInput.plugins.Indent(!0,2),new codeInput.plugins.SelectTokenCallbacks(codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks.createClassSynchronisation("in-selection"),!1,!0,!0,!0,!0,!1),new codeInput.plugins.SpecialChars(!0)])):codeInput.registerTemplate("code-editor",codeInput.templates.prism(Prism,[new codeInput.plugins.AutoCloseBrackets,new codeInput.plugins.Autocomplete(function(a,b,c){"popup"==b.value.substring(c-5,c)?(a.style.display="block",a.innerHTML="Here's your popup!"):a.style.display="none"}),new codeInput.plugins.FindAndReplace,new codeInput.plugins.GoToLine,new codeInput.plugins.Indent(!0,2),new codeInput.plugins.SelectTokenCallbacks(new codeInput.plugins.SelectTokenCallbacks.TokenSelectorCallbacks(selectBrace,deselectAllBraces),!0),new codeInput.plugins.SpecialChars(!0)])),startLoad(b,a)}function startLoad(a,b){let c,d=0,e=window.setInterval(()=>{c=a.querySelector("textarea"),null!=c&&window.clearInterval(e),d+=10,testData("TimeTaken","Textarea Appears",d+"ms (nearest 10)"),startTests(c,b)},10)}function allowInputEvents(a,b=void 0){a.addEventListener("input",function(a){a.isTrusted||(a.preventDefault(),b!==void 0&&(b.pluginData.autoCloseBrackets.automatedKeypresses=!0),document.execCommand("insertText",!1,a.data),b!==void 0&&(b.pluginData.autoCloseBrackets.automatedKeypresses=!1))},!1)}async function startTests(a,b){a.focus(),codeInputElement=a.parentElement,allowInputEvents(a,codeInputElement),assertEqual("Core","Initial Textarea Value",a.value,`console.log("Hello, World!");
|
|
2
2
|
// A second line
|
|
3
3
|
// A third line with <html> tags`);let c=codeInputElement.codeElement.innerHTML.replace(/<[^>]+>/g,"");assertEqual("Core","Initial Rendered Value",c,`console.log("Hello, World!");
|
|
4
4
|
// A second line
|
|
5
|
-
// A third line with <html> tags
|
|
5
|
+
// A third line with <html> tags
|
|
6
|
+
`),codeInputElement.value+=`
|
|
6
7
|
console.log("I've got another line!", 2 < 3, "should be true.");`,await waitAsync(50),assertEqual("Core","JS-updated Textarea Value",a.value,`console.log("Hello, World!");
|
|
7
8
|
// A second line
|
|
8
9
|
// A third line with <html> tags
|
|
9
10
|
console.log("I've got another line!", 2 < 3, "should be true.");`),c=codeInputElement.codeElement.innerHTML.replace(/<[^>]+>/g,""),assertEqual("Core","JS-updated Rendered Value",c,`console.log("Hello, World!");
|
|
10
11
|
// A second line
|
|
11
12
|
// A third line with <html> tags
|
|
12
|
-
console.log("I've got another line!", 2 < 3, "should be true.")
|
|
13
|
+
console.log("I've got another line!", 2 < 3, "should be true.");
|
|
14
|
+
`);let d=0,e=0,f=a=>{a.isTrusted||d++};codeInputElement.addEventListener("input",f);let g=()=>{e++};codeInputElement.addEventListener("change",g);let h=!1,i=()=>{h=!0};codeInputElement.addEventListener("input",i),codeInputElement.removeEventListener("input",i),a.focus(),addText(a," // Hi"),a.blur(),a.focus(),assertEqual("Core","Function Event Listeners: Input Called Right Number of Times",d,6),assertEqual("Core","Function Event Listeners: Change Called Right Number of Times",e,1),testAssertion("Core","Function Event Listeners: Input Removed Listener Not Called",!h,"(code-input element).removeEventListener did not work."),codeInputElement.removeEventListener("input",f),codeInputElement.removeEventListener("change",g),d=0,e=0,codeInputElement.addEventListener("input",{handleEvent:a=>{a.isTrusted||d++}}),codeInputElement.addEventListener("change",{handleEvent:()=>{e++}}),h=!1,i={handleEvent:()=>{h=!0}},codeInputElement.addEventListener("input",i),codeInputElement.removeEventListener("input",i),a.focus(),addText(a," // Hi"),a.blur(),a.focus(),assertEqual("Core","Object Event Listeners: Input Called Right Number of Times",d,6),assertEqual("Core","Object Event Listeners: Change Called Right Number of Times",e,1),testAssertion("Core","Object Event Listeners: Input Removed Listener Not Called",!h,"(code-input element).removeEventListener did not work."),b||(testAssertion("Core","Language attribute Initial value",!codeInputElement.codeElement.classList.contains("language-javascript")&&!codeInputElement.codeElement.classList.contains("language-html"),`Language unset but code element's class name is ${codeInputElement.codeElement.className}.`),codeInputElement.setAttribute("language","HTML"),await waitAsync(50),testAssertion("Core","Language attribute Changed value 1",codeInputElement.codeElement.classList.contains("language-html")&&!codeInputElement.codeElement.classList.contains("language-javascript"),`Language set to HTML but code element's class name is ${codeInputElement.codeElement.className}.`),codeInputElement.setAttribute("language","JavaScript"),await waitAsync(50),testAssertion("Core","Language attribute Changed value 2",codeInputElement.codeElement.classList.contains("language-javascript")&&!codeInputElement.codeElement.classList.contains("language-html"),`Language set to JavaScript but code element's class name is ${codeInputElement.codeElement.className}.`));let j=codeInputElement.parentElement;j.reset(),await waitAsync(50),assertEqual("Core","Form Reset resets Code-Input Value",codeInputElement.value,`console.log("Hello, World!");
|
|
13
15
|
// A second line
|
|
14
16
|
// A third line with <html> tags`),assertEqual("Core","Form Reset resets Textarea Value",a.value,`console.log("Hello, World!");
|
|
15
17
|
// A second line
|
|
16
18
|
// A third line with <html> tags`),c=codeInputElement.codeElement.innerHTML.replace(/<[^>]+>/g,""),assertEqual("Core","Form Reset resets Rendered Value",c,`console.log("Hello, World!");
|
|
17
19
|
// A second line
|
|
18
|
-
// A third line with <html> tags`),testAddingText("AutoCloseBrackets",a,function(a){addText(a,`\nconsole.log("A test message`),move(a,2),addText(a,`;\nconsole.log("Another test message");\n{[{[]}(([[`),backspace(a),backspace(a),backspace(a),addText(a,`)`)},"\nconsole.log(\"A test message\");\nconsole.log(\"Another test message\");\n{[{[]}()]}",77,77),addText(a,"popup"),await waitAsync(50),testAssertion("Autocomplete","Popup Shows",confirm("Does the autocomplete popup display correctly? (OK=Yes)"),"user-judged"),backspace(a),await waitAsync(50),testAssertion("Autocomplete","Popup Disappears",confirm("Has the popup disappeared? (OK=Yes)"),"user-judged"),backspace(a),backspace(a),backspace(a),backspace(a),b&&(a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"console.log(\"Hello, World!\");\nfunction sayHello(name) {\n console.log(\"Hello, \" + name + \"!\");\n}\nsayHello(\"code-input\");"),await waitAsync(50),assertEqual("Autodetect","Detects JavaScript",codeInputElement.getAttribute("language"),"javascript"),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"#!/usr/bin/python\nprint(\"Hello, World!\")\nfor i in range(5):\n print(i)"),await waitAsync(50),assertEqual("Autodetect","Detects Python",codeInputElement.getAttribute("language"),"python"),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"body, html {\n height: 100%;\n background-color: blue;\n color: red;\n}"),await waitAsync(50),assertEqual("Autodetect","Detects CSS",codeInputElement.getAttribute("language"),"css")),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"// hello /\\S/g\nhe('llo', /\\s/g);\nhello"),a.selectionStart=a.selectionEnd=0,await waitAsync(50),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"f",ctrlKey:!0}));let i=codeInputElement.querySelectorAll(".code-input_find-and-replace_dialog input"),j=i[0],k=i[1],l=i[2],m=i[3],n=codeInputElement.querySelectorAll(".code-input_find-and-replace_dialog button"),o=n[0],p=n[1],q=n[2],r=n[3],s=codeInputElement.querySelector(".code-input_find-and-replace_dialog details summary");j.value="/\\s/g",l.click(),await waitAsync(150),testAssertion("FindAndReplace","Finds Case-Sensitive Matches Correctly",confirm("Is there a match on only the lowercase '/\\s/g'?"),"user-judged"),j.value="he[^l]*llo",k.click(),l.click(),await waitAsync(150),testAssertion("FindAndReplace","Finds RegExp Matches Correctly",confirm("Are there matches on all 'he...llo's?"),"user-judged"),s.click(),p.click(),m.value="do('hello",q.click(),await waitAsync(50),assertEqual("FindAndReplace","Replaces Once Correctly",a.value,"// hello /\\S/g\ndo('hello', /\\s/g);\nhello"),o.click(),codeInputElement.querySelector(".code-input_find-and-replace_dialog").dispatchEvent(new KeyboardEvent("keydown",{key:"Escape"})),codeInputElement.querySelector(".code-input_find-and-replace_dialog").dispatchEvent(new KeyboardEvent("keyup",{key:"Escape"})),assertEqual("FindAndReplace","Selection Start on Focused Match when Dialog Exited",a.selectionStart,3),assertEqual("FindAndReplace","Selection End on Focused Match when Dialog Exited",a.selectionEnd,8),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"h",ctrlKey:!0})),j.value="",j.focus(),allowInputEvents(j),addText(j,"hello"),await waitAsync(150),m.value="hi",r.click(),assertEqual("FindAndReplace","Replaces All Correctly",a.value,"// hi /\\S/g\ndo('hi', /\\s/g);\nhi"),codeInputElement.querySelector(".code-input_find-and-replace_dialog").dispatchEvent(new KeyboardEvent("keydown",{key:"Escape"})),codeInputElement.querySelector(".code-input_find-and-replace_dialog").dispatchEvent(new KeyboardEvent("keyup",{key:"Escape"})),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line"),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0}));let t=codeInputElement.querySelector(".code-input_go-to-line_dialog input");t.value="1",t.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),t.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Line Only",a.selectionStart,0),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0})),t.value="3:18",t.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),t.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Line and Column",a.selectionStart,45),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0})),t.value="10",t.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),t.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Rejects Out-of-range Line",t.classList.contains("code-input_go-to-line_error"),!0),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0})),t.value="2:12",t.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),t.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Rejects Out-of-range Column",t.classList.contains("code-input_go-to-line_error"),!0),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0})),t.value="sausages",t.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),t.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Rejects Invalid Input",t.classList.contains("code-input_go-to-line_error"),!0),assertEqual("GoToLine","Stays open when Rejects Input",t.parentElement.classList.contains("code-input_go-to-line_hidden-dialog"),!1),t.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape"})),t.dispatchEvent(new KeyboardEvent("keyup",{key:"Escape"})),assertEqual("GoToLine","Exits when Esc pressed",t.parentElement.classList.contains("code-input_go-to-line_hidden-dialog"),!0),a.selectionStart=a.selectionEnd=a.value.length,addText(a,"\nfor(let i = 0; i < 100; i++) {\n for(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n }\n}\n{\n // This is indented\n}"),a.selectionStart=0,a.selectionEnd=a.value.length,a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!1})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!1})),assertEqual("Indent","Indents Lines",a.value," // 7 times table\n let i = 1;\n while(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n // That's my code.\n // This is another comment\n // Another\n // Line\n for(let i = 0; i < 100; i++) {\n for(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n }\n }\n {\n // This is indented\n }"),a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!0})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!0})),assertEqual("Indent","Unindents Lines",a.value,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line\nfor(let i = 0; i < 100; i++) {\n for(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n }\n}\n{\n // This is indented\n}"),a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!0})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!0})),assertEqual("Indent","Unindents Lines where some are already fully unindented",a.value,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line\nfor(let i = 0; i < 100; i++) {\nfor(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n}\n}\n{\n// This is indented\n}"),a.selectionStart=255,a.selectionEnd=274,a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!1})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!1})),assertEqual("Indent","Indents Lines by Selection",a.value,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line\nfor(let i = 0; i < 100; i++) {\nfor(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n}\n}\n{\n // This is indented\n}"),a.selectionStart=265,a.selectionEnd=265,a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!0})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!0})),assertEqual("Indent","Unindents Lines by Selection",a.value,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line\nfor(let i = 0; i < 100; i++) {\nfor(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n}\n}\n{\n// This is indented\n}"),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),testAddingText("Indent-AutoCloseBrackets",a,function(a){addText(a,`function printTriples(max) {\nfor(let i = 0; i < max-2; i++) {\nfor(let j = 0; j < max-1; j++) {\nfor(let k = 0; k < max; k++) {\nconsole.log(i,j,k);\n}\n//Hmmm...`,!0)},"function printTriples(max) {\n for(let i = 0; i < max-2; i++) {\n for(let j = 0; j < max-1; j++) {\n for(let k = 0; k < max; k++) {\n console.log(i,j,k);\n }\n //Hmmm...\n }\n }\n }\n}",189,189),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"\"Some special characters: \x96,\x01\x03,\x02...\""),a.selectionStart=a.value.length-4,a.selectionEnd=a.value.length,await waitAsync(50),testAssertion("SpecialChars","Displays Correctly",confirm("Do the special characters read (0096),(0001)(0003),(0002) and align with the ellipsis? (OK=Yes)"),"user-judged"),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),fetch(new Request("https://cdn.jsdelivr.net/gh/webcoder49/code-input@2.1/code-input.js")).then(a=>a.text()).then(b=>{a.value="// code-input v2.1: A large code file (not the latest version!)\n// Editing this here should give little latency.\n\n"+b,a.selectionStart=112,a.selectionEnd=112,addText(a,"\n",!0),document.getElementById("collapse-results").setAttribute("open",!0)}),testsFailed?(document.querySelector("h2").style.backgroundColor="red",document.querySelector("h2").textContent="Some Tests have Failed."):(document.querySelector("h2").style.backgroundColor="lightgreen",document.querySelector("h2").textContent="All Tests have Passed.")}
|
|
20
|
+
// A third line with <html> tags
|
|
21
|
+
`),testAddingText("AutoCloseBrackets",a,function(a){addText(a,`\nconsole.log("A test message`),move(a,2),addText(a,`;\nconsole.log("Another test message");\n{[{[]}(([[`),backspace(a),backspace(a),backspace(a),addText(a,`)`)},"\nconsole.log(\"A test message\");\nconsole.log(\"Another test message\");\n{[{[]}()]}",77,77),addText(a,"popup"),await waitAsync(50),testAssertion("Autocomplete","Popup Shows",confirm("Does the autocomplete popup display correctly? (OK=Yes)"),"user-judged"),backspace(a),await waitAsync(50),testAssertion("Autocomplete","Popup Disappears",confirm("Has the popup disappeared? (OK=Yes)"),"user-judged"),backspace(a),backspace(a),backspace(a),backspace(a),b&&(a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"console.log(\"Hello, World!\");\nfunction sayHello(name) {\n console.log(\"Hello, \" + name + \"!\");\n}\nsayHello(\"code-input\");"),await waitAsync(50),assertEqual("Autodetect","Detects JavaScript",codeInputElement.getAttribute("language"),"javascript"),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"#!/usr/bin/python\nprint(\"Hello, World!\")\nfor i in range(5):\n print(i)"),await waitAsync(50),assertEqual("Autodetect","Detects Python",codeInputElement.getAttribute("language"),"python"),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"body, html {\n height: 100%;\n background-color: blue;\n color: red;\n}"),await waitAsync(50),assertEqual("Autodetect","Detects CSS",codeInputElement.getAttribute("language"),"css")),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"// hello /\\S/g\nhe('llo', /\\s/g);\nhello"),a.selectionStart=a.selectionEnd=0,await waitAsync(50),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"f",ctrlKey:!0}));let k=codeInputElement.querySelectorAll(".code-input_find-and-replace_dialog input"),l=k[0],m=k[1],n=k[2],o=k[3],p=codeInputElement.querySelectorAll(".code-input_find-and-replace_dialog button"),q=p[0],r=p[1],s=p[2],t=p[3],u=codeInputElement.querySelector(".code-input_find-and-replace_dialog details summary");l.value="/\\s/g",n.click(),await waitAsync(150),testAssertion("FindAndReplace","Finds Case-Sensitive Matches Correctly",confirm("Is there a match on only the lowercase '/\\s/g'?"),"user-judged"),l.value="he[^l]*llo",m.click(),n.click(),await waitAsync(150),testAssertion("FindAndReplace","Finds RegExp Matches Correctly",confirm("Are there matches on all 'he...llo's?"),"user-judged"),u.click(),r.click(),o.value="do('hello",s.click(),await waitAsync(50),assertEqual("FindAndReplace","Replaces Once Correctly",a.value,"// hello /\\S/g\ndo('hello', /\\s/g);\nhello"),q.click(),codeInputElement.querySelector(".code-input_find-and-replace_dialog").dispatchEvent(new KeyboardEvent("keydown",{key:"Escape"})),codeInputElement.querySelector(".code-input_find-and-replace_dialog").dispatchEvent(new KeyboardEvent("keyup",{key:"Escape"})),assertEqual("FindAndReplace","Selection Start on Focused Match when Dialog Exited",a.selectionStart,3),assertEqual("FindAndReplace","Selection End on Focused Match when Dialog Exited",a.selectionEnd,8),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"h",ctrlKey:!0})),l.value="",l.focus(),allowInputEvents(l),addText(l,"hello"),await waitAsync(200),o.value="hi",t.click(),assertEqual("FindAndReplace","Replaces All Correctly",a.value,"// hi /\\S/g\ndo('hi', /\\s/g);\nhi"),codeInputElement.querySelector(".code-input_find-and-replace_dialog").dispatchEvent(new KeyboardEvent("keydown",{key:"Escape"})),codeInputElement.querySelector(".code-input_find-and-replace_dialog").dispatchEvent(new KeyboardEvent("keyup",{key:"Escape"})),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line"),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0}));let v=codeInputElement.querySelector(".code-input_go-to-line_dialog input");v.value="1",v.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),v.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Line Only",a.selectionStart,0),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0})),v.value="3:18",v.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),v.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Line and Column",a.selectionStart,45),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0})),v.value="10",v.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),v.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Rejects Out-of-range Line",v.classList.contains("code-input_go-to-line_error"),!0),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0})),v.value="2:12",v.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),v.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Rejects Out-of-range Column",v.classList.contains("code-input_go-to-line_error"),!0),a.dispatchEvent(new KeyboardEvent("keydown",{cancelable:!0,key:"g",ctrlKey:!0})),v.value="sausages",v.dispatchEvent(new KeyboardEvent("keydown",{key:"Enter"})),v.dispatchEvent(new KeyboardEvent("keyup",{key:"Enter"})),assertEqual("GoToLine","Rejects Invalid Input",v.classList.contains("code-input_go-to-line_error"),!0),assertEqual("GoToLine","Stays open when Rejects Input",v.parentElement.classList.contains("code-input_go-to-line_hidden-dialog"),!1),v.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape"})),v.dispatchEvent(new KeyboardEvent("keyup",{key:"Escape"})),assertEqual("GoToLine","Exits when Esc pressed",v.parentElement.classList.contains("code-input_go-to-line_hidden-dialog"),!0),a.selectionStart=a.selectionEnd=a.value.length,addText(a,"\nfor(let i = 0; i < 100; i++) {\n for(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n }\n}\n{\n // This is indented\n}"),a.selectionStart=0,a.selectionEnd=a.value.length,a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!1})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!1})),assertEqual("Indent","Indents Lines",a.value," // 7 times table\n let i = 1;\n while(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n // That's my code.\n // This is another comment\n // Another\n // Line\n for(let i = 0; i < 100; i++) {\n for(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n }\n }\n {\n // This is indented\n }"),a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!0})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!0})),assertEqual("Indent","Unindents Lines",a.value,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line\nfor(let i = 0; i < 100; i++) {\n for(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n }\n}\n{\n // This is indented\n}"),a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!0})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!0})),assertEqual("Indent","Unindents Lines where some are already fully unindented",a.value,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line\nfor(let i = 0; i < 100; i++) {\nfor(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n}\n}\n{\n// This is indented\n}"),a.selectionStart=255,a.selectionEnd=274,a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!1})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!1})),assertEqual("Indent","Indents Lines by Selection",a.value,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line\nfor(let i = 0; i < 100; i++) {\nfor(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n}\n}\n{\n // This is indented\n}"),a.selectionStart=265,a.selectionEnd=265,a.dispatchEvent(new KeyboardEvent("keydown",{key:"Tab",shiftKey:!0})),a.dispatchEvent(new KeyboardEvent("keyup",{key:"Tab",shiftKey:!0})),assertEqual("Indent","Unindents Lines by Selection",a.value,"// 7 times table\nlet i = 1;\nwhile(i <= 12) { console.log(`7 x ${i} = ${7*i}`) }\n// That's my code.\n// This is another comment\n// Another\n// Line\nfor(let i = 0; i < 100; i++) {\nfor(let j = i; j < 100; j++) {\n // Here's some code\n console.log(i,j);\n}\n}\n{\n// This is indented\n}"),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),testAddingText("Indent-AutoCloseBrackets",a,function(a){addText(a,`function printTriples(max) {\nfor(let i = 0; i < max-2; i++) {\nfor(let j = 0; j < max-1; j++) {\nfor(let k = 0; k < max; k++) {\nconsole.log(i,j,k);\n}\n//Hmmm...\n}//Test auto-unindent\n{`,!0),move(a,1),backspace(a)},"function printTriples(max) {\n for(let i = 0; i < max-2; i++) {\n for(let j = 0; j < max-1; j++) {\n for(let k = 0; k < max; k++) {\n console.log(i,j,k);\n }\n //Hmmm...\n }//Test auto-unindent\n {\n }\n }\n }\n}",221,221),b?(addText(a,"\nlet x = 1;\nlet y = 2;\nconsole.log(`${x} + ${y} = ${x+y}`);"),move(a,-4),a.selectionStart-=35,await waitAsync(50),assertEqual("SelectTokenCallbacks","Number of Selected Tokens",codeInputElement.querySelectorAll(".in-selection").length,13),assertEqual("SelectTokenCallbacks","Number of Selected .hljs-string Tokens",codeInputElement.querySelectorAll(".hljs-string.in-selection").length,0),assertEqual("SelectTokenCallbacks","Number of Selected .hljs-subst Tokens",codeInputElement.querySelectorAll(".hljs-subst.in-selection").length,2)):(addText(a,"\n[(),((),'Hi')]"),await waitAsync(50),move(a,-2),await waitAsync(50),assertEqual("SelectTokenCallbacks","Number of Selected Braces 1",codeInputElement.getElementsByClassName("brace-hover").length,2),move(a,1),await waitAsync(50),assertEqual("SelectTokenCallbacks","Number of Selected Braces 2",codeInputElement.getElementsByClassName("brace-hover").length,4)),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),addText(a,"\"Some special characters: \x96,\x01\x03,\x02...\""),a.selectionStart=a.value.length-4,a.selectionEnd=a.value.length,await waitAsync(50),testAssertion("SpecialChars","Displays Correctly",confirm("Do the special characters read (0096),(0001)(0003),(0002) and align with the ellipsis? (OK=Yes)"),"user-judged"),a.selectionStart=0,a.selectionEnd=a.value.length,backspace(a),fetch(new Request("https://cdn.jsdelivr.net/gh/webcoder49/code-input@2.1/code-input.js")).then(a=>a.text()).then(b=>{a.value="// code-input v2.1: A large code file (not the latest version!)\n// Editing this here should give little latency.\n\n"+b,a.selectionStart=112,a.selectionEnd=112,addText(a,"\n",!0),document.getElementById("collapse-results").setAttribute("open",!0)}),testsFailed?(document.querySelector("h2").style.backgroundColor="red",document.querySelector("h2").textContent="Some Tests have Failed."):(document.querySelector("h2").style.backgroundColor="lightgreen",document.querySelector("h2").textContent="All Tests have Passed.")}
|