@bhsd/codemirror-mediawiki 2.28.2 → 2.29.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/README.md CHANGED
@@ -7,7 +7,8 @@
7
7
  <summary>Expand</summary>
8
8
 
9
9
  - [Description](#description)
10
- - [Usage](#usage)
10
+ - [Installation](#installation)
11
+ - [Browser Usage](#browser-usage)
11
12
  - [JavaScript](#javascript)
12
13
  - [CSS](#css)
13
14
  - [Constructor](#constructor)
@@ -68,7 +69,19 @@ Here is a [demo](https://bhsd-harry.github.io/codemirror-mediawiki). To experime
68
69
 
69
70
  Nonetheless, this repository also provides a customized version with additional functionality for use on a MediaWiki site. Browser editing tools such as [Wikiplus-highlight](https://github.com/bhsd-harry/Wikiplus-highlight) and an [InPageEdit plugin](https://github.com/inpageedit/Plugins) are built upon it. Please refer to a separate [README](./mw/README.md) file for the information.
70
71
 
71
- # Usage
72
+ # Installation
73
+
74
+ You can install the package via npm and import it as a module:
75
+
76
+ ```bash
77
+ npm install @bhsd/codemirror-mediawiki
78
+ ```
79
+
80
+ ```js
81
+ import {CodeMirror6} from '@bhsd/codemirror-mediawiki';
82
+ ```
83
+
84
+ # Browser Usage
72
85
 
73
86
  You can download the code via CDN, for example:
74
87
 
package/dist/bidi.js ADDED
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @author MusikAnimal
3
+ * @license GPL-2.0-or-later
4
+ * @see https://gerrit.wikimedia.org/g/mediawiki/extensions/CodeMirror
5
+ */
6
+ import { EditorView, Direction, ViewPlugin, Decoration } from '@codemirror/view';
7
+ import { Prec, RangeSetBuilder } from '@codemirror/state';
8
+ import { syntaxTree } from '@codemirror/language';
9
+ import { getTag } from './matchTag';
10
+ import { tokens } from './config';
11
+ const isolateLTR = Decoration.mark({
12
+ class: 'cm-bidi-isolate cm-bidi-ltr',
13
+ bidiIsolate: Direction.LTR,
14
+ }), isolate = Decoration.mark({ class: 'cm-bidi-isolate' });
15
+ export const computeIsolates = ({ visibleRanges, state, textDirection }) => {
16
+ const set = new RangeSetBuilder();
17
+ if (textDirection === Direction.RTL) {
18
+ for (const { from, to } of visibleRanges) {
19
+ let node = syntaxTree(state).resolve(from, 1), td = 0, table = 0, parameter = 0;
20
+ while (node && node.to <= to) {
21
+ const { name, from: f, to: t, nextSibling } = node;
22
+ if (/-(?:ext|html)tag-bracket/u.test(name) && state.sliceDoc(f, t).includes('<')) {
23
+ const tag = getTag(state, nextSibling);
24
+ if (tag) {
25
+ set.add(tag.from, tag.to, isolateLTR);
26
+ }
27
+ }
28
+ else if (!td && !table && name.includes(tokens.tableDefinition)) {
29
+ if (/-html-(?:table|tr)/u.test(name)) {
30
+ table = state.doc.lineAt(f).to;
31
+ set.add(f, table, isolateLTR);
32
+ }
33
+ else {
34
+ td = f;
35
+ }
36
+ }
37
+ else if (table && f > table) {
38
+ table = 0;
39
+ }
40
+ else if (td && name.includes(tokens.tableDelimiter2)) {
41
+ set.add(td, f, isolateLTR);
42
+ td = 0;
43
+ }
44
+ else if (/-(?:template|parserfunction)-delimiter/u.test(name)) {
45
+ if (parameter) {
46
+ set.add(parameter, f, isolate);
47
+ }
48
+ parameter = t;
49
+ }
50
+ else if (parameter && /-(?:template|parserfunction)-bracket/u.test(name)) {
51
+ if (state.sliceDoc(f, f + 1) === '}') {
52
+ set.add(parameter, f, isolate);
53
+ }
54
+ parameter = 0;
55
+ }
56
+ node = node.nextSibling;
57
+ }
58
+ }
59
+ }
60
+ return set.finish();
61
+ };
62
+ export default ViewPlugin.fromClass(class {
63
+ constructor(view) {
64
+ this.isolates = computeIsolates(view);
65
+ this.tree = syntaxTree(view.state);
66
+ this.dir = view.textDirection;
67
+ }
68
+ update({ docChanged, viewportChanged, state, view }) {
69
+ const tree = syntaxTree(state), { textDirection } = view;
70
+ if (docChanged || viewportChanged || tree !== this.tree || textDirection !== this.dir) {
71
+ this.isolates = computeIsolates(view);
72
+ this.tree = tree;
73
+ this.dir = textDirection;
74
+ }
75
+ }
76
+ }, {
77
+ provide(plugin) {
78
+ const access = (view) => view.plugin(plugin)?.isolates ?? Decoration.none;
79
+ return Prec.lowest([
80
+ EditorView.decorations.of(access),
81
+ EditorView.bidiIsolatedRanges.of(access),
82
+ ]);
83
+ },
84
+ });