Skip to content

Commit 5787919

Browse files
Merge pull request #197 from SwiftFiddle/codemirror
Use CodeMirror
2 parents 530a808 + 7b4f751 commit 5787919

File tree

7 files changed

+135
-102
lines changed

7 files changed

+135
-102
lines changed

Public/css/common.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ body {
4242
#syntax-container {
4343
font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
4444
font-size: 11pt;
45-
line-height: 1.5;
45+
line-height: 1.4;
4646
}
4747

4848
.lined .nav-link {

Public/css/editor.css

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
#editor-container {
2-
position: relative;
3-
height: 100%;
4-
line-height: 1.5;
1+
.CodeMirror {
2+
font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
3+
font-size: 11pt;
4+
line-height: 1.4;
5+
}
6+
7+
.editor-marker-start {
8+
border-left: 1px solid rgb(81, 101, 255);
9+
background-color: rgba(81, 101, 255, 0.25);
510
}
611

712
.editor-marker {
8-
position: absolute;
9-
border: 1px solid rgb(81, 101, 255);
13+
border-top: 1px solid rgb(81, 101, 255);
14+
border-bottom: 1px solid rgb(81, 101, 255);
15+
background-color: rgba(81, 101, 255, 0.25);
16+
}
17+
18+
.editor-marker-end {
19+
border-right: 1px solid rgb(81, 101, 255);
1020
background-color: rgba(81, 101, 255, 0.25);
1121
}

Public/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
<main class="flex-grow-1 invisible">
9898
<div class="row row-cols-2 g-0 h-100">
9999
<div class="col">
100-
<pre id="editor-container">#(defaultSampleCode)</pre>
100+
<textarea id="editor-container" class="h-100 d-none">#(defaultSampleCode)</textarea>
101101
</div>
102102
<div class="col">
103103
<div class="tab-content">

Public/js/app.js

Lines changed: 9 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
"use strict";
22

33
import { Tooltip } from "bootstrap";
4+
import { Editor } from "./editor.js";
45
import { StructureView } from "./structure_view.js";
56
import { SyntaxView } from "./syntax_view.js";
67
import { StatisticsView } from "./statistics_view.js";
78
import { WebSocketClient } from "./websocket.js";
89
import { debounce } from "./debounce.js";
910

10-
import "../css/editor.css";
11-
12-
import "ace-builds/src-min-noconflict/ace";
13-
import "ace-builds/src-min-noconflict/ext-language_tools";
14-
import "ace-builds/src-min-noconflict/mode-swift";
15-
import "ace-builds/src-min-noconflict/theme-xcode";
16-
const Range = ace.require("ace/range").Range;
17-
1811
export class App {
1912
get contentViewHeight() {
2013
const headerHeight = document.querySelector("header").clientHeight;
@@ -24,30 +17,7 @@ export class App {
2417
}
2518

2619
constructor() {
27-
this.editor = ace.edit("editor-container");
28-
this.editor.setTheme("ace/theme/xcode");
29-
this.editor.session.setMode("ace/mode/swift");
30-
this.editor.$blockScrolling = Infinity;
31-
this.editor.setOptions({
32-
tabSize: 2,
33-
useSoftTabs: true,
34-
autoScrollEditorIntoView: true,
35-
fontFamily:
36-
"Menlo, Consolas, 'DejaVu Sans Mono', 'Ubuntu Mono', monospace",
37-
fontSize: "11pt",
38-
showInvisibles: false,
39-
enableAutoIndent: true,
40-
enableBasicAutocompletion: true,
41-
enableSnippets: true,
42-
enableLiveAutocompletion: true,
43-
scrollPastEnd: 0.5, // Overscroll
44-
wrap: "free",
45-
displayIndentGuides: true,
46-
});
47-
this.editor.renderer.setOptions({
48-
showFoldWidgets: false,
49-
showPrintMargin: false,
50-
});
20+
this.editor = new Editor(document.getElementById("editor-container"));
5121

5222
this.structureView = new StructureView(
5323
document.getElementById("structure")
@@ -72,7 +42,7 @@ export class App {
7242
const updateOnTextChange = debounce(() => {
7343
this.update();
7444
}, 400);
75-
this.editor.on("change", (change) => {
45+
this.editor.on("change", () => {
7646
updateOnTextChange();
7747
});
7848

@@ -107,33 +77,6 @@ export class App {
10777
formatter.send({ code: this.editor.getValue() });
10878
});
10979

110-
const dropZone = document.getElementById("editor-container");
111-
dropZone.addEventListener(
112-
"dragover",
113-
(event) => {
114-
event.stopPropagation();
115-
event.preventDefault();
116-
event.dataTransfer.dropEffect = "copy";
117-
},
118-
false
119-
);
120-
dropZone.addEventListener(
121-
"drop",
122-
(event) => {
123-
event.stopPropagation();
124-
event.preventDefault();
125-
126-
const files = event.dataTransfer.files;
127-
const reader = new FileReader();
128-
reader.onload = (event) => {
129-
this.editor.setValue(event.target.result);
130-
this.editor.clearSelection();
131-
};
132-
reader.readAsText(files[0], "UTF-8");
133-
},
134-
false
135-
);
136-
13780
const onresize = debounce(() => {
13881
this.onresize();
13982
}, 200);
@@ -203,14 +146,7 @@ export class App {
203146
updateStructure(structureData) {
204147
this.structureView.update(structureData);
205148
this.structureView.onmouseover = (event, target, data) => {
206-
this.editor.selection.setRange(
207-
new Range(
208-
data.range.startRow - 1,
209-
data.range.startColumn - 1,
210-
data.range.endRow - 1,
211-
data.range.endColumn - 1
212-
)
213-
);
149+
this.editor.setSelection(data.range);
214150
};
215151
}
216152

@@ -223,27 +159,18 @@ export class App {
223159

224160
this.statisticsView.onmouseover = (event, target, ranges) => {
225161
for (const range of ranges) {
226-
this.editor.session.addMarker(
227-
new Range(
228-
range.startRow - 1,
229-
range.startColumn - 1,
230-
range.endRow - 1,
231-
range.endColumn - 1
232-
),
233-
"editor-marker",
234-
"text"
235-
);
162+
this.editor.markText(range);
236163
}
237164
};
238165
this.statisticsView.onmouseout = (event, target) => {
239-
const markers = this.editor.session.getMarkers();
240-
for (const [key, value] of Object.entries(markers)) {
241-
this.editor.session.removeMarker(value.id);
242-
}
166+
this.editor.clearMarks();
243167
};
244168
}
245169

246170
onresize() {
171+
document.querySelector(".CodeMirror").style.height = this.contentViewHeight;
172+
this.editor.refresh();
173+
247174
document.getElementById("structure").style.height = this.contentViewHeight;
248175
document.getElementById("syntax-container").style.height =
249176
this.contentViewHeight;

Public/js/editor.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"use strict";
2+
3+
import "codemirror/lib/codemirror.css";
4+
5+
import CodeMirror from "codemirror";
6+
import "codemirror/mode/swift/swift";
7+
import "codemirror/addon/edit/matchbrackets";
8+
import "codemirror/addon/edit/closebrackets";
9+
10+
import "../css/editor.css";
11+
12+
export class Editor {
13+
constructor(container) {
14+
this.container = container;
15+
16+
this.init();
17+
}
18+
19+
init() {
20+
this.editor = CodeMirror.fromTextArea(this.container, {
21+
autoCloseBrackets: true,
22+
lineNumbers: true,
23+
lineWrapping: true,
24+
matchBrackets: true,
25+
mode: "swift",
26+
screenReaderLabel: "Source code editor",
27+
tabSize: 2,
28+
});
29+
this.editor.setSize("100%", "100%");
30+
31+
this.editor.on("drop", (editor, event) => {
32+
event.preventDefault();
33+
event.stopPropagation();
34+
35+
const files = event.dataTransfer.files;
36+
if (files.length === 0) {
37+
return;
38+
}
39+
const reader = new FileReader();
40+
reader.onload = (event) => {
41+
this.editor.setValue(event.target.result);
42+
};
43+
reader.readAsText(files[0], "UTF-8");
44+
});
45+
}
46+
47+
getValue() {
48+
return this.editor.getValue();
49+
}
50+
51+
setValue(value) {
52+
this.editor.setValue(value);
53+
}
54+
55+
setSelection(range) {
56+
this.editor.setSelection(
57+
{ ch: range.startColumn - 1, line: range.startRow - 1 },
58+
{ ch: range.endColumn - 1, line: range.endRow - 1 },
59+
{ scroll: false }
60+
);
61+
}
62+
63+
clearSelection() {
64+
this.editor.setCursor({ ch: 0, line: 0 });
65+
}
66+
67+
markText(range) {
68+
return this.editor.markText(
69+
{ ch: range.startColumn - 1, line: range.startRow - 1 },
70+
{ ch: range.endColumn - 1, line: range.endRow - 1 },
71+
{
72+
className: "editor-marker",
73+
startStyle: "editor-marker-start",
74+
endStyle: "editor-marker-end",
75+
}
76+
);
77+
}
78+
79+
clearMarks() {
80+
this.editor.getAllMarks().forEach((mark) => {
81+
mark.clear();
82+
});
83+
}
84+
85+
focus() {
86+
this.editor.focus();
87+
}
88+
89+
refresh() {
90+
this.editor.refresh();
91+
}
92+
93+
on(event, callback) {
94+
this.editor.on(event, callback);
95+
}
96+
}

package-lock.json

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"@fortawesome/pro-regular-svg-icons": "6.4.0",
1212
"@fortawesome/pro-solid-svg-icons": "6.4.0",
1313
"@popperjs/core": "2.11.8",
14-
"ace-builds": "1.22.0",
1514
"bootstrap": "5.2.3",
15+
"codemirror": "5.65.13",
1616
"datatables.net-bs5": "1.13.4",
1717
"plausible-tracker": "0.3.8",
1818
"reconnecting-websocket": "4.4.0"

0 commit comments

Comments
 (0)