qword 1.1.11 → 1.1.13
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 +10 -0
- package/bower.json +25 -0
- package/client/_clipboard.js +50 -0
- package/client/_init-socket.js +76 -0
- package/client/_on-save.js +38 -0
- package/client/content.d.ts +8 -0
- package/client/content.js +14 -0
- package/client/create.d.ts +33 -0
- package/client/create.js +101 -0
- package/client/decorations.d.ts +38 -0
- package/client/decorations.js +110 -0
- package/client/dom.d.ts +8 -0
- package/client/dom.js +17 -0
- package/client/editor.d.ts +46 -0
- package/client/editor.js +178 -0
- package/client/events.d.ts +8 -0
- package/client/events.js +8 -0
- package/client/highlight.d.ts +3 -0
- package/client/highlight.js +82 -0
- package/client/history.d.ts +5 -0
- package/client/history.js +14 -0
- package/client/index.d.ts +60 -0
- package/client/index.js +38 -0
- package/client/loadremote.js +102 -0
- package/client/options.d.ts +31 -0
- package/client/options.js +70 -0
- package/client/position.d.ts +19 -0
- package/client/position.js +33 -0
- package/client/qword.js +196 -0
- package/client/save.js +53 -0
- package/client/scroll.d.ts +11 -0
- package/client/scroll.js +9 -0
- package/client/show-message.js +30 -0
- package/client/story.js +55 -0
- package/client/types.d.ts +28 -0
- package/dist/qword.js +1 -1
- package/dist/qword.js.map +1 -1
- package/dist-dev/qword.js +1 -1
- package/package.json +1 -1
- package/modules/cm-searchbox/ChangeLog +0 -60
- package/modules/cm-searchbox/LICENSE +0 -21
- package/modules/cm-searchbox/README.md +0 -27
- package/modules/cm-searchbox/img/searchbox.png +0 -0
- package/modules/cm-searchbox/lib/searchbox.js +0 -679
- package/modules/cm-searchbox/package.json +0 -27
- package/modules/cm-show-invisibles/ChangeLog +0 -108
- package/modules/cm-show-invisibles/LICENSE +0 -21
- package/modules/cm-show-invisibles/README.md +0 -25
- package/modules/cm-show-invisibles/lib/show-invisibles.js +0 -131
- package/modules/cm-show-invisibles/package.json +0 -34
- package/modules/codemirror-emmet/README.md +0 -56
- 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/codemirror-emmet/editor.js +0 -204
- package/modules/codemirror-emmet/gulpfile.js +0 -54
- package/modules/codemirror-emmet/index.html +0 -68
- package/modules/codemirror-emmet/package.json +0 -36
- package/modules/codemirror-emmet/plugin.js +0 -201
- package/modules/codemirror-emmet/shim.js +0 -19
- package/modules/codemirror-emmet/vendor/almond.js +0 -410
- package/modules/codemirror-emmet/vendor/codemirror/v4/codemirror.css +0 -270
- package/modules/codemirror-emmet/vendor/codemirror/v4/codemirror.js +0 -7339
- package/modules/codemirror-emmet/vendor/codemirror/v4/css.js +0 -701
- package/modules/codemirror-emmet/vendor/codemirror/v4/htmlmixed.js +0 -117
- package/modules/codemirror-emmet/vendor/codemirror/v4/xml.js +0 -349
- package/modules/loadremote/ChangeLog +0 -23
- package/modules/loadremote/LICENSE +0 -21
- package/modules/loadremote/README.md +0 -53
- package/modules/loadremote/lib/loadremote.js +0 -147
- package/modules/loadremote/package.json +0 -26
package/ChangeLog
CHANGED
package/bower.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dword",
|
|
3
|
+
"homepage": "https://github.com/cloudcmd/dword",
|
|
4
|
+
"authors": [
|
|
5
|
+
"coderaiser <mnemonic.enemy@gmail.com>"
|
|
6
|
+
],
|
|
7
|
+
"description": "web editor",
|
|
8
|
+
"main": "bin/dword.js",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"file",
|
|
11
|
+
"edit"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"private": true,
|
|
15
|
+
"ignore": [
|
|
16
|
+
"node_modules",
|
|
17
|
+
"modules"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"codemirror-emmet": "~1.1.0",
|
|
21
|
+
"cm-searchbox": "1.0.8",
|
|
22
|
+
"cm-show-invisibles": "^3.1.0",
|
|
23
|
+
"jshint": "^2.13.5"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import clipboard from '@cloudcmd/clipboard';
|
|
2
|
+
import once from 'once';
|
|
3
|
+
import showMessage from './show-message.js';
|
|
4
|
+
|
|
5
|
+
const showMessageOnce = once(showMessage);
|
|
6
|
+
|
|
7
|
+
export default function clipboardCommand(command) {
|
|
8
|
+
const {_view, _story} = this;
|
|
9
|
+
const NAME = 'editor-clipboard';
|
|
10
|
+
|
|
11
|
+
const getSelected = () => {
|
|
12
|
+
const {from, to} = _view.state.selection.main;
|
|
13
|
+
return _view.state.sliceDoc(from, to);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const insert = (text) => {
|
|
17
|
+
const {from, to} = _view.state.selection.main;
|
|
18
|
+
|
|
19
|
+
_view.dispatch({
|
|
20
|
+
changes: {
|
|
21
|
+
from,
|
|
22
|
+
to,
|
|
23
|
+
insert: text,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
if (command === 'copy') {
|
|
29
|
+
const value = getSelected();
|
|
30
|
+
_story.setData(NAME, value);
|
|
31
|
+
|
|
32
|
+
return clipboard.writeText(value);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (command === 'cut') {
|
|
36
|
+
const value = getSelected();
|
|
37
|
+
_story.setData(NAME, value);
|
|
38
|
+
insert('');
|
|
39
|
+
|
|
40
|
+
return clipboard.writeText(value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return clipboard
|
|
44
|
+
.readText()
|
|
45
|
+
.then(insert)
|
|
46
|
+
.catch(() => {
|
|
47
|
+
showMessageOnce.call(this, 'Could not paste from clipboard. Inner buffer used.');
|
|
48
|
+
insert(_story.getData(NAME));
|
|
49
|
+
});
|
|
50
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {applyPatch} from 'daffy';
|
|
2
|
+
import {alert} from 'smalltalk';
|
|
3
|
+
|
|
4
|
+
const getHost = () => {
|
|
5
|
+
const l = location;
|
|
6
|
+
|
|
7
|
+
return l.origin || l.protocol + '//' + l.host;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function() {
|
|
11
|
+
const qword = this;
|
|
12
|
+
const href = getHost();
|
|
13
|
+
const FIVE_SECONDS = 5000;
|
|
14
|
+
|
|
15
|
+
const patch = (name, data) => {
|
|
16
|
+
socket.emit('patch', name, data);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const {_prefixSocket} = qword;
|
|
20
|
+
|
|
21
|
+
const socket = globalThis.io.connect(href + _prefixSocket, {
|
|
22
|
+
'max reconnection attempts': 2 ** 32,
|
|
23
|
+
'reconnection limit': FIVE_SECONDS,
|
|
24
|
+
'path': this._socketPath + '/socket.io',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
this._socket = socket;
|
|
28
|
+
|
|
29
|
+
socket.on('reject', () => {
|
|
30
|
+
this.emit('reject');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
socket.on('connect', () => {
|
|
34
|
+
qword._patch = patch;
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
socket.on('message', (msg) => {
|
|
38
|
+
this._onSave(null, msg);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
socket.on('file', (name, data) => {
|
|
42
|
+
qword
|
|
43
|
+
.setModeForPath(name)
|
|
44
|
+
.setValueFirst(name, data)
|
|
45
|
+
.moveCursorTo(0, 0);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
socket.on('patch', (name, data, hash) => {
|
|
49
|
+
if (name !== this._FileName)
|
|
50
|
+
return;
|
|
51
|
+
|
|
52
|
+
if (hash !== this._story.getHash(name))
|
|
53
|
+
return;
|
|
54
|
+
|
|
55
|
+
const cursor = qword.getCursor();
|
|
56
|
+
const value = qword.getValue();
|
|
57
|
+
const result = applyPatch(value, data);
|
|
58
|
+
|
|
59
|
+
this.setValue(result);
|
|
60
|
+
|
|
61
|
+
this
|
|
62
|
+
._story
|
|
63
|
+
.setData(name, value)
|
|
64
|
+
.setHash(name, this.sha());
|
|
65
|
+
|
|
66
|
+
qword.moveCursorTo(cursor.row, cursor.column);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
socket.on('disconnect', () => {
|
|
70
|
+
qword.save.patch = globalThis._patchHttp;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
socket.on('err', (error) => {
|
|
74
|
+
alert(this._TITLE, error);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {confirm} from 'smalltalk';
|
|
2
|
+
import {write} from 'restafary/client';
|
|
3
|
+
|
|
4
|
+
function empty() {}
|
|
5
|
+
|
|
6
|
+
export default function onSave(error, text) {
|
|
7
|
+
const Value = this._Value;
|
|
8
|
+
const FileName = this._FileName;
|
|
9
|
+
let msg = 'Try again?';
|
|
10
|
+
|
|
11
|
+
if (error) {
|
|
12
|
+
if (error.message)
|
|
13
|
+
msg = error.message + '\n' + msg;
|
|
14
|
+
else
|
|
15
|
+
msg = `Can't save.` + msg;
|
|
16
|
+
|
|
17
|
+
const onSave = this._onSave.bind(this);
|
|
18
|
+
|
|
19
|
+
return confirm(this._TITLE, msg)
|
|
20
|
+
.then(() => {
|
|
21
|
+
write(this._FileName, this._Value, onSave);
|
|
22
|
+
})
|
|
23
|
+
.catch(empty)
|
|
24
|
+
.then(() => {
|
|
25
|
+
this.focus();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.showMessage(text);
|
|
30
|
+
|
|
31
|
+
const hash = this.sha();
|
|
32
|
+
this
|
|
33
|
+
._story
|
|
34
|
+
.setData(FileName, Value)
|
|
35
|
+
.setHash(FileName, hash);
|
|
36
|
+
|
|
37
|
+
this._Emitter.emit('save', Value.length);
|
|
38
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type {EditorView} from '@codemirror/view';
|
|
2
|
+
import type {SourceCode} from './types.js';
|
|
3
|
+
|
|
4
|
+
export function getValue(view: EditorView): SourceCode;
|
|
5
|
+
export const getDocValue: typeof getValue;
|
|
6
|
+
|
|
7
|
+
export function setValue(view: EditorView, value: SourceCode): void;
|
|
8
|
+
export const setDocValue: typeof setValue;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const getValue = (view) => view.state.doc.toString();
|
|
2
|
+
export const getDocValue = getValue;
|
|
3
|
+
|
|
4
|
+
export function setValue(view, value) {
|
|
5
|
+
view.dispatch({
|
|
6
|
+
changes: {
|
|
7
|
+
from: 0,
|
|
8
|
+
to: view.state.doc.length,
|
|
9
|
+
insert: value,
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const setDocValue = setValue;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {Compartment} from '@codemirror/state';
|
|
2
|
+
import {type ViewUpdate, EditorView} from '@codemirror/view';
|
|
3
|
+
import type {
|
|
4
|
+
SourceCode,
|
|
5
|
+
KeyMap,
|
|
6
|
+
EditorMode,
|
|
7
|
+
EditorTheme,
|
|
8
|
+
} from './types.js';
|
|
9
|
+
|
|
10
|
+
export type CreateEditorOptions = {
|
|
11
|
+
value?: SourceCode;
|
|
12
|
+
mode?: EditorMode | {
|
|
13
|
+
name: EditorMode;
|
|
14
|
+
json?: boolean;
|
|
15
|
+
};
|
|
16
|
+
keyMap?: KeyMap;
|
|
17
|
+
theme?: EditorTheme;
|
|
18
|
+
lineNumbers?: boolean;
|
|
19
|
+
readOnly?: boolean;
|
|
20
|
+
foldGutter?: boolean;
|
|
21
|
+
updateListener?: (update: ViewUpdate) => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Augmented EditorView with compartment refs for dynamic option changes.
|
|
25
|
+
export type QwordEditorView = EditorView & {
|
|
26
|
+
_themeCompartment: Compartment;
|
|
27
|
+
_keymapCompartment: Compartment;
|
|
28
|
+
_langCompartment: Compartment;
|
|
29
|
+
_historyCompartment: Compartment;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function createEditor(element: Element, options?: CreateEditorOptions): QwordEditorView;
|
|
33
|
+
|
package/client/create.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {EditorState, Compartment} from '@codemirror/state';
|
|
2
|
+
import {
|
|
3
|
+
EditorView,
|
|
4
|
+
lineNumbers as lineNumbersExtension,
|
|
5
|
+
drawSelection,
|
|
6
|
+
keymap,
|
|
7
|
+
} from '@codemirror/view';
|
|
8
|
+
import {history, historyKeymap} from '@codemirror/commands';
|
|
9
|
+
import {
|
|
10
|
+
foldGutter,
|
|
11
|
+
codeFolding,
|
|
12
|
+
syntaxHighlighting,
|
|
13
|
+
indentOnInput,
|
|
14
|
+
indentUnit,
|
|
15
|
+
bracketMatching,
|
|
16
|
+
} from '@codemirror/language';
|
|
17
|
+
import {highlightStyle} from './highlight.js';
|
|
18
|
+
import {
|
|
19
|
+
keymapExtension,
|
|
20
|
+
themeExtension,
|
|
21
|
+
languageExtension,
|
|
22
|
+
} from './options.js';
|
|
23
|
+
import {markField, lineField} from './decorations.js';
|
|
24
|
+
|
|
25
|
+
export function createEditor(element, options = {}) {
|
|
26
|
+
const {
|
|
27
|
+
value = '',
|
|
28
|
+
mode = 'javascript',
|
|
29
|
+
keyMap = 'default',
|
|
30
|
+
theme = 'default',
|
|
31
|
+
lineNumbers = true,
|
|
32
|
+
readOnly = false,
|
|
33
|
+
foldGutter: fold = false,
|
|
34
|
+
updateListener,
|
|
35
|
+
} = options;
|
|
36
|
+
|
|
37
|
+
const themeCompartment = new Compartment();
|
|
38
|
+
const keymapCompartment = new Compartment();
|
|
39
|
+
const langCompartment = new Compartment();
|
|
40
|
+
const historyCompartment = new Compartment();
|
|
41
|
+
|
|
42
|
+
const hideCursorOnBlur = EditorView.theme({
|
|
43
|
+
'&:not(.cm-focused) .cm-fat-cursor': {
|
|
44
|
+
display: 'none',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const extensions = [
|
|
49
|
+
historyCompartment.of([
|
|
50
|
+
history(),
|
|
51
|
+
keymap.of(historyKeymap),
|
|
52
|
+
]),
|
|
53
|
+
markField,
|
|
54
|
+
lineField,
|
|
55
|
+
themeCompartment.of(themeExtension(theme)),
|
|
56
|
+
keymapCompartment.of(keymapExtension(keyMap)),
|
|
57
|
+
bracketMatching(),
|
|
58
|
+
langCompartment.of(languageExtension(mode)),
|
|
59
|
+
syntaxHighlighting(highlightStyle),
|
|
60
|
+
indentOnInput(),
|
|
61
|
+
indentUnit.of(' '),
|
|
62
|
+
...lineNumbers
|
|
63
|
+
? [
|
|
64
|
+
lineNumbersExtension(),
|
|
65
|
+
]
|
|
66
|
+
: [],
|
|
67
|
+
...fold
|
|
68
|
+
? [
|
|
69
|
+
foldGutter(),
|
|
70
|
+
codeFolding(),
|
|
71
|
+
]
|
|
72
|
+
: [],
|
|
73
|
+
...readOnly
|
|
74
|
+
? [
|
|
75
|
+
EditorState.readOnly.of(true),
|
|
76
|
+
]
|
|
77
|
+
: [],
|
|
78
|
+
...updateListener
|
|
79
|
+
? [
|
|
80
|
+
EditorView.updateListener.of(updateListener),
|
|
81
|
+
]
|
|
82
|
+
: [],
|
|
83
|
+
drawSelection(),
|
|
84
|
+
hideCursorOnBlur,
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
const view = new EditorView({
|
|
88
|
+
state: EditorState.create({
|
|
89
|
+
doc: value,
|
|
90
|
+
extensions,
|
|
91
|
+
}),
|
|
92
|
+
parent: element,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
view._themeCompartment = themeCompartment;
|
|
96
|
+
view._keymapCompartment = keymapCompartment;
|
|
97
|
+
view._langCompartment = langCompartment;
|
|
98
|
+
view._historyCompartment = historyCompartment;
|
|
99
|
+
|
|
100
|
+
return view;
|
|
101
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Range,
|
|
3
|
+
StateEffect,
|
|
4
|
+
StateField,
|
|
5
|
+
} from '@codemirror/state';
|
|
6
|
+
import {
|
|
7
|
+
Decoration,
|
|
8
|
+
EditorView,
|
|
9
|
+
type DecorationSet,
|
|
10
|
+
} from '@codemirror/view';
|
|
11
|
+
import type {SourcePosition} from './types.js';
|
|
12
|
+
|
|
13
|
+
export const setMarkEffect: StateEffect<Range<Decoration>>;
|
|
14
|
+
export const clearMarkEffect: StateEffect<null>;
|
|
15
|
+
export const setLineEffect: StateEffect<{
|
|
16
|
+
line: number;
|
|
17
|
+
cls: string;
|
|
18
|
+
}>;
|
|
19
|
+
export const clearLineEffect: StateEffect<{
|
|
20
|
+
line: number;
|
|
21
|
+
cls: string;
|
|
22
|
+
}>;
|
|
23
|
+
|
|
24
|
+
export const markField: StateField<DecorationSet>;
|
|
25
|
+
export const lineField: StateField<DecorationSet>;
|
|
26
|
+
|
|
27
|
+
export type MarkHandle = {
|
|
28
|
+
clear: () => void;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function markText(view: EditorView, from: SourcePosition, to: SourcePosition, {className}: {
|
|
32
|
+
className: string;
|
|
33
|
+
}): MarkHandle;
|
|
34
|
+
|
|
35
|
+
export function addLineClass(view: EditorView, line: number, _where: string, className: string): void;
|
|
36
|
+
|
|
37
|
+
export function removeLineClass(view: EditorView, line: number, _where: string, className: string): void;
|
|
38
|
+
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {StateEffect, StateField} from '@codemirror/state';
|
|
2
|
+
import {EditorView, Decoration} from '@codemirror/view';
|
|
3
|
+
import {positionToOffset} from './position.js';
|
|
4
|
+
|
|
5
|
+
const noop = () => {};
|
|
6
|
+
|
|
7
|
+
export const setMarkEffect = StateEffect.define();
|
|
8
|
+
export const clearMarkEffect = StateEffect.define();
|
|
9
|
+
export const setLineEffect = StateEffect.define();
|
|
10
|
+
export const clearLineEffect = StateEffect.define();
|
|
11
|
+
|
|
12
|
+
export const markField = StateField.define({
|
|
13
|
+
create: () => Decoration.none,
|
|
14
|
+
update(decorations, transaction) {
|
|
15
|
+
decorations = decorations.map(transaction.changes);
|
|
16
|
+
|
|
17
|
+
for (const effect of transaction.effects) {
|
|
18
|
+
if (effect.is(setMarkEffect))
|
|
19
|
+
decorations = decorations.update({
|
|
20
|
+
add: [effect.value],
|
|
21
|
+
sort: true,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (effect.is(clearMarkEffect))
|
|
25
|
+
decorations = Decoration.none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return decorations;
|
|
29
|
+
},
|
|
30
|
+
provide: (field) => EditorView.decorations.from(field),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const lineField = StateField.define({
|
|
34
|
+
create: () => Decoration.none,
|
|
35
|
+
update(decorations, transaction) {
|
|
36
|
+
decorations = decorations.map(transaction.changes);
|
|
37
|
+
|
|
38
|
+
for (const effect of transaction.effects) {
|
|
39
|
+
if (effect.is(setLineEffect)) {
|
|
40
|
+
const {line, cls} = effect.value;
|
|
41
|
+
const {from} = transaction.state.doc.line(Math.min(line + 1, transaction.state.doc.lines));
|
|
42
|
+
|
|
43
|
+
decorations = decorations.update({
|
|
44
|
+
add: [
|
|
45
|
+
Decoration
|
|
46
|
+
.line({
|
|
47
|
+
class: cls,
|
|
48
|
+
})
|
|
49
|
+
.range(from),
|
|
50
|
+
],
|
|
51
|
+
sort: true,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (effect.is(clearLineEffect)) {
|
|
56
|
+
const {line, cls} = effect.value;
|
|
57
|
+
|
|
58
|
+
decorations = decorations.update({
|
|
59
|
+
filter: (from, _, decoration) => !(decoration.spec.class === cls && transaction.state.doc.lineAt(from).number === line + 1),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return decorations;
|
|
65
|
+
},
|
|
66
|
+
provide: (field) => EditorView.decorations.from(field),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export function markText(view, from, to, {className}) {
|
|
70
|
+
const fromOffset = positionToOffset(view.state.doc, from);
|
|
71
|
+
const toOffset = positionToOffset(view.state.doc, to);
|
|
72
|
+
|
|
73
|
+
if (fromOffset === toOffset)
|
|
74
|
+
return {
|
|
75
|
+
clear: noop,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const decoration = Decoration
|
|
79
|
+
.mark({
|
|
80
|
+
class: className,
|
|
81
|
+
})
|
|
82
|
+
.range(fromOffset, toOffset);
|
|
83
|
+
|
|
84
|
+
view.dispatch({
|
|
85
|
+
effects: setMarkEffect.of(decoration),
|
|
86
|
+
});
|
|
87
|
+
return {
|
|
88
|
+
clear: () => view.dispatch({
|
|
89
|
+
effects: clearMarkEffect.of(null),
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function addLineClass(view, line, _where, className) {
|
|
95
|
+
view.dispatch({
|
|
96
|
+
effects: setLineEffect.of({
|
|
97
|
+
line,
|
|
98
|
+
cls: className,
|
|
99
|
+
}),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function removeLineClass(view, line, _where, className) {
|
|
104
|
+
view.dispatch({
|
|
105
|
+
effects: clearLineEffect.of({
|
|
106
|
+
line,
|
|
107
|
+
cls: className,
|
|
108
|
+
}),
|
|
109
|
+
});
|
|
110
|
+
}
|
package/client/dom.d.ts
ADDED
package/client/dom.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {EditorView} from '@codemirror/view';
|
|
2
|
+
|
|
3
|
+
export function getView(container) {
|
|
4
|
+
const element = container.querySelector('.cm-editor');
|
|
5
|
+
return element ? EditorView.findFromDOM(element) : null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function refresh(view) {
|
|
9
|
+
view.requestMeasure();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function observeResize(view, container) {
|
|
13
|
+
const observer = new ResizeObserver(() => view.requestMeasure());
|
|
14
|
+
observer.observe(container);
|
|
15
|
+
|
|
16
|
+
return () => observer.disconnect();
|
|
17
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type QwordEditorView,
|
|
3
|
+
type CreateEditorOptions,
|
|
4
|
+
} from './create.js';
|
|
5
|
+
import type {MarkHandle} from './decorations.js';
|
|
6
|
+
import type {OptionKey, OptionValue} from './options.js';
|
|
7
|
+
import type {
|
|
8
|
+
SourceCode,
|
|
9
|
+
SourcePosition,
|
|
10
|
+
CharOffset,
|
|
11
|
+
KeyMap,
|
|
12
|
+
EditorMode,
|
|
13
|
+
EditorTheme,
|
|
14
|
+
} from './types.js';
|
|
15
|
+
|
|
16
|
+
export type EditorOptions = CreateEditorOptions;
|
|
17
|
+
|
|
18
|
+
export default class Editor {
|
|
19
|
+
constructor(element: Element, options?: EditorOptions);
|
|
20
|
+
getValue(): SourceCode;
|
|
21
|
+
setValue(value: SourceCode): this;
|
|
22
|
+
getCursorIndex(): CharOffset;
|
|
23
|
+
getCursor(): {
|
|
24
|
+
row: number;
|
|
25
|
+
column: number;
|
|
26
|
+
};
|
|
27
|
+
posFromIndex(index: CharOffset): SourcePosition;
|
|
28
|
+
focus(): this;
|
|
29
|
+
moveCursorTo(row: number, column?: number): this;
|
|
30
|
+
markRange(from: SourcePosition, to: SourcePosition, className: string): MarkHandle;
|
|
31
|
+
addLineClass(line: number, className: string): this;
|
|
32
|
+
removeLineClass(line: number, className: string): this;
|
|
33
|
+
setOption(name: OptionKey, value: OptionValue): this;
|
|
34
|
+
setMode(mode: EditorMode): this;
|
|
35
|
+
setTheme(theme: EditorTheme): this;
|
|
36
|
+
setKeyMap(name: KeyMap): this;
|
|
37
|
+
setModeForPath(path: string): this;
|
|
38
|
+
isChanged(): boolean;
|
|
39
|
+
clearHistory(): this;
|
|
40
|
+
on(event: string, handler: (...args: unknown[]) => void): this;
|
|
41
|
+
addListener(event: string, handler: (...args: unknown[]) => void): this;
|
|
42
|
+
once(event: string, handler: (...args: unknown[]) => void): this;
|
|
43
|
+
removeListener(event: string, handler: (...args: unknown[]) => void): this;
|
|
44
|
+
emit(...args: unknown[]): this;
|
|
45
|
+
_view(): QwordEditorView;
|
|
46
|
+
}
|