qword 1.0.2 → 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 +22 -0
- package/README.md +2 -3
- 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 -391
- package/client/save.js +2 -2
- 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 -15
- 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,433 +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
|
-
// ✅ FIX: добавили vim 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`);
|
|
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
|
+
}
|
|
120
57
|
|
|
121
|
-
|
|
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;
|
|
67
|
+
}
|
|
122
68
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
this.
|
|
69
|
+
sha() {
|
|
70
|
+
const sha = new jssha('SHA-1', 'TEXT');
|
|
71
|
+
sha.update(this.getValue());
|
|
72
|
+
|
|
73
|
+
return sha.getHash('HEX');
|
|
126
74
|
}
|
|
127
75
|
|
|
128
|
-
|
|
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
|
+
}
|
|
129
87
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
oneDark,
|
|
141
|
-
this._langCompartment.of(javascript()),
|
|
142
|
-
// ✅ FIX: vim теперь через compartment
|
|
143
|
-
this._vimCompartment.of([]),
|
|
144
|
-
keymap.of([
|
|
145
|
-
...defaultKeymap,
|
|
146
|
-
...historyKeymap, {
|
|
147
|
-
key: 'Mod-s',
|
|
148
|
-
run: () => {
|
|
149
|
-
this.save();
|
|
150
|
-
return true;
|
|
151
|
-
},
|
|
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,
|
|
152
98
|
},
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const state = EditorState.create({
|
|
159
|
-
doc: '',
|
|
160
|
-
extensions: baseExtensions(),
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
this._view = new EditorView({
|
|
164
|
-
state,
|
|
165
|
-
parent: this._Element,
|
|
166
|
-
});
|
|
99
|
+
scrollIntoView: true,
|
|
100
|
+
});
|
|
101
|
+
this.focus();
|
|
102
|
+
}
|
|
167
103
|
|
|
168
|
-
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
+
|
|
178
131
|
return this;
|
|
179
132
|
}
|
|
180
133
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
return this;
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
Qword.prototype.focus = function() {
|
|
193
|
-
this._view.focus();
|
|
194
|
-
return this;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
Qword.prototype.getCursor = function() {
|
|
198
|
-
const pos = this._view.state.selection.main.head;
|
|
199
|
-
const line = this._view.state.doc.lineAt(pos);
|
|
200
|
-
|
|
201
|
-
return {
|
|
202
|
-
row: line.number - 1,
|
|
203
|
-
column: pos - line.from,
|
|
204
|
-
};
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
Qword.prototype.moveCursorTo = function(row, column = 0) {
|
|
208
|
-
const line = this._view.state.doc.line(row + 1);
|
|
209
|
-
|
|
210
|
-
this._view.dispatch({
|
|
211
|
-
selection: {
|
|
212
|
-
anchor: line.from + column,
|
|
213
|
-
},
|
|
214
|
-
scrollIntoView: true,
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
return this;
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
Qword.prototype.remove = function(direction) {
|
|
221
|
-
const pos = this._view.state.selection.main.head;
|
|
222
|
-
|
|
223
|
-
this._view.dispatch({
|
|
224
|
-
changes: direction === 'right' ? {
|
|
225
|
-
from: pos,
|
|
226
|
-
to: pos + 1,
|
|
227
|
-
} : {
|
|
228
|
-
from: pos - 1,
|
|
229
|
-
to: pos,
|
|
230
|
-
},
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
return this;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
Qword.prototype.setModeForPath = function(path) {
|
|
237
|
-
const ext = path
|
|
238
|
-
.split('.')
|
|
239
|
-
.pop();
|
|
240
|
-
|
|
241
|
-
let lang = javascript();
|
|
242
|
-
|
|
243
|
-
if (ext === 'json')
|
|
244
|
-
lang = json();
|
|
245
|
-
|
|
246
|
-
if (ext === 'html')
|
|
247
|
-
lang = html();
|
|
248
|
-
|
|
249
|
-
this._view.dispatch({
|
|
250
|
-
effects: this._langCompartment.reconfigure(lang),
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
return this;
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
Qword.prototype.setValueFirst = function(name, value) {
|
|
257
|
-
this.setModeForPath(name);
|
|
258
|
-
this.setValue(value);
|
|
259
|
-
|
|
260
|
-
this._FileName = name;
|
|
261
|
-
this._Value = value;
|
|
262
|
-
|
|
263
|
-
this.moveCursorTo(0, 0);
|
|
264
|
-
|
|
265
|
-
return this;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
Qword.prototype.addKeyMap = function(map) {
|
|
269
|
-
const bindings = Object
|
|
270
|
-
.entries(map)
|
|
271
|
-
.map(([key, fn]) => ({
|
|
272
|
-
key,
|
|
273
|
-
run: () => {
|
|
274
|
-
fn.call(this);
|
|
275
|
-
return true;
|
|
134
|
+
selectAll() {
|
|
135
|
+
const {doc} = this._view.state;
|
|
136
|
+
this._view.dispatch({
|
|
137
|
+
selection: {
|
|
138
|
+
anchor: 0,
|
|
139
|
+
head: doc.length,
|
|
276
140
|
},
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
return this;
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
Qword.prototype.on = function(event, fn) {
|
|
287
|
-
this._Emitter.on(event, fn);
|
|
288
|
-
return this;
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
Qword.prototype.emit = function(...args) {
|
|
292
|
-
this._Emitter.emit(...args);
|
|
293
|
-
return this;
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
Qword.prototype.isChanged = function() {
|
|
297
|
-
return this.getValue() !== this._Value;
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
Qword.prototype._diff = function(newValue) {
|
|
301
|
-
return createPatch(this._Value || '', newValue);
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
Qword.prototype._patchHttp = function(path, patch) {
|
|
305
|
-
restafary.patch(path, patch, this._onSave.bind(this));
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
Qword.prototype._writeHttp = function(path, result) {
|
|
309
|
-
restafary.write(path, result, this._onSave.bind(this));
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
Qword.prototype.evaluate = function() {
|
|
313
|
-
if (!this._FileName?.endsWith('.js'))
|
|
314
|
-
return smalltalk.alert(this._TITLE, 'JS only');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
315
145
|
|
|
316
|
-
|
|
146
|
+
enableKey() {
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
317
149
|
|
|
318
|
-
|
|
319
|
-
|
|
150
|
+
cutToClipboard() {
|
|
151
|
+
return this._clipboard('cut');
|
|
152
|
+
}
|
|
320
153
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
Qword.prototype.goToLine = function() {
|
|
325
|
-
const num = Number(prompt('Line number'));
|
|
154
|
+
copyToClipboard() {
|
|
155
|
+
return this._clipboard('copy');
|
|
156
|
+
}
|
|
326
157
|
|
|
327
|
-
|
|
328
|
-
return;
|
|
158
|
+
pasteFromClipboard() {
|
|
159
|
+
return this._clipboard('paste');
|
|
160
|
+
}
|
|
329
161
|
|
|
330
|
-
|
|
162
|
+
_patchHttp(path, patch) {
|
|
163
|
+
restafary.patch(path, patch, this._onSave.bind(this));
|
|
164
|
+
}
|
|
331
165
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
},
|
|
336
|
-
scrollIntoView: true,
|
|
337
|
-
});
|
|
166
|
+
_writeHttp(path, data) {
|
|
167
|
+
restafary.write(path, data, this._onSave.bind(this));
|
|
168
|
+
}
|
|
338
169
|
|
|
339
|
-
|
|
340
|
-
|
|
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
|
+
}
|
|
341
178
|
|
|
342
179
|
Qword.prototype._clipboard = _clipboard;
|
|
343
180
|
Qword.prototype.save = save;
|
|
344
181
|
Qword.prototype._onSave = _onSave;
|
|
345
182
|
Qword.prototype._initSocket = _initSocket;
|
|
346
|
-
|
|
347
|
-
Qword.prototype._onDragOver = function(event) {
|
|
348
|
-
event.preventDefault();
|
|
349
|
-
event.dataTransfer.dropEffect = 'copy';
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
Qword.prototype._onDrop = function(event) {
|
|
353
|
-
event.preventDefault();
|
|
354
|
-
|
|
355
|
-
const [file] = event.dataTransfer.files;
|
|
356
|
-
|
|
357
|
-
if (!file)
|
|
358
|
-
return;
|
|
359
|
-
|
|
360
|
-
const reader = new FileReader();
|
|
361
|
-
|
|
362
|
-
reader.onload = (e) => {
|
|
363
|
-
this.setValue(e.target.result);
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
reader.readAsText(file);
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
Qword.prototype.sha = function() {
|
|
370
|
-
const shaObj = new jssha('SHA-1', 'TEXT');
|
|
371
|
-
shaObj.update(this.getValue());
|
|
372
|
-
|
|
373
|
-
return shaObj.getHash('HEX');
|
|
374
|
-
};
|
|
375
|
-
|
|
376
|
-
Qword.prototype.setOption = function(name, value) {
|
|
377
|
-
const {_Ace} = this;
|
|
378
|
-
const preventOverwrite = () => {
|
|
379
|
-
this._Config.options[name] = value;
|
|
380
|
-
};
|
|
381
|
-
|
|
382
|
-
preventOverwrite();
|
|
383
|
-
|
|
384
|
-
if (name === 'keyMap')
|
|
385
|
-
this.setKeyMap(value);
|
|
386
|
-
|
|
387
|
-
return this;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
Qword.prototype.setOptions = function(options) {
|
|
391
|
-
const theme = EditorView.theme({
|
|
392
|
-
'&': {
|
|
393
|
-
fontSize: options.fontSize,
|
|
394
|
-
fontFamily: options.fontFamily,
|
|
395
|
-
},
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
this._view.dispatch({
|
|
399
|
-
effects: this._fontCompartment.reconfigure(theme),
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
return this;
|
|
403
|
-
};
|
|
404
|
-
|
|
405
183
|
Qword.prototype.showMessage = showMessage;
|
|
406
|
-
|
|
407
|
-
Qword.prototype.setKeyMap = function(mode) {
|
|
408
|
-
this._vimEnabled = mode === 'vim';
|
|
409
|
-
|
|
410
|
-
this._view.dispatch({
|
|
411
|
-
effects: this._vimCompartment.reconfigure(this._vimEnabled ? vim() : []),
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
return this;
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
Qword.prototype._loadOptions = async function() {
|
|
418
|
-
const url = this._PREFIX + '/options.json';
|
|
419
|
-
|
|
420
|
-
if (this._Options)
|
|
421
|
-
return this._Options;
|
|
422
|
-
|
|
423
|
-
const data = await load.json(url);
|
|
424
|
-
|
|
425
|
-
this._Options = data;
|
|
426
|
-
|
|
427
|
-
return data;
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
Qword.prototype.enableKey = function() {
|
|
431
|
-
this._isKey = true;
|
|
432
|
-
return this;
|
|
433
|
-
};
|
package/client/save.js
CHANGED
|
@@ -34,9 +34,9 @@ async function save() {
|
|
|
34
34
|
if (!zip)
|
|
35
35
|
return this._write(_filename, value);
|
|
36
36
|
|
|
37
|
-
const
|
|
37
|
+
const zippedValue = await zipio(value);
|
|
38
38
|
|
|
39
|
-
return this._write(`${_filename}?unzip`,
|
|
39
|
+
return this._write(`${_filename}?unzip`, zippedValue);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function _setValue(ctx) {
|
|
@@ -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;
|