@bhsd/codemirror-mediawiki 2.6.1 → 2.6.3
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/README.md +18 -1
- package/dist/codemirror.d.ts +9 -0
- package/dist/main.min.js +10 -10
- package/dist/mw.min.js +3 -2
- package/dist/mw.min.js.map +3 -3
- package/i18n/en.json +5 -2
- package/i18n/zh-hans.json +5 -2
- package/i18n/zh-hant.json +5 -2
- package/mw/README.md +15 -0
- package/mw/base.ts +19 -9
- package/mw/msg.ts +3 -3
- package/mw/preference.ts +50 -17
- package/mw/textSelection.ts +17 -14
- package/package.json +1 -1
package/mw/preference.ts
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import {rules} from 'wikiparser-node/dist/base';
|
|
2
|
+
import {CodeMirror} from './base';
|
|
2
3
|
import {msg, i18n, setObject, getObject} from './msg';
|
|
3
|
-
import
|
|
4
|
+
import {instances} from './textSelection';
|
|
4
5
|
|
|
5
6
|
const storageKey = 'codemirror-mediawiki-addons',
|
|
6
|
-
wikilintKey = 'codemirror-mediawiki-wikilint'
|
|
7
|
+
wikilintKey = 'codemirror-mediawiki-wikilint',
|
|
8
|
+
codeKeys = ['ESLint', 'Stylelint'] as const;
|
|
9
|
+
|
|
10
|
+
declare type codeKey = typeof codeKeys[number];
|
|
11
|
+
|
|
7
12
|
export const indentKey = 'codemirror-mediawiki-indent',
|
|
8
13
|
prefs = new Set<string>(getObject(storageKey) as string[] | null),
|
|
9
|
-
wikilintConfig = (getObject(wikilintKey) || {}) as Record<Rule, RuleState | undefined
|
|
14
|
+
wikilintConfig = (getObject(wikilintKey) || {}) as Record<Rule, RuleState | undefined>,
|
|
15
|
+
codeConfigs = new Map(codeKeys.map(k => [k, getObject(`codemirror-mediawiki-${k}`)]));
|
|
10
16
|
|
|
11
17
|
// OOUI组件
|
|
12
18
|
let dialog: OO.ui.MessageDialog | undefined,
|
|
13
|
-
layout: OO.ui.IndexLayout
|
|
14
|
-
panelMain: OO.ui.TabPanelLayout | undefined,
|
|
15
|
-
panelWikilint: OO.ui.TabPanelLayout | undefined,
|
|
19
|
+
layout: OO.ui.IndexLayout,
|
|
16
20
|
widget: OO.ui.CheckboxMultiselectInputWidget,
|
|
17
21
|
indentWidget: OO.ui.TextInputWidget,
|
|
18
|
-
field: OO.ui.FieldLayout,
|
|
19
|
-
indentField: OO.ui.FieldLayout,
|
|
20
22
|
indent = localStorage.getItem(indentKey) || '';
|
|
23
|
+
const widgets: Partial<Record<codeKey, OO.ui.MultilineTextInputWidget>> = {};
|
|
21
24
|
|
|
22
25
|
const enum RuleState {
|
|
23
26
|
off = '0',
|
|
@@ -28,7 +31,8 @@ const enum RuleState {
|
|
|
28
31
|
const wikilintWidgets = new Map<Rule, OO.ui.DropdownInputWidget>();
|
|
29
32
|
|
|
30
33
|
mw.loader.addStyleTag(`#cm-preference>.oo-ui-window-frame{height:100%!important}
|
|
31
|
-
#cm-preference .oo-ui-panelLayout{overflow:visible}
|
|
34
|
+
#cm-preference .oo-ui-panelLayout{overflow:visible}
|
|
35
|
+
#cm-preference .cm-editor{border:1.5px solid #dedede;border-radius:.3em}`);
|
|
32
36
|
|
|
33
37
|
/**
|
|
34
38
|
* 打开设置对话框
|
|
@@ -45,9 +49,25 @@ export const openPreference = async (editors: (CodeMirror | undefined)[]): Promi
|
|
|
45
49
|
windowManager.$element.appendTo(document.body);
|
|
46
50
|
windowManager.addWindows([dialog]);
|
|
47
51
|
layout = new OO.ui.IndexLayout();
|
|
48
|
-
panelMain = new OO.ui.TabPanelLayout('main', {label: msg('title')})
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
const panelMain = new OO.ui.TabPanelLayout('main', {label: msg('title')}),
|
|
53
|
+
panelWikilint = new OO.ui.TabPanelLayout('wikilint', {label: 'WikiLint'}),
|
|
54
|
+
panels: Partial<Record<codeKey, OO.ui.TabPanelLayout>> = {};
|
|
55
|
+
for (const key of codeKeys) {
|
|
56
|
+
const c = codeConfigs.get(key);
|
|
57
|
+
widgets[key] = new OO.ui.MultilineTextInputWidget({
|
|
58
|
+
value: c ? JSON.stringify(c, null, indent || '\t') : '',
|
|
59
|
+
});
|
|
60
|
+
const codeField = new OO.ui.FieldLayout(widgets[key]!, {label: msg(`${key}-config`), align: 'top'}),
|
|
61
|
+
panel = new OO.ui.TabPanelLayout(key, {label: key, $content: codeField.$element});
|
|
62
|
+
panel.on('active', active => {
|
|
63
|
+
const [textarea] = panel.$element.find('textarea') as unknown as [HTMLTextAreaElement];
|
|
64
|
+
if (active && !instances.has(textarea)) {
|
|
65
|
+
void CodeMirror.fromTextArea(textarea, 'json');
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
panels[key] = panel;
|
|
69
|
+
}
|
|
70
|
+
layout.addTabPanels([panelMain, panelWikilint, ...Object.values(panels)], 0);
|
|
51
71
|
widget = new OO.ui.CheckboxMultiselectInputWidget({
|
|
52
72
|
options: Object.keys(i18n)
|
|
53
73
|
.filter(k => k !== 'addon-indent' && k.startsWith('addon-') && !k.endsWith('-mac'))
|
|
@@ -58,12 +78,12 @@ export const openPreference = async (editors: (CodeMirror | undefined)[]): Promi
|
|
|
58
78
|
})),
|
|
59
79
|
value: [...prefs] as unknown as string,
|
|
60
80
|
});
|
|
61
|
-
field = new OO.ui.FieldLayout(widget, {
|
|
62
|
-
label: msg('label'),
|
|
63
|
-
align: 'top',
|
|
64
|
-
});
|
|
65
81
|
indentWidget = new OO.ui.TextInputWidget({value: indent, placeholder: '\\t'});
|
|
66
|
-
|
|
82
|
+
const field = new OO.ui.FieldLayout(widget, {
|
|
83
|
+
label: msg('label'),
|
|
84
|
+
align: 'top',
|
|
85
|
+
}),
|
|
86
|
+
indentField = new OO.ui.FieldLayout(indentWidget, {label: msg('addon-indent')});
|
|
67
87
|
panelMain.$element.append(
|
|
68
88
|
field.$element,
|
|
69
89
|
indentField.$element,
|
|
@@ -98,6 +118,19 @@ export const openPreference = async (editors: (CodeMirror | undefined)[]): Promi
|
|
|
98
118
|
size: 'medium',
|
|
99
119
|
}).closing as unknown as Promise<{action?: unknown} | undefined>);
|
|
100
120
|
if (typeof data === 'object' && data.action === 'accept') {
|
|
121
|
+
const jsonErrors: string[] = [];
|
|
122
|
+
for (const key of codeKeys) {
|
|
123
|
+
try {
|
|
124
|
+
const config = JSON.parse(widgets[key]!.getValue().trim() || 'null');
|
|
125
|
+
codeConfigs.set(key, config);
|
|
126
|
+
setObject(`codemirror-mediawiki-${key}`, config);
|
|
127
|
+
} catch {
|
|
128
|
+
jsonErrors.push(key);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (jsonErrors.length > 0) {
|
|
132
|
+
void OO.ui.alert(msg('json-error', jsonErrors.join(msg('and'))));
|
|
133
|
+
}
|
|
101
134
|
for (const [rule, dropdown] of wikilintWidgets) {
|
|
102
135
|
wikilintConfig[rule] = dropdown.getValue() as RuleState;
|
|
103
136
|
}
|
package/mw/textSelection.ts
CHANGED
|
@@ -17,37 +17,40 @@ export const textSelection = {
|
|
|
17
17
|
return getInstance(this).view.state.doc.toString();
|
|
18
18
|
},
|
|
19
19
|
setContents(this: JQuery<HTMLTextAreaElement>, content: string): JQuery<HTMLTextAreaElement> {
|
|
20
|
-
getInstance(this)
|
|
20
|
+
const cm = getInstance(this),
|
|
21
|
+
{view: {scrollDOM}} = cm,
|
|
22
|
+
{scrollTop} = scrollDOM;
|
|
23
|
+
cm.setContent(content);
|
|
24
|
+
scrollDOM.scrollTop = scrollTop;
|
|
21
25
|
return this;
|
|
22
26
|
},
|
|
23
27
|
getSelection(this: JQuery<HTMLTextAreaElement>): string {
|
|
24
|
-
const {view: {state}} = getInstance(this)
|
|
25
|
-
|
|
28
|
+
const {view: {state}} = getInstance(this),
|
|
29
|
+
{selection: {main: {from, to}}} = state;
|
|
30
|
+
return state.sliceDoc(from, to);
|
|
26
31
|
},
|
|
27
32
|
setSelection(
|
|
28
33
|
this: JQuery<HTMLTextAreaElement>,
|
|
29
|
-
{start, end}: {start: number, end?: number},
|
|
34
|
+
{start, end = start}: {start: number, end?: number},
|
|
30
35
|
): JQuery<HTMLTextAreaElement> {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
selection: {anchor: start, head: end ?? start},
|
|
36
|
+
getInstance(this).view.dispatch({
|
|
37
|
+
selection: {anchor: start, head: end},
|
|
34
38
|
});
|
|
35
|
-
view.focus();
|
|
36
39
|
return this;
|
|
37
40
|
},
|
|
38
41
|
replaceSelection(this: JQuery<HTMLTextAreaElement>, value: string): JQuery<HTMLTextAreaElement> {
|
|
39
|
-
const {view} = getInstance(this)
|
|
40
|
-
|
|
41
|
-
view.dispatch({selection: {anchor: from, head: to}});
|
|
42
|
+
const {view} = getInstance(this);
|
|
43
|
+
view.dispatch({selection: view.state.selection.asSingle()});
|
|
42
44
|
view.dispatch(view.state.replaceSelection(value));
|
|
43
45
|
return this;
|
|
44
46
|
},
|
|
45
47
|
getCaretPosition(this: JQuery<HTMLTextAreaElement>, option?: {startAndEnd?: boolean}): [number, number] | number {
|
|
46
|
-
const {view: {state: {selection: {main}}}} = getInstance(this);
|
|
47
|
-
return option?.startAndEnd ? [
|
|
48
|
+
const {view: {state: {selection: {main: {from, to, head}}}}} = getInstance(this);
|
|
49
|
+
return option?.startAndEnd ? [from, to] : head;
|
|
48
50
|
},
|
|
49
51
|
scrollToCaretPosition(this: JQuery<HTMLTextAreaElement>): JQuery<HTMLTextAreaElement> {
|
|
50
|
-
getInstance(this)
|
|
52
|
+
const cm = getInstance(this);
|
|
53
|
+
cm.scrollTo();
|
|
51
54
|
return this;
|
|
52
55
|
},
|
|
53
56
|
};
|