qword 1.0.3 → 1.1.0
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/ChangeLog +14 -0
- package/assets/style.css +10 -10
- package/client/_clipboard.js +30 -33
- package/client/_clipboard.spec.js +160 -0
- package/client/content.d.ts +8 -0
- package/client/content.js +14 -0
- package/client/content.spec.js +69 -0
- package/client/create.d.ts +32 -0
- package/client/create.js +95 -0
- package/client/create.spec.js +192 -0
- package/client/decorations.d.ts +40 -0
- package/client/decorations.js +110 -0
- package/client/decorations.spec.js +135 -0
- package/client/dom.d.ts +7 -0
- package/client/dom.js +17 -0
- package/client/dom.spec.js +78 -0
- package/client/editor.d.ts +72 -0
- package/client/editor.js +164 -0
- package/client/editor.spec.js +307 -0
- package/client/events.d.ts +7 -0
- package/client/events.js +8 -0
- package/client/events.spec.js +100 -0
- package/client/highlight.d.ts +3 -0
- package/client/highlight.js +82 -0
- package/client/highlight.spec.js +28 -0
- package/client/history.d.ts +4 -0
- package/client/history.js +16 -0
- package/client/history.spec.js +57 -0
- package/client/index.d.ts +60 -0
- package/client/index.js +37 -0
- package/client/loadremote.js +10 -4
- package/client/options.d.ts +30 -0
- package/client/options.js +59 -0
- package/client/options.spec.js +157 -0
- package/client/position.d.ts +21 -0
- package/client/position.js +33 -0
- package/client/position.spec.js +176 -0
- package/client/qword.js +141 -416
- package/client/scroll.d.ts +10 -0
- package/client/scroll.js +9 -0
- package/client/scroll.spec.js +58 -0
- package/client/types.d.ts +24 -0
- package/dist/qword.js +175 -1
- package/dist/qword.js.map +1 -1
- package/dist-dev/qword.js +544 -660
- package/package.json +30 -14
- package/server/edit.js +8 -3
- package/server/edit.spec.js +101 -0
- package/test/errors.ts +21 -0
- package/test/types.ts +134 -0
- package/client/codemirror/show-trailing.js +0 -54
- package/client/codemirror/use-soft-tabs.js +0 -38
- package/client/set-key-map.js +0 -3
- package/dist/2b22a33a0a80bb926bbc.png +0 -1
- package/dist/8e9019bd86255ac9a618.png +0 -1
- package/dist/codemirror.js +0 -2
- package/dist/codemirror.js.map +0 -1
- package/dist/dword.js +0 -2
- package/dist/dword.js.map +0 -1
- package/dist-dev/2b22a33a0a80bb926bbc.png +0 -1
- package/dist-dev/8e9019bd86255ac9a618.png +0 -1
- package/dist-dev/codemirror.js +0 -104
- package/dist-dev/dword.js +0 -960
- package/modules/codemirror-emmet/dist/emmet.js +0 -48661
- package/modules/codemirror-emmet/dist/emmet.min.js +0 -8
- package/modules/codemirror-emmet/dist/emmetPlugin.js +0 -840
- package/modules/codemirror-emmet/dist/emmetPlugin.min.js +0 -1
- package/modules/codemirror-emmet/dist/index.html +0 -46
- package/modules/jshint/README.md +0 -114
- package/modules/jshint/dist/jshint-rhino.js +0 -32143
- package/modules/jshint/dist/jshint.js +0 -32141
- package/modules/jshint/package.json +0 -77
package/client/qword.js
CHANGED
|
@@ -1,458 +1,183 @@
|
|
|
1
1
|
import '../css/qword.css';
|
|
2
|
-
import {EditorState, Compartment} from '@codemirror/state';
|
|
3
|
-
import {
|
|
4
|
-
EditorView,
|
|
5
|
-
keymap,
|
|
6
|
-
lineNumbers,
|
|
7
|
-
highlightActiveLine,
|
|
8
|
-
} from '@codemirror/view';
|
|
9
|
-
import {
|
|
10
|
-
history,
|
|
11
|
-
historyKeymap,
|
|
12
|
-
defaultKeymap,
|
|
13
|
-
} from '@codemirror/commands';
|
|
14
|
-
import {
|
|
15
|
-
syntaxHighlighting,
|
|
16
|
-
defaultHighlightStyle,
|
|
17
|
-
} from '@codemirror/language';
|
|
18
|
-
import {oneDark} from '@codemirror/theme-one-dark';
|
|
19
|
-
import {javascript} from '@codemirror/lang-javascript';
|
|
20
|
-
import {json} from '@codemirror/lang-json';
|
|
21
|
-
import {html} from '@codemirror/lang-html';
|
|
22
|
-
import Emitify from 'emitify';
|
|
23
2
|
import * as smalltalk from 'smalltalk';
|
|
24
3
|
import jssha from 'jssha';
|
|
25
4
|
import load from 'load.js';
|
|
26
5
|
import {createPatch} from 'daffy';
|
|
27
6
|
import * as restafary from 'restafary/client';
|
|
28
|
-
import {tryCatch} from 'try-catch';
|
|
29
|
-
import {vim} from '@replit/codemirror-vim';
|
|
30
7
|
import {tryToCatch} from 'try-to-catch';
|
|
8
|
+
import {tryCatch} from 'try-catch';
|
|
9
|
+
import Editor from './editor.js';
|
|
31
10
|
import Story from './story.js';
|
|
32
|
-
import loadRemote, {loadModules, loadOptions} from './loadremote.js';
|
|
33
11
|
import _clipboard from './_clipboard.js';
|
|
34
12
|
import save from './save.js';
|
|
35
13
|
import _initSocket from './_init-socket.js';
|
|
36
14
|
import _onSave from './_on-save.js';
|
|
37
15
|
import showMessage from './show-message.js';
|
|
16
|
+
import loadRemote, {loadModules, loadOptions} from './loadremote.js';
|
|
38
17
|
|
|
39
18
|
const noop = () => {};
|
|
40
19
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
20
|
+
export default class Qword extends Editor {
|
|
21
|
+
constructor(element, options = {}, callback = noop) {
|
|
22
|
+
super(element, options);
|
|
23
|
+
|
|
24
|
+
this._TITLE = 'Qword';
|
|
25
|
+
this._story = Story();
|
|
26
|
+
this._savedValue = '';
|
|
27
|
+
this._filename = '';
|
|
28
|
+
this._maxSize = options.maxSize || 512_000;
|
|
29
|
+
this._PREFIX = options.prefix || '/qword';
|
|
30
|
+
this._prefixSocket = options.prefixSocket || '/qword';
|
|
31
|
+
this._socketPath = options.socketPath || '';
|
|
32
|
+
|
|
33
|
+
restafary.prefix(`${this._PREFIX}/api/v1/fs`);
|
|
34
|
+
this
|
|
35
|
+
._init()
|
|
36
|
+
.then(() => callback(this));
|
|
51
37
|
}
|
|
52
38
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
this._Emitter = Emitify();
|
|
73
|
-
|
|
74
|
-
this._view = null;
|
|
75
|
-
this._pendingValue = null;
|
|
76
|
-
|
|
77
|
-
this._modeCompartment = new Compartment();
|
|
78
|
-
this._keymapCompartment = new Compartment();
|
|
79
|
-
this._fontCompartment = new Compartment();
|
|
80
|
-
this._langCompartment = new Compartment();
|
|
81
|
-
this._historyCompartment = new Compartment();
|
|
82
|
-
this._vimCompartment = new Compartment();
|
|
83
|
-
|
|
84
|
-
this._Element.addEventListener('drop', this._onDrop.bind(this));
|
|
85
|
-
this._Element.addEventListener('dragover', this._onDragOver.bind(this));
|
|
86
|
-
|
|
87
|
-
this
|
|
88
|
-
._init()
|
|
89
|
-
.then(() => callback(this));
|
|
90
|
-
|
|
91
|
-
this._patch = (path, patch) => {
|
|
92
|
-
this._patchHttp(path, patch);
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
this._write = (path, result) => {
|
|
96
|
-
this._writeHttp(path, result);
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
Qword.prototype._init = async function() {
|
|
101
|
-
const prefix = this._PREFIX;
|
|
102
|
-
|
|
103
|
-
const [error, config] = await tryToCatch(load.json, this._PREFIX + '/edit.json');
|
|
104
|
-
|
|
105
|
-
if (error)
|
|
106
|
-
return smalltalk.alert(this._TITLE, 'Could not load edit.json!');
|
|
107
|
-
|
|
108
|
-
this._Config = config;
|
|
109
|
-
|
|
110
|
-
await Promise.all([
|
|
111
|
-
loadOptions(prefix),
|
|
112
|
-
loadModules(prefix),
|
|
113
|
-
]);
|
|
114
|
-
|
|
115
|
-
await loadRemote('socket', {
|
|
116
|
-
prefix: this._socketPath,
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
restafary.prefix(`${this._PREFIX}/api/v1/fs`);
|
|
120
|
-
|
|
121
|
-
this._initEditor();
|
|
39
|
+
async _init() {
|
|
40
|
+
const [error, config] = await tryToCatch(load.json, `${this._PREFIX}/edit.json`);
|
|
41
|
+
|
|
42
|
+
if (error)
|
|
43
|
+
return smalltalk.alert(this._TITLE, 'Could not load edit.json!');
|
|
44
|
+
|
|
45
|
+
this._Config = config;
|
|
46
|
+
|
|
47
|
+
await Promise.all([
|
|
48
|
+
loadOptions(this._PREFIX),
|
|
49
|
+
loadModules(this._PREFIX),
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
await loadRemote('socket', {
|
|
53
|
+
prefix: this._socketPath,
|
|
54
|
+
});
|
|
55
|
+
this._initSocket();
|
|
56
|
+
}
|
|
122
57
|
|
|
123
|
-
|
|
124
|
-
this.
|
|
125
|
-
this.
|
|
58
|
+
setValueFirst(name, value) {
|
|
59
|
+
this.setModeForPath(name);
|
|
60
|
+
this.setValue(value);
|
|
61
|
+
this._filename = name;
|
|
62
|
+
this._savedValue = value;
|
|
63
|
+
this.clearHistory();
|
|
64
|
+
this.moveCursorTo(0, 0);
|
|
65
|
+
|
|
66
|
+
return this;
|
|
126
67
|
}
|
|
127
68
|
|
|
128
|
-
|
|
69
|
+
sha() {
|
|
70
|
+
const sha = new jssha('SHA-1', 'TEXT');
|
|
71
|
+
sha.update(this.getValue());
|
|
72
|
+
|
|
73
|
+
return sha.getHash('HEX');
|
|
74
|
+
}
|
|
129
75
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
76
|
+
evaluate() {
|
|
77
|
+
if (!this._filename?.endsWith('.js'))
|
|
78
|
+
return smalltalk.alert(this._TITLE, 'JS only');
|
|
79
|
+
|
|
80
|
+
const [error] = tryCatch(new Function(this.getValue()));
|
|
81
|
+
|
|
82
|
+
if (error)
|
|
83
|
+
smalltalk.alert(this._TITLE, error.message);
|
|
84
|
+
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
135
87
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
this._langCompartment.of(javascript()),
|
|
147
|
-
this._vimCompartment.of([]),
|
|
148
|
-
keymap.of([
|
|
149
|
-
...defaultKeymap,
|
|
150
|
-
...historyKeymap, {
|
|
151
|
-
key: 'Mod-s',
|
|
152
|
-
run: () => {
|
|
153
|
-
this.save();
|
|
154
|
-
return true;
|
|
155
|
-
},
|
|
88
|
+
goToLine() {
|
|
89
|
+
const number = Number(prompt('Line number'));
|
|
90
|
+
|
|
91
|
+
if (!number)
|
|
92
|
+
return;
|
|
93
|
+
|
|
94
|
+
const line = this._view.state.doc.line(number);
|
|
95
|
+
this._view.dispatch({
|
|
96
|
+
selection: {
|
|
97
|
+
anchor: line.from,
|
|
156
98
|
},
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const state = EditorState.create({
|
|
163
|
-
doc: '',
|
|
164
|
-
extensions: baseExtensions(),
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
this._view = new EditorView({
|
|
168
|
-
state,
|
|
169
|
-
parent: this._Element,
|
|
170
|
-
});
|
|
99
|
+
scrollIntoView: true,
|
|
100
|
+
});
|
|
101
|
+
this.focus();
|
|
102
|
+
}
|
|
171
103
|
|
|
172
|
-
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
104
|
+
remove(direction) {
|
|
105
|
+
const {state} = this._view;
|
|
106
|
+
const {from, to} = state.selection.main;
|
|
107
|
+
const isCollapsed = from === to;
|
|
108
|
+
|
|
109
|
+
if (direction === 'right') {
|
|
110
|
+
const end = isCollapsed ? to + 1 : to;
|
|
111
|
+
this._view.dispatch({
|
|
112
|
+
changes: {
|
|
113
|
+
from,
|
|
114
|
+
to: end,
|
|
115
|
+
insert: '',
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
const start = isCollapsed ? from - 1 : from;
|
|
120
|
+
|
|
121
|
+
if (start >= 0)
|
|
122
|
+
this._view.dispatch({
|
|
123
|
+
changes: {
|
|
124
|
+
from: start,
|
|
125
|
+
to,
|
|
126
|
+
insert: '',
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
182
131
|
return this;
|
|
183
132
|
}
|
|
184
133
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
return this;
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
Qword.prototype.focus = function() {
|
|
197
|
-
this._view.focus();
|
|
198
|
-
return this;
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
Qword.prototype.getCursor = function() {
|
|
202
|
-
const pos = this._view.state.selection.main.head;
|
|
203
|
-
const line = this._view.state.doc.lineAt(pos);
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
row: line.number - 1,
|
|
207
|
-
column: pos - line.from,
|
|
208
|
-
};
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
Qword.prototype.moveCursorTo = function(row, column = 0) {
|
|
212
|
-
const line = this._view.state.doc.line(row + 1);
|
|
213
|
-
|
|
214
|
-
this._view.dispatch({
|
|
215
|
-
selection: {
|
|
216
|
-
anchor: line.from + column,
|
|
217
|
-
},
|
|
218
|
-
scrollIntoView: true,
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
return this;
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
Qword.prototype.remove = function(direction) {
|
|
225
|
-
const pos = this._view.state.selection.main.head;
|
|
226
|
-
|
|
227
|
-
this._view.dispatch({
|
|
228
|
-
changes: direction === 'right' ? {
|
|
229
|
-
from: pos,
|
|
230
|
-
to: pos + 1,
|
|
231
|
-
} : {
|
|
232
|
-
from: pos - 1,
|
|
233
|
-
to: pos,
|
|
234
|
-
},
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
return this;
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
Qword.prototype.setModeForPath = function(path) {
|
|
241
|
-
const ext = path
|
|
242
|
-
.split('.')
|
|
243
|
-
.pop();
|
|
244
|
-
|
|
245
|
-
let lang = javascript();
|
|
246
|
-
|
|
247
|
-
if (ext === 'json')
|
|
248
|
-
lang = json();
|
|
249
|
-
|
|
250
|
-
if (ext === 'html')
|
|
251
|
-
lang = html();
|
|
252
|
-
|
|
253
|
-
this._view.dispatch({
|
|
254
|
-
effects: this._langCompartment.reconfigure(lang),
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
return this;
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
Qword.prototype.setValueFirst = function(name, value) {
|
|
261
|
-
this.setModeForPath(name);
|
|
262
|
-
this.setValue(value);
|
|
263
|
-
|
|
264
|
-
this._FileName = name;
|
|
265
|
-
this._Value = value;
|
|
266
|
-
|
|
267
|
-
this.clearHistory();
|
|
268
|
-
this.moveCursorTo(0, 0);
|
|
269
|
-
|
|
270
|
-
return this;
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
Qword.prototype.addKeyMap = function(map) {
|
|
274
|
-
const bindings = Object
|
|
275
|
-
.entries(map)
|
|
276
|
-
.map(([key, fn]) => ({
|
|
277
|
-
key,
|
|
278
|
-
run: () => {
|
|
279
|
-
fn.call(this);
|
|
280
|
-
return true;
|
|
134
|
+
selectAll() {
|
|
135
|
+
const {doc} = this._view.state;
|
|
136
|
+
this._view.dispatch({
|
|
137
|
+
selection: {
|
|
138
|
+
anchor: 0,
|
|
139
|
+
head: doc.length,
|
|
281
140
|
},
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
return this;
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
Qword.prototype.on = function(event, fn) {
|
|
292
|
-
this._Emitter.on(event, fn);
|
|
293
|
-
return this;
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
Qword.prototype.emit = function(...args) {
|
|
297
|
-
this._Emitter.emit(...args);
|
|
298
|
-
return this;
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
Qword.prototype.isChanged = function() {
|
|
302
|
-
return this.getValue() !== this._Value;
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
Qword.prototype._diff = function(newValue) {
|
|
306
|
-
return createPatch(this._Value || '', newValue);
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
Qword.prototype._patchHttp = function(path, patch) {
|
|
310
|
-
restafary.patch(path, patch, this._onSave.bind(this));
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
Qword.prototype._writeHttp = function(path, result) {
|
|
314
|
-
restafary.write(path, result, this._onSave.bind(this));
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
Qword.prototype.evaluate = function() {
|
|
318
|
-
if (!this._FileName?.endsWith('.js'))
|
|
319
|
-
return smalltalk.alert(this._TITLE, 'JS only');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
320
145
|
|
|
321
|
-
|
|
146
|
+
enableKey() {
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
322
149
|
|
|
323
|
-
|
|
324
|
-
|
|
150
|
+
cutToClipboard() {
|
|
151
|
+
return this._clipboard('cut');
|
|
152
|
+
}
|
|
325
153
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
Qword.prototype.goToLine = function() {
|
|
330
|
-
const num = Number(prompt('Line number'));
|
|
154
|
+
copyToClipboard() {
|
|
155
|
+
return this._clipboard('copy');
|
|
156
|
+
}
|
|
331
157
|
|
|
332
|
-
|
|
333
|
-
return;
|
|
158
|
+
pasteFromClipboard() {
|
|
159
|
+
return this._clipboard('paste');
|
|
160
|
+
}
|
|
334
161
|
|
|
335
|
-
|
|
162
|
+
_patchHttp(path, patch) {
|
|
163
|
+
restafary.patch(path, patch, this._onSave.bind(this));
|
|
164
|
+
}
|
|
336
165
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
},
|
|
341
|
-
scrollIntoView: true,
|
|
342
|
-
});
|
|
166
|
+
_writeHttp(path, data) {
|
|
167
|
+
restafary.write(path, data, this._onSave.bind(this));
|
|
168
|
+
}
|
|
343
169
|
|
|
344
|
-
|
|
345
|
-
|
|
170
|
+
async _doDiff(path) {
|
|
171
|
+
const equal = await this
|
|
172
|
+
._story
|
|
173
|
+
.checkHash(path)
|
|
174
|
+
.catch(() => false);
|
|
175
|
+
return equal ? '' : createPatch(this._savedValue || '', this.getValue());
|
|
176
|
+
}
|
|
177
|
+
}
|
|
346
178
|
|
|
347
179
|
Qword.prototype._clipboard = _clipboard;
|
|
348
180
|
Qword.prototype.save = save;
|
|
349
181
|
Qword.prototype._onSave = _onSave;
|
|
350
182
|
Qword.prototype._initSocket = _initSocket;
|
|
351
|
-
|
|
352
|
-
Qword.prototype._onDragOver = function(event) {
|
|
353
|
-
event.preventDefault();
|
|
354
|
-
event.dataTransfer.dropEffect = 'copy';
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
Qword.prototype._onDrop = function(event) {
|
|
358
|
-
event.preventDefault();
|
|
359
|
-
|
|
360
|
-
const [file] = event.dataTransfer.files;
|
|
361
|
-
|
|
362
|
-
if (!file)
|
|
363
|
-
return;
|
|
364
|
-
|
|
365
|
-
const reader = new FileReader();
|
|
366
|
-
|
|
367
|
-
reader.onload = (e) => {
|
|
368
|
-
this.setValue(e.target.result);
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
reader.readAsText(file);
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
Qword.prototype.sha = function() {
|
|
375
|
-
const shaObj = new jssha('SHA-1', 'TEXT');
|
|
376
|
-
shaObj.update(this.getValue());
|
|
377
|
-
|
|
378
|
-
return shaObj.getHash('HEX');
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
Qword.prototype.setOption = function(name, value) {
|
|
382
|
-
const preventOverwrite = () => {
|
|
383
|
-
this._Config.options[name] = value;
|
|
384
|
-
};
|
|
385
|
-
|
|
386
|
-
preventOverwrite();
|
|
387
|
-
|
|
388
|
-
if (name === 'keyMap')
|
|
389
|
-
this.setKeyMap(value);
|
|
390
|
-
|
|
391
|
-
return this;
|
|
392
|
-
};
|
|
393
|
-
|
|
394
|
-
Qword.prototype.setOptions = function(options) {
|
|
395
|
-
const theme = EditorView.theme({
|
|
396
|
-
'&': {
|
|
397
|
-
fontSize: options.fontSize,
|
|
398
|
-
fontFamily: options.fontFamily,
|
|
399
|
-
},
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
this._view.dispatch({
|
|
403
|
-
effects: this._fontCompartment.reconfigure(theme),
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
return this;
|
|
407
|
-
};
|
|
408
|
-
|
|
409
183
|
Qword.prototype.showMessage = showMessage;
|
|
410
|
-
|
|
411
|
-
Qword.prototype.setKeyMap = function(mode) {
|
|
412
|
-
this._vimEnabled = mode === 'vim';
|
|
413
|
-
|
|
414
|
-
this._view.dispatch({
|
|
415
|
-
effects: this._vimCompartment.reconfigure(this._vimEnabled ? vim() : []),
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
return this;
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
Qword.prototype._loadOptions = async function() {
|
|
422
|
-
const url = this._PREFIX + '/options.json';
|
|
423
|
-
|
|
424
|
-
if (this._Options)
|
|
425
|
-
return this._Options;
|
|
426
|
-
|
|
427
|
-
const data = await load.json(url);
|
|
428
|
-
|
|
429
|
-
this._Options = data;
|
|
430
|
-
|
|
431
|
-
return data;
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
Qword.prototype.enableKey = function() {
|
|
435
|
-
this._isKey = true;
|
|
436
|
-
return this;
|
|
437
|
-
};
|
|
438
|
-
|
|
439
|
-
Qword.prototype.clearHistory = function() {
|
|
440
|
-
if (!this._view)
|
|
441
|
-
return this;
|
|
442
|
-
|
|
443
|
-
this._view.dispatch({
|
|
444
|
-
effects: this._historyCompartment.reconfigure(this._vimEnabled ? [] : [
|
|
445
|
-
history(),
|
|
446
|
-
keymap.of(historyKeymap),
|
|
447
|
-
]),
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
const {cm} = this._view;
|
|
451
|
-
|
|
452
|
-
cm.state.vim.undoHistory = [];
|
|
453
|
-
cm.state.vim.redoHistory = [];
|
|
454
|
-
cm.state.vim.globalState.jumpList = [];
|
|
455
|
-
|
|
456
|
-
return this;
|
|
457
|
-
};
|
|
458
|
-
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type {EditorView} from '@codemirror/view';
|
|
2
|
+
|
|
3
|
+
export type ScrollInfo = {
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const getScrollInfo: (view: EditorView) => ScrollInfo;
|
|
9
|
+
|
|
10
|
+
export function scrollTo(view: EditorView, left: number, top: number): void;
|
package/client/scroll.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {test} from 'supertape';
|
|
2
|
+
import {EditorState} from '@codemirror/state';
|
|
3
|
+
import {EditorView} from '@codemirror/view';
|
|
4
|
+
import {getScrollInfo, scrollTo} from './scroll.js';
|
|
5
|
+
|
|
6
|
+
function makeView() {
|
|
7
|
+
const element = document.createElement('div');
|
|
8
|
+
document.body.appendChild(element);
|
|
9
|
+
|
|
10
|
+
return new EditorView({
|
|
11
|
+
state: EditorState.create({
|
|
12
|
+
doc: 'hello',
|
|
13
|
+
}),
|
|
14
|
+
parent: element,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
test('scroll: getScrollInfo left is a number', (t) => {
|
|
19
|
+
const view = makeView();
|
|
20
|
+
const result = typeof getScrollInfo(view).left;
|
|
21
|
+
const expected = 'number';
|
|
22
|
+
|
|
23
|
+
view.destroy();
|
|
24
|
+
|
|
25
|
+
t.equal(result, expected);
|
|
26
|
+
t.end();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('scroll: getScrollInfo top is a number', (t) => {
|
|
30
|
+
const view = makeView();
|
|
31
|
+
const result = typeof getScrollInfo(view).top;
|
|
32
|
+
const expected = 'number';
|
|
33
|
+
|
|
34
|
+
view.destroy();
|
|
35
|
+
|
|
36
|
+
t.equal(result, expected);
|
|
37
|
+
t.end();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('scroll: scrollTo sets scrollLeft to 0', (t) => {
|
|
41
|
+
const view = makeView();
|
|
42
|
+
scrollTo(view, 0, 0);
|
|
43
|
+
|
|
44
|
+
view.destroy();
|
|
45
|
+
|
|
46
|
+
t.equal(view.scrollDOM.scrollLeft, 0);
|
|
47
|
+
t.end();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('scroll: scrollTo sets scrollTop to 0', (t) => {
|
|
51
|
+
const view = makeView();
|
|
52
|
+
scrollTo(view, 0, 0);
|
|
53
|
+
|
|
54
|
+
view.destroy();
|
|
55
|
+
|
|
56
|
+
t.equal(view.scrollDOM.scrollTop, 0);
|
|
57
|
+
t.end();
|
|
58
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Character offset into source text (0-indexed, matches CM6) — same convention as putout-editor's codemirror-adapter.
|
|
2
|
+
export type CharOffset = number;
|
|
3
|
+
|
|
4
|
+
// Line/column position — matches CodeMirror's {line, ch} convention.
|
|
5
|
+
export type SourcePosition = {
|
|
6
|
+
line: number;
|
|
7
|
+
ch: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// CodeMirror editor mode string — e.g. 'javascript', 'json', 'html'.
|
|
11
|
+
export type EditorMode = string;
|
|
12
|
+
|
|
13
|
+
// CodeMirror key map name.
|
|
14
|
+
export type KeyMap =
|
|
15
|
+
| 'vim'
|
|
16
|
+
| 'emacs'
|
|
17
|
+
| 'sublime'
|
|
18
|
+
| 'default';
|
|
19
|
+
|
|
20
|
+
// Editor theme name.
|
|
21
|
+
export type EditorTheme = 'nord' | 'default' | 'dark' | 'one-dark';
|
|
22
|
+
|
|
23
|
+
// JavaScript/TypeScript source code.
|
|
24
|
+
export type SourceCode = string;
|