@webcoder49/code-input 2.1.0 → 2.2.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/CONTRIBUTING.md +11 -1
- package/README.md +17 -8
- package/code-input.css +47 -22
- package/code-input.d.ts +65 -4
- package/code-input.js +127 -176
- package/code-input.min.css +1 -1
- package/code-input.min.js +1 -1
- package/package.json +1 -1
- package/plugins/README.md +21 -6
- package/plugins/auto-close-brackets.js +61 -0
- package/plugins/auto-close-brackets.min.js +1 -0
- package/plugins/autocomplete.js +18 -11
- package/plugins/autocomplete.min.js +1 -1
- package/plugins/autodetect.js +4 -4
- package/plugins/autodetect.min.js +1 -1
- package/plugins/find-and-replace.css +145 -0
- package/plugins/find-and-replace.js +652 -0
- package/plugins/find-and-replace.min.css +1 -0
- package/plugins/find-and-replace.min.js +1 -0
- package/plugins/go-to-line.css +77 -0
- package/plugins/go-to-line.js +157 -0
- package/plugins/go-to-line.min.css +1 -0
- package/plugins/go-to-line.min.js +1 -0
- package/plugins/indent.js +71 -11
- package/plugins/indent.min.js +1 -1
- package/plugins/special-chars.css +0 -4
- package/plugins/special-chars.js +60 -58
- package/plugins/special-chars.min.css +1 -1
- package/plugins/special-chars.min.js +1 -1
- package/plugins/test.js +1 -2
- package/plugins/test.min.js +1 -1
- package/tests/hljs.html +54 -0
- package/tests/prism.html +55 -0
- package/tests/tester.js +529 -0
- package/tests/tester.min.js +18 -0
- package/plugins/debounce-update.js +0 -40
- package/plugins/debounce-update.min.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
codeInput.plugins.FindAndReplace=class extends codeInput.Plugin{useCtrlF=!1;useCtrlH=!1;constructor(a=!0,b=!0){super([]),this.useCtrlF=a,this.useCtrlH=b}afterElementsAdded(a){const b=a.textareaElement;this.useCtrlF&&b.addEventListener("keydown",b=>{this.checkCtrlF(a,b)}),this.useCtrlH&&b.addEventListener("keydown",b=>{this.checkCtrlH(a,b)})}afterHighlight(a){a.pluginData.findAndReplace==null||a.pluginData.findAndReplace.dialog==null||a.pluginData.findAndReplace.dialog.classList.contains("code-input_find-and-replace_hidden-dialog")||(a.pluginData.findAndReplace.dialog.findMatchState.rehighlightMatches(),this.updateMatchDescription(a.pluginData.findAndReplace.dialog),0==a.pluginData.findAndReplace.dialog.findMatchState.numMatches&&a.pluginData.findAndReplace.dialog.findInput.classList.add("code-input_find-and-replace_error"))}text2RegExp(a,b,c){return new RegExp(c?a:a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),b?"g":"gi")}updateMatchDescription(a){a.matchDescription.textContent=0==a.findInput.value.length?"Search for matches in your code.":0>=a.findMatchState.numMatches?"No matches.":1==a.findMatchState.numMatches?"1 match found.":`${a.findMatchState.focusedMatchID+1} of ${a.findMatchState.numMatches} matches.`}updateFindMatches(a){let b=a.findInput.value;setTimeout(()=>{if(b==a.findInput.value){if(a.findMatchState.clearMatches(),0<b.length){try{a.findMatchState.updateMatches(this.text2RegExp(a.findInput.value,a.findCaseSensitiveCheckbox.checked,a.findRegExpCheckbox.checked))}catch(b){if(b instanceof SyntaxError){a.findInput.classList.add("code-input_find-and-replace_error");let c=b.message.split(": ");return void(a.matchDescription.textContent="Error: "+c[c.length-1])}throw b}0<a.findMatchState.numMatches?a.findInput.classList.remove("code-input_find-and-replace_error"):a.findInput.classList.add("code-input_find-and-replace_error")}this.updateMatchDescription(a)}},100)}checkFindPrompt(a,b,c){"Enter"==c.key&&(a.findMatchState.nextMatch(),this.updateMatchDescription(a))}checkReplacePrompt(a,b,c){"Enter"==c.key&&(a.findMatchState.replaceOnce(a.replaceInput.value),this.updateMatchDescription(a))}cancelPrompt(a,b,c){c.preventDefault(),a.textarea.focus(),0<a.findMatchState.numMatches?(b.textareaElement.selectionStart=a.findMatchState.matchStartIndexes[a.findMatchState.focusedMatchID],b.textareaElement.selectionEnd=a.findMatchState.matchEndIndexes[a.findMatchState.focusedMatchID]):(b.textareaElement.selectionStart=a.selectionStart,b.textareaElement.selectionEnd=a.selectionEnd),a.findMatchState.clearMatches(),a.classList.add("code-input_find-and-replace_hidden-dialog")}showPrompt(a,b){if(a.pluginData.findAndReplace==null||a.pluginData.findAndReplace.dialog==null){const c=a.textareaElement,d=document.createElement("div"),e=document.createElement("input"),f=document.createElement("input"),g=document.createElement("input"),h=document.createElement("code"),i=document.createElement("input"),j=document.createElement("details"),k=document.createElement("summary"),l=document.createElement("div"),m=document.createElement("button"),n=document.createElement("button"),o=document.createElement("button"),p=document.createElement("button"),q=document.createElement("span");l.appendChild(m),l.appendChild(n),l.appendChild(o),l.appendChild(p),l.appendChild(q),d.appendChild(l),d.appendChild(e),d.appendChild(g),d.appendChild(f),d.appendChild(h),j.appendChild(k),j.appendChild(i),d.appendChild(j),d.className="code-input_find-and-replace_dialog",e.spellcheck=!1,e.placeholder="Find",f.setAttribute("type","checkbox"),f.title="Match Case Sensitive",f.classList.add("code-input_find-and-replace_case-sensitive-checkbox"),g.setAttribute("type","checkbox"),g.title="Use JavaScript Regular Expression",g.classList.add("code-input_find-and-replace_reg-exp-checkbox"),h.textContent="Search for matches in your code.",h.classList.add("code-input_find-and-replace_match-description"),k.innerText="Replace",i.spellcheck=!1,i.placeholder="Replace with",m.innerText="\u2193",m.title="Find Next Occurence",n.innerText="\u2191",n.title="Find Previous Occurence",o.className="code-input_find-and-replace_button-hidden",o.innerText="Replace",o.title="Replace This Occurence",p.className="code-input_find-and-replace_button-hidden",p.innerText="Replace All",p.title="Replace All Occurences",m.addEventListener("click",a=>{a.preventDefault(),d.findMatchState.nextMatch(),this.updateMatchDescription(d)}),n.addEventListener("click",()=>{event.preventDefault(),d.findMatchState.previousMatch(),this.updateMatchDescription(d)}),o.addEventListener("click",a=>{a.preventDefault(),d.findMatchState.replaceOnce(i.value),o.focus()}),p.addEventListener("click",a=>{a.preventDefault(),d.findMatchState.replaceAll(i.value),p.focus()}),j.addEventListener("toggle",()=>{o.classList.toggle("code-input_find-and-replace_button-hidden"),p.classList.toggle("code-input_find-and-replace_button-hidden")}),d.findMatchState=new codeInput.plugins.FindAndReplace.FindMatchState(a),d.codeInput=a,d.textarea=c,d.findInput=e,d.findCaseSensitiveCheckbox=f,d.findRegExpCheckbox=g,d.matchDescription=h,d.replaceInput=i,d.replaceDropdown=j,this.checkCtrlH&&e.addEventListener("keydown",a=>{a.ctrlKey&&"h"==a.key&&(a.preventDefault(),j.setAttribute("open",!0))}),e.addEventListener("keypress",a=>{"Enter"==a.key&&a.preventDefault()}),i.addEventListener("keypress",a=>{"Enter"==a.key&&a.preventDefault()}),d.addEventListener("keyup",b=>{"Escape"==b.key&&this.cancelPrompt(d,a,b)}),e.addEventListener("keyup",b=>{this.checkFindPrompt(d,a,b)}),e.addEventListener("input",()=>{this.updateFindMatches(d)}),f.addEventListener("click",()=>{this.updateFindMatches(d)}),g.addEventListener("click",()=>{this.updateFindMatches(d)}),i.addEventListener("keyup",b=>{this.checkReplacePrompt(d,a,b),i.focus()}),q.addEventListener("click",b=>{this.cancelPrompt(d,a,b)}),a.dialogContainerElement.appendChild(d),a.pluginData.findAndReplace={dialog:d},e.focus(),b&&j.setAttribute("open",!0),d.selectionStart=a.textareaElement.selectionStart,d.selectionEnd=a.textareaElement.selectionEnd}else a.pluginData.findAndReplace.dialog.classList.remove("code-input_find-and-replace_hidden-dialog"),a.pluginData.findAndReplace.dialog.findInput.focus(),b?a.pluginData.findAndReplace.dialog.replaceDropdown.setAttribute("open",!0):a.pluginData.findAndReplace.dialog.replaceDropdown.removeAttribute("open"),this.updateFindMatches(a.pluginData.findAndReplace.dialog),a.pluginData.findAndReplace.dialog.selectionStart=a.textareaElement.selectionStart,a.pluginData.findAndReplace.dialog.selectionEnd=a.textareaElement.selectionEnd}checkCtrlF(a,b){b.ctrlKey&&"f"==b.key&&(b.preventDefault(),this.showPrompt(a,!1))}checkCtrlH(a,b){b.ctrlKey&&"h"==b.key&&(b.preventDefault(),this.showPrompt(a,!0))}};const CODE_INPUT_FIND_AND_REPLACE_MATCH_BLOCK_SIZE=500;codeInput.plugins.FindAndReplace.FindMatchState=class{codeInput=null;lastValue=null;lastSearchRegexp=null;numMatches=0;focusedMatchID=0;matchStartIndexes=[];matchEndIndexes=[];focusedMatchStartIndex=0;matchBlocksHighlighted=[];constructor(a){this.focusedMatchStartIndex=a.textareaElement.selectionStart,this.codeInput=a}clearMatches(){this.numMatches=0,this.matchStartIndexes=[],this.matchEndIndexes=[];let a=this.codeInput.codeElement.querySelectorAll(".code-input_find-and-replace_temporary-span");for(let b=0;b<a.length;b++)a[b].parentElement.replaceChild(new Text(a[b].textContent),a[b]);let b=this.codeInput.codeElement.querySelectorAll(".code-input_find-and-replace_find-match");for(let a=0;a<b.length;a++)b[a].removeAttribute("data-code-input_find-and-replace_match-id"),b[a].classList.remove("code-input_find-and-replace_find-match"),b[a].classList.remove("code-input_find-and-replace_find-match-focused")}updateMatches(a){var b=Math.floor;this.lastSearchRegexp=a,this.lastValue=this.codeInput.value;let c,d=0;this.matchStartIndexes=[],this.matchEndIndexes=[],this.matchBlocksHighlighted=[];let e=b(this.focusedMatchID/CODE_INPUT_FIND_AND_REPLACE_MATCH_BLOCK_SIZE);for(let b=0;b<e;b++)this.matchBlocksHighlighted.push(!1);for(this.matchBlocksHighlighted.push(!0);null!==(c=a.exec(this.codeInput.value));){let a=c[0];if(0==a.length)throw SyntaxError("Causes an infinite loop");let e=b(d/CODE_INPUT_FIND_AND_REPLACE_MATCH_BLOCK_SIZE);this.matchBlocksHighlighted.length<e&&this.matchBlocksHighlighted.push(!1),this.matchBlocksHighlighted[e]&&this.highlightMatch(d,this.codeInput.codeElement,c.index,c.index+a.length),this.matchStartIndexes.push(c.index),this.matchEndIndexes.push(c.index+a.length),d++}this.numMatches=d,0<this.numMatches&&this.focusMatch()}rehighlightMatches(){this.updateMatches(this.lastSearchRegexp),this.focusMatch()}replaceOnce(a){0<this.numMatches&&a!=this.codeInput.value.substring(0,this.matchStartIndexes[this.focusedMatchID],this.matchEndIndexes[this.focusedMatchID])&&(this.focusedMatchStartIndex+=a.length,this.codeInput.textareaElement.focus(),this.codeInput.textareaElement.selectionStart=this.matchStartIndexes[this.focusedMatchID],this.codeInput.textareaElement.selectionEnd=this.matchEndIndexes[this.focusedMatchID],document.execCommand("insertText",!1,a))}replaceAll(a){const b=a.length;let c=0;for(let d=0;d<this.numMatches;d++)this.codeInput.textareaElement.focus(),this.codeInput.textareaElement.selectionStart=this.matchStartIndexes[d]+c,this.codeInput.textareaElement.selectionEnd=this.matchEndIndexes[d]+c,c+=b-(this.matchEndIndexes[d]-this.matchStartIndexes[d]),document.execCommand("insertText",!1,a)}nextMatch(){this.focusMatch((this.focusedMatchID+1)%this.numMatches)}previousMatch(){this.focusMatch((this.focusedMatchID+this.numMatches-1)%this.numMatches)}focusMatch(a=void 0){if(a===void 0){for(a=0;a<this.matchStartIndexes.length&&this.matchStartIndexes[a]<this.focusedMatchStartIndex;)a++;a>=this.matchStartIndexes.length&&(a=0)}this.focusedMatchStartIndex=this.matchStartIndexes[a],this.focusedMatchID=a;let b=this.codeInput.codeElement.querySelectorAll(".code-input_find-and-replace_find-match-focused");for(let c=0;c<b.length;c++)b[c].classList.remove("code-input_find-and-replace_find-match-focused");let c=Math.floor(a/CODE_INPUT_FIND_AND_REPLACE_MATCH_BLOCK_SIZE);if(!this.matchBlocksHighlighted[c]){this.matchBlocksHighlighted[c]=!0;for(let a=CODE_INPUT_FIND_AND_REPLACE_MATCH_BLOCK_SIZE*c;a<CODE_INPUT_FIND_AND_REPLACE_MATCH_BLOCK_SIZE*(c+1);a++)this.highlightMatch(a,this.codeInput.codeElement,this.matchStartIndexes[a],this.matchEndIndexes[a])}let d=this.codeInput.codeElement.querySelectorAll(`.code-input_find-and-replace_find-match[data-code-input_find-and-replace_match-id="${a}"]`);for(let b=0;b<d.length;b++)d[b].classList.add("code-input_find-and-replace_find-match-focused");0<d.length&&this.codeInput.scrollTo(d[0].offsetLeft-this.codeInput.offsetWidth/2,d[0].offsetTop-this.codeInput.offsetHeight/2)}highlightMatch(a,b,c,d){for(let e=0;e<b.childNodes.length;e++){let f=b.childNodes[e],g=f.textContent,h=!1;if(3==f.nodeType){if(e+1<b.childNodes.length&&3==b.childNodes[e+1].nodeType){b.childNodes[e+1].textContent=f.textContent+b.childNodes[e+1].textContent,b.removeChild(f),e--;continue}h=!0;let a=document.createElement("span");a.textContent=g,a.classList.add("code-input_find-and-replace_temporary-span"),b.replaceChild(a,f),f=a}if(0>=c){if(g.length>=d){if(h){let b=document.createElement("span");b.classList.add("code-input_find-and-replace_find-match"),b.setAttribute("data-code-input_find-and-replace_match-id",a),b.classList.add("code-input_find-and-replace_temporary-span"),b.textContent=g.substring(0,d),"\n"==b.textContent[0]&&b.classList.add("code-input_find-and-replace_start-newline");let c=g.substring(d);return f.textContent=c,f.insertAdjacentElement("beforebegin",b),void e++}return void this.highlightMatch(a,f,0,d)}f.classList.add("code-input_find-and-replace_find-match"),f.setAttribute("data-code-input_find-and-replace_match-id",a),"\n"==f.textContent[0]&&f.classList.add("code-input_find-and-replace_start-newline")}else if(g.length>c){if(!h)this.highlightMatch(a,f,c,d);else if(g.length>d){let b=document.createElement("span");b.classList.add("code-input_find-and-replace_temporary-span"),b.textContent=g.substring(0,c);let h=g.substring(c,d);f.textContent=h,f.classList.add("code-input_find-and-replace_find-match"),f.setAttribute("data-code-input_find-and-replace_match-id",a),"\n"==f.textContent[0]&&f.classList.add("code-input_find-and-replace_start-newline");let i=document.createElement("span");i.classList.add("code-input_find-and-replace_temporary-span"),i.textContent=g.substring(d),f.insertAdjacentElement("beforebegin",b),f.insertAdjacentElement("afterend",i),e++}else{let b=g.substring(0,c);f.textContent=b;let d=document.createElement("span");d.classList.add("code-input_find-and-replace_find-match"),d.setAttribute("data-code-input_find-and-replace_match-id",a),d.classList.add("code-input_find-and-replace_temporary-span"),d.textContent=g.substring(c),"\n"==d.textContent[0]&&d.classList.add("code-input_find-and-replace_start-newline"),f.insertAdjacentElement("afterend",d),e++}if(g.length>d)return}c-=g.length,d-=g.length}}};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
@keyframes code-input_go-to-line_roll-in {
|
|
2
|
+
0% {opacity: 0; transform: translateY(-34px);}
|
|
3
|
+
100% {opacity: 1; transform: translateY(0px);}
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
@keyframes code-input_go-to-line_roll-out {
|
|
7
|
+
0% {opacity: 1; transform: translateY(0px);}
|
|
8
|
+
100% {opacity: 0; transform: translateY(-34px);}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.code-input_go-to-line_dialog {
|
|
12
|
+
position: absolute;
|
|
13
|
+
top: 0; right: 14px;
|
|
14
|
+
height: 28px;
|
|
15
|
+
padding: 6px;
|
|
16
|
+
padding-top: 8px;
|
|
17
|
+
border: solid 1px #00000044;
|
|
18
|
+
background-color: white;
|
|
19
|
+
border-radius: 6px;
|
|
20
|
+
box-shadow: 0 .2em 1em .2em rgba(0, 0, 0, 0.16);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.code-input_go-to-line_dialog:not(.code-input_go-to-line_hidden-dialog) {
|
|
24
|
+
animation: code-input_go-to-line_roll-in .2s;
|
|
25
|
+
opacity: 1;
|
|
26
|
+
pointer-events: all;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.code-input_go-to-line_dialog.code-input_go-to-line_hidden-dialog {
|
|
30
|
+
animation: code-input_go-to-line_roll-out .2s;
|
|
31
|
+
opacity: 0;
|
|
32
|
+
pointer-events: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.code-input_go-to-line_dialog input::placeholder {
|
|
36
|
+
font-size: 80%;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.code-input_go-to-line_dialog input {
|
|
40
|
+
position: relative;
|
|
41
|
+
width: 240px; height: 32px; top: -3px;
|
|
42
|
+
font-size: large;
|
|
43
|
+
color: #000000aa;
|
|
44
|
+
border: 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.code-input_go-to-line_dialog input.code-input_go-to-line_error {
|
|
48
|
+
color: #ff0000aa;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.code-input_go-to-line_dialog input:focus {
|
|
52
|
+
outline: none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Cancel icon */
|
|
56
|
+
.code-input_go-to-line_dialog span {
|
|
57
|
+
display: inline-block;
|
|
58
|
+
width: 24px;
|
|
59
|
+
line-height: 24px;
|
|
60
|
+
font-family: system-ui;
|
|
61
|
+
font-size: 22px;
|
|
62
|
+
font-weight: 500;
|
|
63
|
+
text-align: center;
|
|
64
|
+
border-radius: 50%;
|
|
65
|
+
color: black;
|
|
66
|
+
opacity: 0.6;
|
|
67
|
+
vertical-align: top;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.code-input_go-to-line_dialog span:before {
|
|
71
|
+
content: "\00d7";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.code-input_go-to-line_dialog span:hover {
|
|
75
|
+
opacity: .8;
|
|
76
|
+
background-color: #00000018;
|
|
77
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add basic Go-To-Line (Ctrl+G by default) functionality to the code editor.
|
|
3
|
+
* Files: go-to-line.js / go-to-line.css
|
|
4
|
+
*/
|
|
5
|
+
codeInput.plugins.GoToLine = class extends codeInput.Plugin {
|
|
6
|
+
useCtrlG = false;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a go-to-line command plugin to pass into a template
|
|
10
|
+
* @param {boolean} useCtrlG Should Ctrl+G be overriden for go-to-line functionality? If not, you can trigger it yourself using (instance of this plugin)`.showPrompt(code-input element)`.
|
|
11
|
+
*/
|
|
12
|
+
constructor(useCtrlG = true) {
|
|
13
|
+
super([]); // No observed attributes
|
|
14
|
+
this.useCtrlG = useCtrlG;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Add keystroke events */
|
|
18
|
+
afterElementsAdded(codeInput) {
|
|
19
|
+
const textarea = codeInput.textareaElement;
|
|
20
|
+
if(this.useCtrlG) {
|
|
21
|
+
textarea.addEventListener('keydown', (event) => { this.checkCtrlG(codeInput, event); });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Called with a dialog box keyup event to check the validity of the line number entered and submit the dialog if Enter is pressed */
|
|
26
|
+
checkPrompt(dialog, event) {
|
|
27
|
+
// Line number(:column number)
|
|
28
|
+
const lines = dialog.textarea.value.split('\n');
|
|
29
|
+
const maxLineNo = lines.length;
|
|
30
|
+
const lineNo = Number(dialog.input.value.split(':')[0]);
|
|
31
|
+
let columnNo = 0; // Means go to start of indented line
|
|
32
|
+
let maxColumnNo = 1;
|
|
33
|
+
const querySplitByColons = dialog.input.value.split(':');
|
|
34
|
+
if(querySplitByColons.length > 2) return dialog.input.classList.add('code-input_go-to-line_error');
|
|
35
|
+
|
|
36
|
+
if (event.key == 'Escape') return this.cancelPrompt(dialog, event);
|
|
37
|
+
|
|
38
|
+
if (dialog.input.value) {
|
|
39
|
+
if (!/^[0-9:]*$/.test(dialog.input.value) || lineNo < 1 || lineNo > maxLineNo) {
|
|
40
|
+
return dialog.input.classList.add('code-input_go-to-line_error');
|
|
41
|
+
} else {
|
|
42
|
+
// Check if line:column
|
|
43
|
+
if(querySplitByColons.length >= 2) {
|
|
44
|
+
columnNo = Number(querySplitByColons[1]);
|
|
45
|
+
maxColumnNo = lines[lineNo-1].length;
|
|
46
|
+
}
|
|
47
|
+
if(columnNo < 0 || columnNo > maxColumnNo) {
|
|
48
|
+
return dialog.input.classList.add('code-input_go-to-line_error');
|
|
49
|
+
} else {
|
|
50
|
+
dialog.input.classList.remove('code-input_go-to-line_error');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (event.key == 'Enter') {
|
|
56
|
+
this.goTo(dialog.textarea, lineNo, columnNo);
|
|
57
|
+
this.cancelPrompt(dialog, event);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Called with a dialog box keyup event to close and clear the dialog box */
|
|
62
|
+
cancelPrompt(dialog, event) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
dialog.textarea.focus();
|
|
65
|
+
|
|
66
|
+
// Remove dialog after animation
|
|
67
|
+
dialog.classList.add('code-input_go-to-line_hidden-dialog');
|
|
68
|
+
dialog.input.value = "";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Show a search-like dialog prompting line number.
|
|
73
|
+
* @param {codeInput.CodeInput} codeInput the `<code-input>` element.
|
|
74
|
+
*/
|
|
75
|
+
showPrompt(codeInput) {
|
|
76
|
+
if(codeInput.pluginData.goToLine == undefined || codeInput.pluginData.goToLine.dialog == undefined) {
|
|
77
|
+
const textarea = codeInput.textareaElement;
|
|
78
|
+
|
|
79
|
+
const dialog = document.createElement('div');
|
|
80
|
+
const input = document.createElement('input');
|
|
81
|
+
const cancel = document.createElement('span');
|
|
82
|
+
|
|
83
|
+
dialog.appendChild(input);
|
|
84
|
+
dialog.appendChild(cancel);
|
|
85
|
+
|
|
86
|
+
dialog.className = 'code-input_go-to-line_dialog';
|
|
87
|
+
input.spellcheck = false;
|
|
88
|
+
input.placeholder = "Line:Column / Line no. then Enter";
|
|
89
|
+
dialog.codeInput = codeInput;
|
|
90
|
+
dialog.textarea = textarea;
|
|
91
|
+
dialog.input = input;
|
|
92
|
+
|
|
93
|
+
input.addEventListener('keypress', (event) => {
|
|
94
|
+
/* Stop enter from submitting form */
|
|
95
|
+
if (event.key == 'Enter') event.preventDefault();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
input.addEventListener('keyup', (event) => { return this.checkPrompt(dialog, event); });
|
|
99
|
+
cancel.addEventListener('click', (event) => { this.cancelPrompt(dialog, event); });
|
|
100
|
+
|
|
101
|
+
codeInput.dialogContainerElement.appendChild(dialog);
|
|
102
|
+
codeInput.pluginData.goToLine = {dialog: dialog};
|
|
103
|
+
input.focus();
|
|
104
|
+
} else {
|
|
105
|
+
codeInput.pluginData.goToLine.dialog.classList.remove("code-input_go-to-line_hidden-dialog");
|
|
106
|
+
codeInput.pluginData.goToLine.dialog.input.focus();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Set the cursor on the first non-space char of textarea's nth line, or to the columnNo-numbered character in the line if it's not 0; and scroll it into view */
|
|
111
|
+
goTo(textarea, lineNo, columnNo = 0) {
|
|
112
|
+
let fontSize;
|
|
113
|
+
let lineHeight;
|
|
114
|
+
let scrollAmount;
|
|
115
|
+
let topPadding;
|
|
116
|
+
let cursorPos = -1;
|
|
117
|
+
let lines = textarea.value.split('\n');
|
|
118
|
+
|
|
119
|
+
if (lineNo > 0 && lineNo <= lines.length) {
|
|
120
|
+
if (textarea.computedStyleMap) {
|
|
121
|
+
fontSize = textarea.computedStyleMap().get('font-size').value;
|
|
122
|
+
lineHeight = fontSize * textarea.computedStyleMap().get('line-height').value;
|
|
123
|
+
} else {
|
|
124
|
+
fontSize = document.defaultView.getComputedStyle(textarea, null).getPropertyValue('font-size').split('px')[0];
|
|
125
|
+
lineHeight = document.defaultView.getComputedStyle(textarea, null).getPropertyValue('line-height').split('px')[0];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// scroll amount and initial top padding (3 lines above, if possible)
|
|
129
|
+
scrollAmount = (lineNo > 3 ? lineNo - 3 : 1) * lineHeight;
|
|
130
|
+
topPadding = (lineHeight - fontSize) / 2;
|
|
131
|
+
|
|
132
|
+
if (lineNo > 1) {
|
|
133
|
+
// cursor positon just after n - 1 full lines
|
|
134
|
+
cursorPos = lines.slice(0, lineNo - 1).join('\n').length;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// scan first non-space char in nth line
|
|
138
|
+
if (columnNo == 0) {
|
|
139
|
+
do cursorPos++; while (textarea.value[cursorPos] != '\n' && /\s/.test(textarea.value[cursorPos]));
|
|
140
|
+
} else {
|
|
141
|
+
cursorPos += 1 + columnNo - 1;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
textarea.scrollTop = scrollAmount - topPadding;
|
|
145
|
+
textarea.setSelectionRange(cursorPos, cursorPos);
|
|
146
|
+
textarea.click();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* Event handler for keydown event that makes Ctrl+G open go to line dialog */
|
|
151
|
+
checkCtrlG(codeInput, event) {
|
|
152
|
+
if (event.ctrlKey && event.key == 'g') {
|
|
153
|
+
event.preventDefault();
|
|
154
|
+
this.showPrompt(codeInput);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@keyframes code-input_go-to-line_roll-in{0%{opacity:0;transform:translateY(-34px)}100%{opacity:1;transform:translateY(0)}}@keyframes code-input_go-to-line_roll-out{0%{opacity:1;transform:translateY(0)}100%{opacity:0;transform:translateY(-34px)}}.code-input_go-to-line_dialog{position:absolute;top:0;right:14px;height:28px;padding:6px;padding-top:8px;border:solid 1px #00000044;background-color:#fff;border-radius:6px;box-shadow:0 .2em 1em .2em rgba(0,0,0,.16)}.code-input_go-to-line_dialog:not(.code-input_go-to-line_hidden-dialog){animation:code-input_go-to-line_roll-in .2s;opacity:1;pointer-events:all}.code-input_go-to-line_dialog.code-input_go-to-line_hidden-dialog{animation:code-input_go-to-line_roll-out .2s;opacity:0;pointer-events:none}.code-input_go-to-line_dialog input::placeholder{font-size:80%}.code-input_go-to-line_dialog input{position:relative;width:240px;height:32px;top:-3px;font-size:large;color:#000000aa;border:0}.code-input_go-to-line_dialog input.code-input_go-to-line_error{color:#ff0000aa}.code-input_go-to-line_dialog input:focus{outline:0}.code-input_go-to-line_dialog span{display:inline-block;width:24px;line-height:24px;font-family:system-ui;font-size:22px;font-weight:500;text-align:center;border-radius:50%;color:#000;opacity:.6;vertical-align:top}.code-input_go-to-line_dialog span:before{content:"\00d7"}.code-input_go-to-line_dialog span:hover{opacity:.8;background-color:#00000018}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
codeInput.plugins.GoToLine=class extends codeInput.Plugin{useCtrlG=!1;constructor(a=!0){super([]),this.useCtrlG=a}afterElementsAdded(a){const b=a.textareaElement;this.useCtrlG&&b.addEventListener("keydown",b=>{this.checkCtrlG(a,b)})}checkPrompt(a,b){const c=a.textarea.value.split("\n"),d=c.length,e=+a.input.value.split(":")[0];let f=0,g=1;const h=a.input.value.split(":");if(2<h.length)return a.input.classList.add("code-input_go-to-line_error");if("Escape"==b.key)return this.cancelPrompt(a,b);if(a.input.value){if(!/^[0-9:]*$/.test(a.input.value)||1>e||e>d)return a.input.classList.add("code-input_go-to-line_error");if(2<=h.length&&(f=+h[1],g=c[e-1].length),0>f||f>g)return a.input.classList.add("code-input_go-to-line_error");a.input.classList.remove("code-input_go-to-line_error")}"Enter"==b.key&&(this.goTo(a.textarea,e,f),this.cancelPrompt(a,b))}cancelPrompt(a,b){b.preventDefault(),a.textarea.focus(),a.classList.add("code-input_go-to-line_hidden-dialog"),a.input.value=""}showPrompt(a){if(a.pluginData.goToLine==null||a.pluginData.goToLine.dialog==null){const b=a.textareaElement,c=document.createElement("div"),d=document.createElement("input"),e=document.createElement("span");c.appendChild(d),c.appendChild(e),c.className="code-input_go-to-line_dialog",d.spellcheck=!1,d.placeholder="Line:Column / Line no. then Enter",c.codeInput=a,c.textarea=b,c.input=d,d.addEventListener("keypress",a=>{"Enter"==a.key&&a.preventDefault()}),d.addEventListener("keyup",a=>this.checkPrompt(c,a)),e.addEventListener("click",a=>{this.cancelPrompt(c,a)}),a.dialogContainerElement.appendChild(c),a.pluginData.goToLine={dialog:c},d.focus()}else a.pluginData.goToLine.dialog.classList.remove("code-input_go-to-line_hidden-dialog"),a.pluginData.goToLine.dialog.input.focus()}goTo(a,b,c=0){let d,e,f,g,h=-1,i=a.value.split("\n");if(0<b&&b<=i.length){if(a.computedStyleMap?(d=a.computedStyleMap().get("font-size").value,e=d*a.computedStyleMap().get("line-height").value):(d=document.defaultView.getComputedStyle(a,null).getPropertyValue("font-size").split("px")[0],e=document.defaultView.getComputedStyle(a,null).getPropertyValue("line-height").split("px")[0]),f=(3<b?b-3:1)*e,g=(e-d)/2,1<b&&(h=i.slice(0,b-1).join("\n").length),0==c)do h++;while("\n"!=a.value[h]&&/\s/.test(a.value[h]));else h+=1+c-1;a.scrollTop=f-g,a.setSelectionRange(h,h),a.click()}}checkCtrlG(a,b){b.ctrlKey&&"g"==b.key&&(b.preventDefault(),this.showPrompt(a))}};
|
package/plugins/indent.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Add indentation using the `Tab` key, and auto-indents after a newline, as well as making it
|
|
3
3
|
* possible to indent/unindent multiple lines using Tab/Shift+Tab
|
|
4
4
|
* Files: indent.js
|
|
5
5
|
*/
|
|
6
6
|
codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
bracketPairs = {}; // No bracket-auto-indentation used when {}
|
|
9
9
|
indentation = "\t";
|
|
10
10
|
indentationNumChars = 1;
|
|
11
11
|
|
|
@@ -13,11 +13,12 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
13
13
|
* Create an indentation plugin to pass into a template
|
|
14
14
|
* @param {Boolean} defaultSpaces Should the Tab key enter spaces rather than tabs? Defaults to false.
|
|
15
15
|
* @param {Number} numSpaces How many spaces is each tab character worth? Defaults to 4.
|
|
16
|
+
* @param {Object} bracketPairs Opening brackets mapped to closing brackets, default and example {"(": ")", "[": "]", "{": "}"}. All brackets must only be one character, and this can be left as null to remove bracket-based indentation behaviour.
|
|
16
17
|
*/
|
|
17
|
-
constructor(defaultSpaces=false, numSpaces=4) {
|
|
18
|
+
constructor(defaultSpaces=false, numSpaces=4, bracketPairs={"(": ")", "[": "]", "{": "}"}) {
|
|
18
19
|
super([]); // No observed attributes
|
|
19
20
|
|
|
20
|
-
this.
|
|
21
|
+
this.bracketPairs = bracketPairs;
|
|
21
22
|
if(defaultSpaces) {
|
|
22
23
|
this.indentation = "";
|
|
23
24
|
for(let i = 0; i < numSpaces; i++) {
|
|
@@ -31,9 +32,10 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
31
32
|
afterElementsAdded(codeInput) {
|
|
32
33
|
let textarea = codeInput.textareaElement;
|
|
33
34
|
textarea.addEventListener('keydown', (event) => { this.checkTab(codeInput, event); this.checkEnter(codeInput, event); this.checkBackspace(codeInput, event); });
|
|
35
|
+
textarea.addEventListener('beforeinput', (event) => { this.checkCloseBracket(codeInput, event); });
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
/*
|
|
38
|
+
/* Deal with the Tab key causing indentation, and Tab+Selection indenting / Shift+Tab+Selection unindenting lines */
|
|
37
39
|
checkTab(codeInput, event) {
|
|
38
40
|
if(event.key != "Tab") {
|
|
39
41
|
return;
|
|
@@ -93,16 +95,17 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
93
95
|
inputElement.selectionEnd = selectionEndI;
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
codeInput.
|
|
98
|
+
codeInput.value = inputElement.value;
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
/* Deal with new lines retaining indentation */
|
|
99
102
|
checkEnter(codeInput, event) {
|
|
100
103
|
if(event.key != "Enter") {
|
|
101
104
|
return;
|
|
102
105
|
}
|
|
103
106
|
event.preventDefault(); // Stop normal \n only
|
|
104
107
|
|
|
105
|
-
let inputElement = codeInput.
|
|
108
|
+
let inputElement = codeInput.textareaElement;
|
|
106
109
|
let lines = inputElement.value.split("\n");
|
|
107
110
|
let letterI = 0;
|
|
108
111
|
let currentLineI = lines.length - 1;
|
|
@@ -135,6 +138,39 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
135
138
|
lines[currentLineI] = lines[currentLineI].substring(0, cursorPosInLine);
|
|
136
139
|
}
|
|
137
140
|
|
|
141
|
+
let bracketThreeLinesTriggered = false;
|
|
142
|
+
let furtherIndentation = "";
|
|
143
|
+
if(this.bracketPairs != null) {
|
|
144
|
+
for(let openingBracket in this.bracketPairs) {
|
|
145
|
+
if(lines[currentLineI][lines[currentLineI].length-1] == openingBracket) {
|
|
146
|
+
let closingBracket = this.bracketPairs[openingBracket];
|
|
147
|
+
if(textAfterCursor.length > 0 && textAfterCursor[0] == closingBracket) {
|
|
148
|
+
// Create new line and then put textAfterCursor on yet another line:
|
|
149
|
+
// {
|
|
150
|
+
// |CARET|
|
|
151
|
+
// }
|
|
152
|
+
bracketThreeLinesTriggered = true;
|
|
153
|
+
for (let i = 0; i < numberIndents+1; i++) {
|
|
154
|
+
furtherIndentation += this.indentation;
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
// Just create new line:
|
|
158
|
+
// {
|
|
159
|
+
// |CARET|
|
|
160
|
+
numberIndents++;
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
} else {
|
|
164
|
+
// Check whether brackets cause unindent
|
|
165
|
+
let closingBracket = this.bracketPairs[openingBracket];
|
|
166
|
+
if(textAfterCursor.length > 0 && textAfterCursor[0] == closingBracket) {
|
|
167
|
+
numberIndents--;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
138
174
|
// insert our indents and any text from the previous line that might have been after the line break
|
|
139
175
|
for (let i = 0; i < numberIndents; i++) {
|
|
140
176
|
newLine += this.indentation;
|
|
@@ -143,6 +179,10 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
143
179
|
// save the current cursor position
|
|
144
180
|
let selectionStartI = inputElement.selectionStart;
|
|
145
181
|
|
|
182
|
+
if(bracketThreeLinesTriggered) {
|
|
183
|
+
document.execCommand("insertText", false, "\n" + furtherIndentation); // Write indented line
|
|
184
|
+
numberIndents += 1; // Reflects the new indent
|
|
185
|
+
}
|
|
146
186
|
document.execCommand("insertText", false, "\n" + newLine); // Write new line, including auto-indentation
|
|
147
187
|
|
|
148
188
|
// move cursor to new position
|
|
@@ -153,17 +193,18 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
153
193
|
// Scroll down to cursor if necessary
|
|
154
194
|
let paddingTop = Number(getComputedStyle(inputElement).paddingTop.replace("px", ""));
|
|
155
195
|
let lineHeight = Number(getComputedStyle(inputElement).lineHeight.replace("px", ""));
|
|
156
|
-
let inputHeight = Number(getComputedStyle(
|
|
196
|
+
let inputHeight = Number(getComputedStyle(codeInput).height.replace("px", ""));
|
|
157
197
|
if(currentLineI*lineHeight + lineHeight*2 + paddingTop >= inputElement.scrollTop + inputHeight) { // Cursor too far down
|
|
158
|
-
|
|
198
|
+
codeInput.scrollBy(0, Number(getComputedStyle(inputElement).lineHeight.replace("px", "")));
|
|
159
199
|
}
|
|
160
200
|
|
|
161
|
-
codeInput.
|
|
201
|
+
codeInput.value = inputElement.value;
|
|
162
202
|
}
|
|
163
203
|
|
|
204
|
+
/* Deal with one 'tab' of spaces-based-indentation being deleted by each backspace, rather than one space */
|
|
164
205
|
checkBackspace(codeInput, event) {
|
|
165
206
|
if(event.key != "Backspace" || this.indentationNumChars == 1) {
|
|
166
|
-
return; // Normal backspace
|
|
207
|
+
return; // Normal backspace when indentation of 1
|
|
167
208
|
}
|
|
168
209
|
|
|
169
210
|
let inputElement = codeInput.textareaElement;
|
|
@@ -175,4 +216,23 @@ codeInput.plugins.Indent = class extends codeInput.Plugin {
|
|
|
175
216
|
document.execCommand("delete", false, "");
|
|
176
217
|
}
|
|
177
218
|
}
|
|
219
|
+
|
|
220
|
+
/* Deal with the typing of closing brackets causing a decrease in indentation */
|
|
221
|
+
checkCloseBracket(codeInput, event) {
|
|
222
|
+
if(codeInput.textareaElement.selectionStart != codeInput.textareaElement.selectionEnd) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
for(let openingBracket in this.bracketPairs) {
|
|
227
|
+
let closingBracket = this.bracketPairs[openingBracket];
|
|
228
|
+
if(event.data == closingBracket) {
|
|
229
|
+
// Closing bracket unindents line
|
|
230
|
+
if(codeInput.value.substring(codeInput.textareaElement.selectionStart - this.indentationNumChars, codeInput.textareaElement.selectionStart) == this.indentation) {
|
|
231
|
+
// Indentation before cursor = delete it
|
|
232
|
+
codeInput.textareaElement.selectionStart -= this.indentationNumChars;
|
|
233
|
+
document.execCommand("delete", false, "");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
178
238
|
}
|
package/plugins/indent.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
codeInput.plugins.Indent=class extends codeInput.Plugin{
|
|
1
|
+
codeInput.plugins.Indent=class extends codeInput.Plugin{bracketPairs={};indentation="\t";indentationNumChars=1;constructor(a=!1,b=4,c={"(":")","[":"]","{":"}"}){if(super([]),this.bracketPairs=c,a){this.indentation="";for(let a=0;a<b;a++)this.indentation+=" ";this.indentationNumChars=b}}afterElementsAdded(a){let b=a.textareaElement;b.addEventListener("keydown",b=>{this.checkTab(a,b),this.checkEnter(a,b),this.checkBackspace(a,b)}),b.addEventListener("beforeinput",b=>{this.checkCloseBracket(a,b)})}checkTab(a,b){var c=Math.max;if("Tab"==b.key){let d=a.textareaElement;if(b.preventDefault(),!b.shiftKey&&d.selectionStart==d.selectionEnd)document.execCommand("insertText",!1,this.indentation);else{let a=d.value.split("\n"),e=0,f=d.selectionStart,g=d.selectionEnd;for(let h=0;h<a.length;h++)(f<=e+a[h].length&&g>=e+1||f==g&&f<=e+a[h].length+1&&g>=e)&&(b.shiftKey?a[h].substring(0,this.indentationNumChars)==this.indentation&&(d.selectionStart=e,d.selectionEnd=e+this.indentationNumChars,document.execCommand("delete",!1,""),f>e&&(f=c(f-this.indentationNumChars,e)),g-=this.indentationNumChars,e-=this.indentationNumChars):(d.selectionStart=e,d.selectionEnd=e,document.execCommand("insertText",!1,this.indentation),f>e&&(f+=this.indentationNumChars),g+=this.indentationNumChars,e+=this.indentationNumChars)),e+=a[h].length+1;d.selectionStart=f,d.selectionEnd=g}a.value=d.value}}checkEnter(a,b){if("Enter"!=b.key)return;b.preventDefault();let c=a.textareaElement,d=c.value.split("\n"),e=0,f=d.length-1,g="",h=0;for(let g=0;g<d.length;g++)if(e+=d[g].length+1,c.selectionEnd<=e){f=g;break}let j=d[f].length-(e-c.selectionEnd)+1;for(let c=0;c<j&&d[f].substring(c,c+this.indentationNumChars)==this.indentation;c+=this.indentationNumChars)h++;let k="";j!=d[f].length&&(k=d[f].substring(j),d[f]=d[f].substring(0,j));let l=!1,m="";if(null!=this.bracketPairs)for(let a in this.bracketPairs)if(d[f][d[f].length-1]==a){let b=this.bracketPairs[a];if(0<k.length&&k[0]==b){l=!0;for(let a=0;a<h+1;a++)m+=this.indentation}else h++;break}else{let b=this.bracketPairs[a];if(0<k.length&&k[0]==b){h--;break}}for(let c=0;c<h;c++)g+=this.indentation;let n=c.selectionStart;l&&(document.execCommand("insertText",!1,"\n"+m),h+=1),document.execCommand("insertText",!1,"\n"+g),c.selectionStart=n+h*this.indentationNumChars+1,c.selectionEnd=c.selectionStart;let o=+getComputedStyle(c).paddingTop.replace("px",""),p=+getComputedStyle(c).lineHeight.replace("px",""),q=+getComputedStyle(a).height.replace("px","");f*p+2*p+o>=c.scrollTop+q&&a.scrollBy(0,+getComputedStyle(c).lineHeight.replace("px","")),a.value=c.value}checkBackspace(a,b){if("Backspace"==b.key&&1!=this.indentationNumChars){let c=a.textareaElement;c.selectionStart==c.selectionEnd&&a.value.substring(c.selectionStart-this.indentationNumChars,c.selectionStart)==this.indentation&&(c.selectionStart-=this.indentationNumChars,b.preventDefault(),document.execCommand("delete",!1,""))}}checkCloseBracket(a,b){if(a.textareaElement.selectionStart==a.textareaElement.selectionEnd)for(let c in this.bracketPairs){let d=this.bracketPairs[c];b.data==d&&a.value.substring(a.textareaElement.selectionStart-this.indentationNumChars,a.textareaElement.selectionStart)==this.indentation&&(a.textareaElement.selectionStart-=this.indentationNumChars,document.execCommand("delete",!1,""))}}};
|
|
@@ -24,10 +24,6 @@
|
|
|
24
24
|
--code-input_special-chars_F: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAAXNSR0IArs4c6QAAAB5JREFUGFdj/P///38GKGAEcRgZGRlBfDAHtwxMGQDZZhP+BnB1kwAAAABJRU5ErkJggg==');
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
.code-input_special-char_container { /* pre element */
|
|
28
|
-
font-size: 20px;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
27
|
.code-input_special-char {
|
|
32
28
|
display: inline-block;
|
|
33
29
|
position: relative;
|