@bhsd/codemirror-mediawiki 3.0.3 → 3.2.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/dist/escape.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { KeyBinding } from '@codemirror/view';
1
+ import { CodeMirror6 } from './codemirror';
2
+ import type { Extension } from '@codemirror/state';
2
3
  export declare const escapeHTML: (str: string) => string, escapeURI: (str: string) => string;
3
- declare const _default: KeyBinding[];
4
+ declare const _default: (cm: CodeMirror6) => Extension;
4
5
  export default _default;
package/dist/escape.js CHANGED
@@ -1,5 +1,8 @@
1
+ import { keymap } from '@codemirror/view';
2
+ import { EditorSelection } from '@codemirror/state';
1
3
  import { indentMore, indentLess } from '@codemirror/commands';
2
- import { CodeMirror6 } from './codemirror';
4
+ import { getLSP } from '@bhsd/browser';
5
+ import { CodeMirror6, menuRegistry } from './codemirror';
3
6
  const entity = { '"': 'quot', "'": 'apos', '<': 'lt', '>': 'gt', '&': 'amp', ' ': 'nbsp' };
4
7
  /**
5
8
  * 根据函数转换选中文本
@@ -7,7 +10,7 @@ const entity = { '"': 'quot', "'": 'apos', '<': 'lt', '>': 'gt', '&': 'amp', ' '
7
10
  * @param cmd 原命令
8
11
  */
9
12
  const convert = (func, cmd) => (view) => {
10
- if (view.state.selection.ranges.some(range => !range.empty)) {
13
+ if (view.state.selection.ranges.some(({ empty }) => !empty)) {
11
14
  CodeMirror6.replaceSelections(view, func);
12
15
  return true;
13
16
  }
@@ -29,7 +32,76 @@ export const escapeHTML = (str) => [...str].map(c => {
29
32
  }
30
33
  return encodeURIComponent(str);
31
34
  };
32
- export default /* @__PURE__ */ (() => [
35
+ const escapeWiki = (cm) => {
36
+ const view = cm.view, { state } = view, { ranges } = state.selection, lsp = getLSP(view, false, cm.getWikiConfig);
37
+ if (lsp && 'provideRefactoringAction' in lsp && ranges.some(({ empty }) => !empty)) {
38
+ (async () => {
39
+ const replacements = new WeakMap();
40
+ for (const range of ranges) {
41
+ // eslint-disable-next-line no-await-in-loop
42
+ const [action] = await lsp.provideRefactoringAction(state.sliceDoc(range.from, range.to));
43
+ replacements.set(range, action?.edit.changes[''][0].newText);
44
+ }
45
+ view.dispatch(state.changeByRange(range => {
46
+ const insert = replacements.get(range);
47
+ if (insert === undefined) {
48
+ return { range };
49
+ }
50
+ return {
51
+ range: EditorSelection.range(range.from, range.from + insert.length),
52
+ changes: { from: range.from, to: range.to, insert },
53
+ };
54
+ }));
55
+ })();
56
+ return true;
57
+ }
58
+ return false;
59
+ };
60
+ const handlerBase = (view, e) => {
61
+ e.stopPropagation();
62
+ view.focus();
63
+ };
64
+ let items;
65
+ menuRegistry.push({
66
+ name: 'escape',
67
+ isActionable({ lang, view }) {
68
+ return lang === 'mediawiki' && view.state.selection.ranges.some(({ empty }) => !empty);
69
+ },
70
+ getItems(cm) {
71
+ if (!items) {
72
+ const view = cm.view, btnHTML = document.createElement('div'), btnURI = document.createElement('div');
73
+ btnHTML.textContent = 'HTML escape';
74
+ btnHTML.addEventListener('click', e => {
75
+ CodeMirror6.replaceSelections(view, escapeHTML);
76
+ handlerBase(view, e);
77
+ });
78
+ btnURI.textContent = 'URI encode/decode';
79
+ btnURI.addEventListener('click', e => {
80
+ CodeMirror6.replaceSelections(view, escapeURI);
81
+ handlerBase(view, e);
82
+ });
83
+ items = [btnHTML, btnURI];
84
+ const lsp = getLSP(view, false, cm.getWikiConfig);
85
+ if (lsp && 'provideRefactoringAction' in lsp) {
86
+ const btnWiki = document.createElement('div');
87
+ btnWiki.textContent = 'Escape with magic words';
88
+ btnWiki.addEventListener('click', e => {
89
+ escapeWiki(cm);
90
+ handlerBase(view, e);
91
+ });
92
+ items.unshift(btnWiki);
93
+ }
94
+ }
95
+ return items;
96
+ },
97
+ });
98
+ export default (cm) => keymap.of([
33
99
  { key: 'Mod-[', run: convert(escapeHTML, indentLess) },
34
100
  { key: 'Mod-]', run: convert(escapeURI, indentMore) },
35
- ])();
101
+ {
102
+ key: 'Mod-\\',
103
+ run() {
104
+ return escapeWiki(cm);
105
+ },
106
+ },
107
+ ]);
package/dist/fold.d.ts CHANGED
@@ -1,14 +1,10 @@
1
- import { GutterMarker, ViewPlugin } from '@codemirror/view';
2
- import { RangeSet } from '@codemirror/state';
3
- import type { EditorView, Tooltip, ViewUpdate, BlockInfo, Command } from '@codemirror/view';
4
- import type { EditorState, StateEffect, Extension } from '@codemirror/state';
1
+ import type { EditorView, Command } from '@codemirror/view';
2
+ import type { EditorState, Extension } from '@codemirror/state';
5
3
  import type { SyntaxNode, Tree } from '@lezer/common';
6
4
  export interface DocRange {
7
5
  from: number;
8
6
  to: number;
9
7
  }
10
- declare type AnchorUpdate = (pos: number, range: DocRange) => number;
11
- export declare const updateSelection: AnchorUpdate;
12
8
  /**
13
9
  * Update the stack of opening (+) or closing (-) brackets
14
10
  * @param state
@@ -23,54 +19,9 @@ export declare const braceStackUpdate: (state: EditorState, node: SyntaxNode) =>
23
19
  * @param refOnly 是否仅检查`<ref>`标签
24
20
  */
25
21
  export declare const foldable: (state: EditorState, posOrNode: number | SyntaxNode, tree?: Tree | null, refOnly?: boolean) => DocRange | false;
26
- /**
27
- * 创建折叠提示
28
- * @param state
29
- */
30
- export declare const create: (state: EditorState) => Tooltip | null;
31
- /**
32
- * 执行折叠
33
- * @param view
34
- * @param effects 折叠
35
- * @param anchor 光标位置
36
- */
37
- export declare const execute: (view: EditorView, effects: StateEffect<DocRange>[], anchor: number) => boolean;
38
- /**
39
- * The rightmost position of all selections, to be updated with folding
40
- * @param state
41
- */
42
- export declare const getAnchor: (state: EditorState) => number;
43
- /**
44
- * 折叠所有模板
45
- * @param state
46
- * @param tree 语法树
47
- * @param effects 折叠
48
- * @param node 语法树节点
49
- * @param end 终止位置
50
- * @param anchor 光标位置
51
- * @param update 更新光标位置
52
- * @param refOnly 是否仅检查`<ref>`标签
53
- */
54
- export declare const traverse: (state: EditorState, tree: Tree, effects: StateEffect<DocRange>[], node: SyntaxNode | null, end: number, anchor: number, update: AnchorUpdate, refOnly?: boolean) => number;
55
- export declare class FoldMarker extends GutterMarker {
56
- readonly open: boolean;
57
- constructor(open: boolean);
58
- eq(other: this): boolean;
59
- toDOM({ state }: EditorView): HTMLSpanElement;
60
- }
61
- export declare const findFold: ({ state }: EditorView, line: BlockInfo) => DocRange | undefined;
62
22
  export declare const foldableLine: ({ state, viewport: { to: end }, viewportLineBlocks }: EditorView, { from: f, to: t }: DocRange) => DocRange | false;
63
- export declare const markers: ViewPlugin<{
64
- markers: RangeSet<FoldMarker>;
65
- update({ docChanged, viewportChanged, startState, state, view }: ViewUpdate): void;
66
- }, undefined>;
67
- /**
68
- * 生成折叠命令
69
- * @param refOnly 是否仅检查`<ref>`标签
70
- */
71
- export declare const foldCommand: (refOnly?: boolean) => Command;
72
23
  export declare const foldRef: Command;
73
- declare const _default: [(e?: Extension | undefined) => Extension];
24
+ declare const _default: (e?: Extension | undefined) => Extension;
74
25
  export default _default;
75
26
  export declare const mediaWikiFold: Extension;
76
27
  /**
package/dist/fold.js CHANGED
@@ -5,8 +5,7 @@ import { getRegex } from '@bhsd/common';
5
5
  import { tokens } from './config';
6
6
  import { matchTag, getTag } from './matchTag';
7
7
  const getExtRegex = /* @__PURE__ */ getRegex(tag => new RegExp(`mw-tag-${tag}(?![a-z])`, 'u'));
8
- export const updateSelection = (pos, { to }) => Math.max(pos, to);
9
- const updateAll = (pos, { from, to }) => from <= pos && to > pos ? to : pos;
8
+ const updateSelection = (pos, { to }) => Math.max(pos, to), updateAll = (pos, { from, to }) => from <= pos && to > pos ? to : pos;
10
9
  /**
11
10
  * Check if a SyntaxNode is among the specified components
12
11
  * @param keys The keys of the tokens to check
@@ -145,7 +144,7 @@ export const foldable = (state, posOrNode, tree, refOnly = false) => {
145
144
  * 创建折叠提示
146
145
  * @param state
147
146
  */
148
- export const create = (state) => {
147
+ const create = (state) => {
149
148
  const { selection: { main: { head } } } = state, range = foldable(state, head);
150
149
  if (range) {
151
150
  const { from, to } = range;
@@ -179,7 +178,7 @@ export const create = (state) => {
179
178
  * @param effects 折叠
180
179
  * @param anchor 光标位置
181
180
  */
182
- export const execute = (view, effects, anchor) => {
181
+ const execute = (view, effects, anchor) => {
183
182
  if (effects.length > 0) {
184
183
  view.dom.querySelector('.cm-tooltip-fold')?.remove();
185
184
  // Fold the template(s) and update the cursor position
@@ -192,7 +191,7 @@ export const execute = (view, effects, anchor) => {
192
191
  * The rightmost position of all selections, to be updated with folding
193
192
  * @param state
194
193
  */
195
- export const getAnchor = (state) => Math.max(...state.selection.ranges.map(({ to }) => to));
194
+ const getAnchor = (state) => Math.max(...state.selection.ranges.map(({ to }) => to));
196
195
  /**
197
196
  * 折叠所有模板
198
197
  * @param state
@@ -204,7 +203,7 @@ export const getAnchor = (state) => Math.max(...state.selection.ranges.map(({ to
204
203
  * @param update 更新光标位置
205
204
  * @param refOnly 是否仅检查`<ref>`标签
206
205
  */
207
- export const traverse = (state, tree, effects, node, end, anchor, update, refOnly) => {
206
+ const traverse = (state, tree, effects, node, end, anchor, update, refOnly) => {
208
207
  while (node && node.from <= end) {
209
208
  /* eslint-disable no-param-reassign */
210
209
  const range = foldable(state, node, tree, refOnly);
@@ -220,7 +219,7 @@ export const traverse = (state, tree, effects, node, end, anchor, update, refOnl
220
219
  }
221
220
  return anchor;
222
221
  };
223
- export class FoldMarker extends GutterMarker {
222
+ class FoldMarker extends GutterMarker {
224
223
  constructor(open) {
225
224
  super();
226
225
  this.open = open;
@@ -236,7 +235,7 @@ export class FoldMarker extends GutterMarker {
236
235
  }
237
236
  }
238
237
  const canFold = /* @__PURE__ */ new FoldMarker(true), canUnfold = /* @__PURE__ */ new FoldMarker(false);
239
- export const findFold = ({ state }, line) => {
238
+ const findFold = ({ state }, line) => {
240
239
  let found;
241
240
  state.field(foldState, false)?.between(line.from, line.to, (from, to) => {
242
241
  if (!found && to === line.to) {
@@ -310,7 +309,7 @@ const buildMarkers = (view) => {
310
309
  }
311
310
  return builder.finish();
312
311
  };
313
- export const markers = /* @__PURE__ */ ViewPlugin.fromClass(class {
312
+ const markers = /* @__PURE__ */ ViewPlugin.fromClass(class {
314
313
  constructor(view) {
315
314
  this.markers = buildMarkers(view);
316
315
  }
@@ -324,17 +323,17 @@ export const markers = /* @__PURE__ */ ViewPlugin.fromClass(class {
324
323
  }
325
324
  }
326
325
  });
327
- const defaultFoldExtension = [foldGutter(), keymap.of(foldKeymap)];
326
+ const defaultFoldExtension = /* @__PURE__ */ (() => [foldGutter(), keymap.of(foldKeymap)])();
328
327
  /**
329
328
  * 生成折叠命令
330
329
  * @param refOnly 是否仅检查`<ref>`标签
331
330
  */
332
- export const foldCommand = (refOnly) => view => {
331
+ const foldCommand = (refOnly) => view => {
333
332
  const { state } = view, tree = syntaxTree(state), effects = [], anchor = traverse(state, tree, effects, tree.topNode.firstChild, Infinity, getAnchor(state), updateAll, refOnly);
334
333
  return execute(view, effects, anchor);
335
334
  };
336
335
  export const foldRef = /* @__PURE__ */ foldCommand(true);
337
- export default [(e = defaultFoldExtension) => e];
336
+ export default ((e = defaultFoldExtension) => e);
338
337
  export const mediaWikiFold = /* @__PURE__ */ (() => [
339
338
  codeFolding({
340
339
  placeholderDOM(view) {
package/dist/html.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { LanguageSupport } from '@codemirror/language';
2
+ import type { MwConfig } from './token';
3
+ declare const _default: (config: MwConfig) => LanguageSupport;
4
+ export default _default;
package/dist/html.js ADDED
@@ -0,0 +1,31 @@
1
+ import { configureNesting } from '@lezer/html';
2
+ import { htmlPlain, htmlCompletionSourceWith } from '@codemirror/lang-html';
3
+ import { javascript, javascriptLanguage } from '@codemirror/lang-javascript';
4
+ import { cssLanguage } from '@codemirror/lang-css';
5
+ import { LanguageSupport } from '@codemirror/language';
6
+ import { jsCompletion } from './javascript';
7
+ import { mediawiki } from './mediawiki';
8
+ import { cssCompletion } from './css';
9
+ export default (config) => {
10
+ const { language, support } = mediawiki(config), lang = new LanguageSupport(htmlPlain.configure({
11
+ wrap: configureNesting([
12
+ { tag: 'script', parser: javascriptLanguage.parser },
13
+ { tag: 'style', parser: cssLanguage.parser },
14
+ { tag: 'noinclude', parser: language.parser },
15
+ ], [{ name: 'style', parser: cssLanguage.parser.configure({ top: 'Styles' }) }]),
16
+ }), [
17
+ htmlPlain.data.of({
18
+ autocomplete: htmlCompletionSourceWith({
19
+ extraTags: {
20
+ noinclude: { globalAttrs: false },
21
+ },
22
+ }),
23
+ }),
24
+ javascript().support,
25
+ jsCompletion,
26
+ cssCompletion(),
27
+ support,
28
+ ]);
29
+ Object.assign(lang, { nestedMWLanguage: language });
30
+ return lang;
31
+ };
package/dist/indent.js CHANGED
@@ -1,4 +1,4 @@
1
- const noDetectionLangs = new Set(['plain', 'mediawiki', 'html']);
1
+ const noDetectionLangs = new Set(['plain', 'mediawiki']);
2
2
  const getLines = (text) => text.children?.flatMap(getLines) ?? text.text;
3
3
  /**
4
4
  * 检测文本的缩进方式
@@ -0,0 +1,102 @@
1
+ import { CodeMirror6 } from './codemirror';
2
+ import type { LanguageSupport } from '@codemirror/language';
3
+ import type { MwConfig } from './token';
4
+ import type { LintSourceGetter } from './lintsource';
5
+ export type { MwConfig };
6
+ export { CodeMirror6 };
7
+ /** Register the `highlightSpecialChars` extension */
8
+ export declare const registerHighlightSpecialChars: () => void;
9
+ /** Register the `highlightActiveLine` extension */
10
+ export declare const registerHighlightActiveLine: () => void;
11
+ /** Register the `highlightWhitespace` extension */
12
+ export declare const registerHighlightWhitespace: () => void;
13
+ /** Register the `highlightTrailingWhitespace` extension */
14
+ export declare const registerHighlightTrailingWhitespace: () => void;
15
+ /** Register the `highlightSelectionMatches` extension */
16
+ export declare const registerHighlightSelectionMatches: () => void;
17
+ /** Register the `bracketMatching` extension */
18
+ export declare const registerBracketMatching: () => void;
19
+ /** Register the `closeBrackets` extension */
20
+ export declare const registerCloseBrackets: () => void;
21
+ /** Register the `scrollPastEnd` extension */
22
+ export declare const registerScrollPastEnd: () => void;
23
+ /** Register the `allowMultipleSelections` extension */
24
+ export declare const registerAllowMultipleSelections: () => void;
25
+ /** Register the `autocompletion` extension */
26
+ export declare const registerAutocompletion: () => void;
27
+ /** Register the `codeFolding` extension */
28
+ export declare const registerCodeFolding: () => void;
29
+ /** Register the `colorPicker` extension */
30
+ export declare const registerColorPicker: () => void;
31
+ /** Register all common extensions */
32
+ export declare const registerCommonExtensions: () => void;
33
+ /** Register MediaWiki language support */
34
+ export declare const registerMediaWiki: () => void;
35
+ /** Register the `openLinks` extension */
36
+ export declare const registerOpenLinks: () => void;
37
+ /** Register the `escape` extension */
38
+ export declare const registerEscape: () => void;
39
+ /** Register the `refHover` extension */
40
+ export declare const registerRefHover: () => void;
41
+ /** Register the `hover` extension */
42
+ export declare const registerHover: () => void;
43
+ /** Register the `signatureHelp` extension */
44
+ export declare const registerSignatureHelp: () => void;
45
+ /** Register the `inlayHints` extension */
46
+ export declare const registerInlayHints: () => void;
47
+ /** Register the `colorPicker` extension for MediaWiki */
48
+ export declare const registerColorPickerForMediaWiki: () => void;
49
+ /** Register the `bracketMatching` extension for MediaWiki */
50
+ export declare const registerBracketMatchingForMediaWiki: () => void;
51
+ /** Register the `codeFolding` extension for MediaWiki */
52
+ export declare const registerCodeFoldingForMediaWiki: () => void;
53
+ /** Register MediaWiki core language support */
54
+ export declare const registerMediaWikiCore: () => void;
55
+ /** Register mixed MediaWiki-HTML language support */
56
+ export declare const registerHTML: () => void;
57
+ /** Register the `closeBrackets` extension for mixed MediaWiki-HTML */
58
+ export declare const registerCloseBracketsForHTML: () => void;
59
+ /** Register the `colorPicker` extension for mixed MediaWiki-HTML */
60
+ export declare const registerColorPickerForHTML: () => void;
61
+ /** Register mixed MediaWiki-HTML core language support */
62
+ export declare const registerHTMLCore: () => void;
63
+ /** Register JavaScript language support */
64
+ export declare const registerJavaScript: () => void;
65
+ /** Register JavaScript core language support */
66
+ export declare const registerJavaScriptCore: () => void;
67
+ /** Register CSS language support */
68
+ export declare const registerCSS: () => void;
69
+ /** Register the `colorPicker` extension for CSS */
70
+ export declare const registerColorPickerForCSS: () => void;
71
+ /** Register CSS core language support */
72
+ export declare const registerCSSCore: () => void;
73
+ /** Register JSON language support */
74
+ export declare const registerJSON: () => void;
75
+ /** Register JSON core language support */
76
+ export declare const registerJSONCore: () => void;
77
+ /** Register Lua language support */
78
+ export declare const registerLua: () => void;
79
+ /** Register Lua core language support */
80
+ export declare const registerLuaCore: () => void;
81
+ /** Register Vue language support */
82
+ export declare const registerVue: () => void;
83
+ /** Register the `closeBrackets` extension for Vue */
84
+ export declare const registerCloseBracketsForVue: () => void;
85
+ /** Register the `colorPicker` extension for Vue */
86
+ export declare const registerColorPickerForVue: () => void;
87
+ /** Register Vue core language support */
88
+ export declare const registerVueCore: () => void;
89
+ /**
90
+ * Register a custom language support
91
+ * @param name language name
92
+ * @param lang language support
93
+ * @param lintSource optional linter
94
+ */
95
+ export declare const registerLanguage: (name: string, lang: (config?: unknown) => LanguageSupport, lintSource?: LintSourceGetter) => void;
96
+ /**
97
+ * Register a custom language support without common extensions
98
+ * @param name language name
99
+ * @param lang language support
100
+ * @param lintSource optional linter
101
+ */
102
+ export declare const registerLanguageCore: (name: string, lang: (config?: unknown) => LanguageSupport, lintSource?: LintSourceGetter) => void;