@bhsd/codemirror-mediawiki 2.3.2 → 2.3.4

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/mw/config.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type {Config} from 'wikilint';
1
2
  import type {MwConfig} from '../src/mediawiki';
2
3
 
3
4
  declare interface MagicWord {
@@ -6,10 +7,9 @@ declare interface MagicWord {
6
7
  'case-sensitive': boolean;
7
8
  }
8
9
 
9
- export const USING_LOCAL = mw.loader.getState('ext.CodeMirror') !== null;
10
-
11
10
  // 和本地缓存有关的常数
12
- const DATA_MODULE = mw.loader.getState('ext.CodeMirror.data') ? 'ext.CodeMirror.data' : 'ext.CodeMirror',
11
+ const USING_LOCAL = mw.loader.getState('ext.CodeMirror') !== null,
12
+ DATA_MODULE = mw.loader.getState('ext.CodeMirror.data') ? 'ext.CodeMirror.data' : 'ext.CodeMirror',
13
13
  ALL_SETTINGS_CACHE: Record<string, {time: number, config: MwConfig}>
14
14
  = JSON.parse(localStorage.getItem('InPageEditMwConfig')!) || {},
15
15
  SITE_ID = `${mw.config.get('wgServerName')}${mw.config.get('wgScriptPath')}`,
@@ -50,7 +50,10 @@ const getConfigPair = (
50
50
  ): [Record<string, string>, Record<string, string>] => [true, false]
51
51
  .map(bool => getConfig(magicWords, rule, bool)) as [Record<string, string>, Record<string, string>];
52
52
 
53
- /** 将设置保存到mw.config */
53
+ /**
54
+ * 将设置保存到mw.config
55
+ * @param config 设置
56
+ */
54
57
  const setConfig = (config: MwConfig): void => {
55
58
  mw.config.set('extCodeMirrorConfig', config);
56
59
  };
@@ -146,3 +149,38 @@ export const getMwConfig = async (): Promise<MwConfig> => {
146
149
  localStorage.setItem('InPageEditMwConfig', JSON.stringify(ALL_SETTINGS_CACHE));
147
150
  return config!;
148
151
  };
152
+
153
+ /**
154
+ * 将MwConfig转换为Config
155
+ * @param minConfig 基础Config
156
+ * @param mwConfig MwConfig
157
+ */
158
+ export const getParserConfig = (minConfig: Config, mwConfig: MwConfig): Config => {
159
+ const config: Config = {
160
+ ...minConfig,
161
+ ext: Object.keys(mwConfig.tags),
162
+ namespaces: mw.config.get('wgFormattedNamespaces'),
163
+ nsid: mwConfig.nsid,
164
+ doubleUnderscore: mwConfig.doubleUnderscore.map(
165
+ obj => Object.keys(obj).map(s => s.slice(2, -2)),
166
+ ) as [string[], string[]],
167
+ variants: mwConfig.variants!,
168
+ protocol: mwConfig.urlProtocols.replace(/\\:/gu, ':'),
169
+ };
170
+ [config.parserFunction[0]] = mwConfig.functionSynonyms;
171
+ if (!USING_LOCAL) {
172
+ for (const [key, val] of Object.entries(mwConfig.functionSynonyms[0])) {
173
+ if (!key.startsWith('#')) {
174
+ config.parserFunction[0][`#${key}`] = val;
175
+ }
176
+ }
177
+ }
178
+ config.parserFunction[1] = [
179
+ ...Object.keys(mwConfig.functionSynonyms[1]),
180
+ '=',
181
+ ];
182
+ for (const key of Object.keys(mwConfig.img!)) {
183
+ config.img[key] = mwConfig.img![key]!.slice(4);
184
+ }
185
+ return config;
186
+ };
package/mw/msg.ts CHANGED
@@ -1,6 +1,11 @@
1
- import {CDN} from './base';
1
+ import type {CodeMirror} from './base';
2
2
 
3
- export const REPO_CDN = 'npm/@bhsd/codemirror-mediawiki@2.3.2';
3
+ export const REPO_CDN = 'npm/@bhsd/codemirror-mediawiki@2.3.4';
4
+
5
+ const {vendor, userAgent, maxTouchPoints, platform} = navigator;
6
+
7
+ export const isMac = vendor.includes('Apple Computer') && (userAgent.includes('Mobile/') || maxTouchPoints > 2)
8
+ || platform.includes('Mac');
4
9
 
5
10
  const storageKey = 'codemirror-mediawiki-i18n',
6
11
  languages: Record<string, string> = {
@@ -21,8 +26,11 @@ const storageKey = 'codemirror-mediawiki-i18n',
21
26
  {version} = i18n,
22
27
  curVersion = REPO_CDN.slice(REPO_CDN.lastIndexOf('@') + 1);
23
28
 
24
- /** 加载 I18N */
25
- export const setI18N = async (): Promise<void> => {
29
+ /**
30
+ * 加载 I18N
31
+ * @param CDN CDN地址
32
+ */
33
+ export const setI18N = async (CDN: string): Promise<void> => {
26
34
  if (i18n['lang'] !== lang || version !== curVersion) {
27
35
  try {
28
36
  Object.assign(i18n, await (await fetch(`${CDN}/${REPO_CDN}/i18n/${lang}.json`)).json());
@@ -33,7 +41,11 @@ export const setI18N = async (): Promise<void> => {
33
41
  }
34
42
  }
35
43
  for (const [k, v] of Object.entries(i18n)) {
36
- mw.messages.set(`cm-mw-${k}`, v);
44
+ if (!k.endsWith('-mac')) {
45
+ mw.messages.set(`cm-mw-${k}`, v);
46
+ } else if (isMac) {
47
+ mw.messages.set(`cm-mw-${k.slice(0, -4)}`, v);
48
+ }
37
49
  }
38
50
  };
39
51
 
@@ -61,6 +73,11 @@ const notify = async (key: string, ...args: string[]): Promise<JQuery<HTMLElemen
61
73
  return $p;
62
74
  };
63
75
 
76
+ /**
77
+ * 欢迎消息
78
+ * @param baseVersion 首次加入新插件的版本
79
+ * @param addons 新插件
80
+ */
64
81
  export const welcome = async (baseVersion: string, addons: string[]): Promise<void> => {
65
82
  let notification: JQuery<HTMLElement> | undefined;
66
83
  if (!version) { // 首次安装
@@ -82,3 +99,27 @@ export const welcome = async (baseVersion: string, addons: string[]): Promise<vo
82
99
  document.getElementById('cm-settings')!.dispatchEvent(new MouseEvent('click'));
83
100
  });
84
101
  };
102
+
103
+ /**
104
+ * 本地化
105
+ * @param cm 编辑器实例
106
+ */
107
+ export const localize = (cm: CodeMirror): void => {
108
+ const obj: Record<string, string> = {},
109
+ messages = [
110
+ 'Find',
111
+ 'next',
112
+ 'previous',
113
+ 'all',
114
+ 'match case',
115
+ 'regexp',
116
+ 'by word',
117
+ 'Replace',
118
+ 'replace',
119
+ 'replace all',
120
+ ];
121
+ for (const message of messages) {
122
+ obj[message] = msg(`phrase-${message.replace(/ /gu, '-')}`);
123
+ }
124
+ cm.localize(obj);
125
+ };
package/mw/openLinks.ts CHANGED
@@ -1,13 +1,13 @@
1
- const {vendor, userAgent, maxTouchPoints, platform} = navigator,
2
- modKey = vendor.includes('Apple Computer') && (userAgent.includes('Mobile/') || maxTouchPoints > 2)
3
- || platform.includes('Mac')
4
- ? 'metaKey'
5
- : 'ctrlKey';
1
+ import {isMac} from './msg';
6
2
 
7
- export const pageSelector = '.cm-mw-template-name, .cm-mw-link-pagename';
3
+ const modKey = isMac ? 'metaKey' : 'ctrlKey',
4
+ pageSelector = '.cm-mw-template-name, .cm-mw-link-pagename';
8
5
 
9
- /** 点击时在新页面打开链接、模板等 */
10
- export const openLinks = function(this: HTMLElement, e: JQuery.ClickEvent): void {
6
+ /**
7
+ * 点击时在新页面打开链接、模板等
8
+ * @param e 点击事件
9
+ */
10
+ const handler = function(this: HTMLElement, e: JQuery.ClickEvent): void {
11
11
  if (!e[modKey]) {
12
12
  return;
13
13
  }
@@ -34,3 +34,17 @@ export const openLinks = function(this: HTMLElement, e: JQuery.ClickEvent): void
34
34
  }
35
35
  open(new mw.Title(page, this.classList.contains('cm-mw-template-name') ? 10 : 0).getUrl(undefined), '_blank');
36
36
  };
37
+
38
+ /**
39
+ * 添加或移除打开链接的事件
40
+ * @param ele 编辑器DOM
41
+ * @param on 是否添加
42
+ */
43
+ export const openLinks = (ele: HTMLElement, on?: boolean): void => {
44
+ if (on) {
45
+ mw.loader.load('mediawiki.Title');
46
+ $(ele).on('click', pageSelector, handler).css('--codemirror-cursor', 'pointer');
47
+ } else if (on === false) {
48
+ $(ele).off('click', pageSelector, handler).css('--codemirror-cursor', '');
49
+ }
50
+ };
package/mw/preference.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import {msg} from './msg';
2
2
  import type {CodeMirror} from './base';
3
3
 
4
- export const storageKey = 'codemirror-mediawiki-addons',
5
- indentKey = 'codemirror-mediawiki-indent';
4
+ const storageKey = 'codemirror-mediawiki-addons';
5
+ export const indentKey = 'codemirror-mediawiki-indent',
6
+ prefs = new Set<string>(JSON.parse(localStorage.getItem(storageKey)!) as string[] | null);
6
7
 
7
8
  const options = [
8
9
  'allowMultipleSelections',
@@ -28,13 +29,12 @@ let dialog: OO.ui.MessageDialog | undefined,
28
29
 
29
30
  /**
30
31
  * 打开设置对话框
31
- * @param addons 预设的扩展
32
32
  * @param editors CodeMirror实例
33
33
  */
34
- export const openPreference = async (addons: Set<string>, editors: (CodeMirror | undefined)[]): Promise<void> => {
34
+ export const openPreference = async (editors: (CodeMirror | undefined)[]): Promise<void> => {
35
35
  await mw.loader.using(['oojs-ui-windows', 'oojs-ui.styles.icons-content']);
36
36
  if (dialog) {
37
- widget.setValue([...addons] as unknown as string);
37
+ widget.setValue([...prefs] as unknown as string);
38
38
  indentWidget.setValue(indent);
39
39
  } else {
40
40
  dialog = new OO.ui.MessageDialog();
@@ -43,17 +43,14 @@ export const openPreference = async (addons: Set<string>, editors: (CodeMirror |
43
43
  windowManager.addWindows([dialog]);
44
44
  widget = new OO.ui.CheckboxMultiselectInputWidget({
45
45
  options: options.map(option => ({data: option, label: $($.parseHTML(msg(`addon-${option}`)))})),
46
- value: [...addons] as unknown as string,
46
+ value: [...prefs] as unknown as string,
47
47
  });
48
48
  field = new OO.ui.FieldLayout(widget, {
49
49
  label: msg('label'),
50
50
  align: 'top',
51
51
  });
52
- indentWidget = new OO.ui.TextInputWidget({placeholder: '\\t'});
53
- indentField = new OO.ui.FieldLayout(indentWidget, {
54
- label: msg('addon-indent'),
55
- notices: [msg('notice')],
56
- });
52
+ indentWidget = new OO.ui.TextInputWidget({value: indent, placeholder: '\\t'});
53
+ indentField = new OO.ui.FieldLayout(indentWidget, {label: msg('addon-indent')});
57
54
  }
58
55
 
59
56
  const data = await (dialog.open({
@@ -68,9 +65,9 @@ export const openPreference = async (addons: Set<string>, editors: (CodeMirror |
68
65
  if (typeof data === 'object' && data.action === 'accept') {
69
66
  const value = widget.getValue() as unknown as string[];
70
67
  indent = indentWidget.getValue(); // eslint-disable-line require-atomic-updates
71
- addons.clear();
68
+ prefs.clear();
72
69
  for (const option of value) {
73
- addons.add(option);
70
+ prefs.add(option);
74
71
  }
75
72
  for (const cm of editors) {
76
73
  cm?.prefer(value);
@@ -2,6 +2,10 @@ import type {CodeMirror} from './base';
2
2
 
3
3
  export const instances = new WeakMap<HTMLTextAreaElement, CodeMirror>();
4
4
 
5
+ /**
6
+ * 获取CodeMirror实例
7
+ * @param $ele textarea元素的jQuery对象
8
+ */
5
9
  const getInstance = ($ele: JQuery<HTMLTextAreaElement>): CodeMirror => instances.get($ele[0]!)!;
6
10
 
7
11
  function getCaretPosition(this: JQuery<HTMLTextAreaElement>, option: {startAndEnd: true}): [number, number];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bhsd/codemirror-mediawiki",
3
- "version": "2.3.2",
3
+ "version": "2.3.4",
4
4
  "description": "Modified CodeMirror mode based on wikimedia/mediawiki-extensions-CodeMirror",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -13,13 +13,10 @@
13
13
  "license": "GPL-2.0",
14
14
  "files":[
15
15
  "/i18n/",
16
- "/src/",
17
- "!/src/gh-page.ts",
18
- "!/src/plugins.ts",
19
- "!/src/*.d.ts",
20
16
  "/mw/*.ts",
21
17
  "!/mw/*.d.ts",
22
18
  "/dist/",
19
+ "!/dist/main.min.js.map",
23
20
  "/mediawiki.css"
24
21
  ],
25
22
  "browser": "dist/main.min.js",
@@ -30,7 +27,7 @@
30
27
  "url": "git+https://github.com/bhsd-harry/codemirror-mediawiki.git"
31
28
  },
32
29
  "scripts": {
33
- "build:core": "esbuild ./src/codemirror.ts --bundle --minify --target=es2018 --format=esm --sourcemap --outfile=dist/main.min.js && tsc --emitDeclarationOnly && rm dist/gh-page.d.ts",
30
+ "build:core": "esbuild ./src/codemirror.ts --bundle --minify --target=es2018 --format=esm --sourcemap --outfile=dist/main.min.js && tsc --emitDeclarationOnly && rm dist/config.d.ts dist/[efgp]*.d.ts",
34
31
  "build:mw": "esbuild ./mw/base.ts --bundle --minify --target=es2018 --format=esm --sourcemap --outfile=dist/mw.min.js",
35
32
  "build:gh-page": "bash build.sh",
36
33
  "build": "npm run build:core && npm run build:mw",
@@ -65,6 +62,7 @@
65
62
  "eslint": "^8.56.0",
66
63
  "eslint-plugin-es-x": "^7.5.0",
67
64
  "eslint-plugin-eslint-comments": "^3.2.0",
65
+ "eslint-plugin-jsdoc": "^48.0.2",
68
66
  "eslint-plugin-promise": "^6.1.1",
69
67
  "eslint-plugin-regexp": "^2.2.0",
70
68
  "eslint-plugin-unicorn": "^50.0.1",
package/dist/config.d.ts DELETED
@@ -1,130 +0,0 @@
1
- /**
2
- * @author MusikAnimal and others
3
- * @license GPL-2.0-or-later
4
- * @link https://gerrit.wikimedia.org/g/mediawiki/extensions/CodeMirror
5
- */
6
- import { Tag } from '@lezer/highlight';
7
- /**
8
- * Configuration for the MediaWiki highlighting mode for CodeMirror.
9
- */
10
- export declare const modeConfig: {
11
- /**
12
- * All HTML/XML tags permitted in MediaWiki Core.
13
- *
14
- * @see https://www.mediawiki.org/wiki/Extension:CodeMirror#Extension_integration
15
- */
16
- permittedHtmlTags: string[];
17
- /**
18
- * HTML tags that are only self-closing.
19
- */
20
- implicitlyClosedHtmlTags: string[];
21
- /**
22
- * Mapping of MediaWiki-esque token identifiers to a standardized lezer highlighting tag.
23
- * Values are one of the default highlighting tags.
24
- *
25
- * Once we allow use of other themes, we may want to tweak these values for aesthetic reasons.
26
- *
27
- * @see https://lezer.codemirror.net/docs/ref/#highlight.tags
28
- * @internal
29
- */
30
- tags: {
31
- apostrophes: string;
32
- apostrophesBold: string;
33
- apostrophesItalic: string;
34
- comment: string;
35
- doubleUnderscore: string;
36
- extLink: string;
37
- extLinkBracket: string;
38
- extLinkProtocol: string;
39
- extLinkText: string;
40
- hr: string;
41
- htmlTagAttribute: string;
42
- htmlTagBracket: string;
43
- htmlTagName: string;
44
- linkBracket: string;
45
- linkDelimiter: string;
46
- linkText: string;
47
- linkToSection: string;
48
- list: string;
49
- parserFunction: string;
50
- parserFunctionBracket: string;
51
- parserFunctionDelimiter: string;
52
- parserFunctionName: string;
53
- sectionHeader: string;
54
- sectionHeader1: string;
55
- sectionHeader2: string;
56
- sectionHeader3: string;
57
- sectionHeader4: string;
58
- sectionHeader5: string;
59
- sectionHeader6: string;
60
- signature: string;
61
- tableBracket: string;
62
- tableDefinition: string;
63
- tableDelimiter: string;
64
- template: string;
65
- templateArgumentName: string;
66
- templateBracket: string;
67
- templateDelimiter: string;
68
- templateName: string;
69
- templateVariable: string;
70
- templateVariableBracket: string;
71
- templateVariableName: string;
72
- section: string;
73
- em: string;
74
- error: string;
75
- extGround: string;
76
- ext2Ground: string;
77
- ext2LinkGround: string;
78
- ext3Ground: string;
79
- ext3LinkGround: string;
80
- extLinkGround: string;
81
- extTag: string;
82
- extTagAttribute: string;
83
- extTagBracket: string;
84
- extTagName: string;
85
- freeExtLink: string;
86
- freeExtLinkProtocol: string;
87
- htmlEntity: string;
88
- link: string;
89
- linkGround: string;
90
- linkPageName: string;
91
- pageName: string;
92
- skipFormatting: string;
93
- strong: string;
94
- tableCaption: string;
95
- templateExtGround: string;
96
- templateExt2Ground: string;
97
- templateExt2LinkGround: string;
98
- templateExt3Ground: string;
99
- templateExt3LinkGround: string;
100
- templateExtLinkGround: string;
101
- templateGround: string;
102
- templateLinkGround: string;
103
- templateVariableDelimiter: string;
104
- template2ExtGround: string;
105
- template2Ext2Ground: string;
106
- template2Ext3Ground: string;
107
- templatet2Ext2LinkGround: string;
108
- template2Ext3LinkGround: string;
109
- template2ExtLinkGround: string;
110
- template2Ground: string;
111
- template2LinkGround: string;
112
- template3ExtGround: string;
113
- template3Ext2Ground: string;
114
- template3Ext3Ground: string;
115
- template3ExtLinkGround: string;
116
- template3Ext2LinkGround: string;
117
- template3Ext3LinkGround: string;
118
- template3Ground: string;
119
- template3LinkGround: string;
120
- };
121
- /**
122
- * These are custom tokens (a.k.a. tags) that aren't mapped to any of the standardized tags.
123
- *
124
- * TODO: pass parent Tags in Tag.define() where appropriate for better theming.
125
- *
126
- * @see https://codemirror.net/docs/ref/#language.StreamParser.tokenTable
127
- * @see https://lezer.codemirror.net/docs/ref/#highlight.Tag%5Edefine
128
- */
129
- readonly tokenTable: Record<string, Tag>;
130
- };
package/dist/escape.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import type { KeyBinding } from '@codemirror/view';
2
- export declare const keyMap: KeyBinding[];
package/dist/fold.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import { EditorView } from '@codemirror/view';
2
- import { StateField } from '@codemirror/state';
3
- import type { Tooltip } from '@codemirror/view';
4
- /**
5
- * 寻找匹配的括号并折叠
6
- * @param view EditorView
7
- */
8
- export declare const fold: (view: EditorView) => boolean;
9
- export declare const cursorTooltipField: StateField<Tooltip | null>;
10
- export declare const cursorTooltipTheme: import("@codemirror/state").Extension;
11
- export declare const handler: (view: EditorView) => (e: MouseEvent) => void;