@uiw/react-codemirror 4.7.0 → 4.8.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 +8 -5
- package/cjs/index.d.ts +0 -3
- package/cjs/index.js +0 -41
- package/cjs/index.js.map +10 -6
- package/cjs/theme/light.js.map +5 -5
- package/cjs/useCodeMirror.js +2 -2
- package/cjs/useCodeMirror.js.map +8 -6
- package/dist/codemirror.js +4009 -324
- package/dist/codemirror.min.js +1 -1
- package/esm/index.d.ts +0 -3
- package/esm/index.js +0 -3
- package/esm/index.js.map +6 -6
- package/esm/theme/light.js.map +5 -5
- package/esm/useCodeMirror.js +1 -1
- package/esm/useCodeMirror.js.map +6 -6
- package/package.json +23 -24
- package/src/index.tsx +0 -3
- package/src/useCodeMirror.ts +1 -1
package/dist/codemirror.js
CHANGED
|
@@ -1,26 +1,237 @@
|
|
|
1
1
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
2
2
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
3
|
-
module.exports = factory(require("react"), require("@codemirror/
|
|
3
|
+
module.exports = factory(require("react"), require("@codemirror/state"), require("@codemirror/theme-one-dark"), require("@codemirror/view"));
|
|
4
4
|
else if(typeof define === 'function' && define.amd)
|
|
5
|
-
define(["react", , ,
|
|
5
|
+
define(["react", , , ], factory);
|
|
6
6
|
else if(typeof exports === 'object')
|
|
7
|
-
exports["@uiw/codemirror"] = factory(require("react"), require("@codemirror/
|
|
7
|
+
exports["@uiw/codemirror"] = factory(require("react"), require("@codemirror/state"), require("@codemirror/theme-one-dark"), require("@codemirror/view"));
|
|
8
8
|
else
|
|
9
|
-
root["@uiw/codemirror"] = factory(root["React"], root["CM"]["@codemirror/
|
|
10
|
-
})(self, (__WEBPACK_EXTERNAL_MODULE__787__,
|
|
9
|
+
root["@uiw/codemirror"] = factory(root["React"], root["CM"]["@codemirror/state"], root["CM"]["@codemirror/theme-one-dark"], root["CM"]["@codemirror/view"]);
|
|
10
|
+
})(self, (__WEBPACK_EXTERNAL_MODULE__787__, __WEBPACK_EXTERNAL_MODULE__242__, __WEBPACK_EXTERNAL_MODULE__362__, __WEBPACK_EXTERNAL_MODULE__105__) => {
|
|
11
11
|
return /******/ (() => { // webpackBootstrap
|
|
12
12
|
/******/ "use strict";
|
|
13
13
|
/******/ var __webpack_modules__ = ({
|
|
14
14
|
|
|
15
|
-
/***/
|
|
16
|
-
/***/ ((__unused_webpack_module,
|
|
15
|
+
/***/ 638:
|
|
16
|
+
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
17
|
+
|
|
18
|
+
var __webpack_unused_export__;
|
|
19
|
+
/**
|
|
20
|
+
* @license React
|
|
21
|
+
* react-jsx-runtime.production.min.js
|
|
22
|
+
*
|
|
23
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
24
|
+
*
|
|
25
|
+
* This source code is licensed under the MIT license found in the
|
|
26
|
+
* LICENSE file in the root directory of this source tree.
|
|
27
|
+
*/
|
|
28
|
+
var f=__webpack_require__(787),k=Symbol.for("react.element"),l=Symbol.for("react.fragment"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};
|
|
29
|
+
function q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=""+g);void 0!==a.key&&(e=""+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}__webpack_unused_export__=l;exports.jsx=q;__webpack_unused_export__=q;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
/***/ }),
|
|
33
|
+
|
|
34
|
+
/***/ 724:
|
|
35
|
+
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if (true) {
|
|
40
|
+
module.exports = __webpack_require__(638);
|
|
41
|
+
} else {}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/***/ }),
|
|
45
|
+
|
|
46
|
+
/***/ 787:
|
|
47
|
+
/***/ ((module) => {
|
|
48
|
+
|
|
49
|
+
module.exports = __WEBPACK_EXTERNAL_MODULE__787__;
|
|
50
|
+
|
|
51
|
+
/***/ }),
|
|
52
|
+
|
|
53
|
+
/***/ 242:
|
|
54
|
+
/***/ ((module) => {
|
|
55
|
+
|
|
56
|
+
module.exports = __WEBPACK_EXTERNAL_MODULE__242__;
|
|
57
|
+
|
|
58
|
+
/***/ }),
|
|
59
|
+
|
|
60
|
+
/***/ 362:
|
|
61
|
+
/***/ ((module) => {
|
|
62
|
+
|
|
63
|
+
module.exports = __WEBPACK_EXTERNAL_MODULE__362__;
|
|
64
|
+
|
|
65
|
+
/***/ }),
|
|
66
|
+
|
|
67
|
+
/***/ 105:
|
|
68
|
+
/***/ ((module) => {
|
|
69
|
+
|
|
70
|
+
module.exports = __WEBPACK_EXTERNAL_MODULE__105__;
|
|
17
71
|
|
|
72
|
+
/***/ })
|
|
73
|
+
|
|
74
|
+
/******/ });
|
|
75
|
+
/************************************************************************/
|
|
76
|
+
/******/ // The module cache
|
|
77
|
+
/******/ var __webpack_module_cache__ = {};
|
|
78
|
+
/******/
|
|
79
|
+
/******/ // The require function
|
|
80
|
+
/******/ function __webpack_require__(moduleId) {
|
|
81
|
+
/******/ // Check if module is in cache
|
|
82
|
+
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
83
|
+
/******/ if (cachedModule !== undefined) {
|
|
84
|
+
/******/ return cachedModule.exports;
|
|
85
|
+
/******/ }
|
|
86
|
+
/******/ // Create a new module (and put it into the cache)
|
|
87
|
+
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
88
|
+
/******/ // no module.id needed
|
|
89
|
+
/******/ // no module.loaded needed
|
|
90
|
+
/******/ exports: {}
|
|
91
|
+
/******/ };
|
|
92
|
+
/******/
|
|
93
|
+
/******/ // Execute the module function
|
|
94
|
+
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
95
|
+
/******/
|
|
96
|
+
/******/ // Return the exports of the module
|
|
97
|
+
/******/ return module.exports;
|
|
98
|
+
/******/ }
|
|
99
|
+
/******/
|
|
100
|
+
/************************************************************************/
|
|
101
|
+
/******/ /* webpack/runtime/compat get default export */
|
|
102
|
+
/******/ (() => {
|
|
103
|
+
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
104
|
+
/******/ __webpack_require__.n = (module) => {
|
|
105
|
+
/******/ var getter = module && module.__esModule ?
|
|
106
|
+
/******/ () => (module['default']) :
|
|
107
|
+
/******/ () => (module);
|
|
108
|
+
/******/ __webpack_require__.d(getter, { a: getter });
|
|
109
|
+
/******/ return getter;
|
|
110
|
+
/******/ };
|
|
111
|
+
/******/ })();
|
|
112
|
+
/******/
|
|
113
|
+
/******/ /* webpack/runtime/define property getters */
|
|
114
|
+
/******/ (() => {
|
|
115
|
+
/******/ // define getter functions for harmony exports
|
|
116
|
+
/******/ __webpack_require__.d = (exports, definition) => {
|
|
117
|
+
/******/ for(var key in definition) {
|
|
118
|
+
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
119
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
120
|
+
/******/ }
|
|
121
|
+
/******/ }
|
|
122
|
+
/******/ };
|
|
123
|
+
/******/ })();
|
|
124
|
+
/******/
|
|
125
|
+
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
126
|
+
/******/ (() => {
|
|
127
|
+
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
128
|
+
/******/ })();
|
|
129
|
+
/******/
|
|
130
|
+
/******/ /* webpack/runtime/make namespace object */
|
|
131
|
+
/******/ (() => {
|
|
132
|
+
/******/ // define __esModule on exports
|
|
133
|
+
/******/ __webpack_require__.r = (exports) => {
|
|
134
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
135
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
136
|
+
/******/ }
|
|
137
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
138
|
+
/******/ };
|
|
139
|
+
/******/ })();
|
|
140
|
+
/******/
|
|
141
|
+
/************************************************************************/
|
|
142
|
+
var __webpack_exports__ = {};
|
|
143
|
+
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
|
144
|
+
(() => {
|
|
145
|
+
// ESM COMPAT FLAG
|
|
146
|
+
__webpack_require__.r(__webpack_exports__);
|
|
18
147
|
|
|
19
148
|
// EXPORTS
|
|
20
149
|
__webpack_require__.d(__webpack_exports__, {
|
|
21
|
-
"
|
|
150
|
+
"default": () => (/* binding */ src),
|
|
151
|
+
"useCodeMirror": () => (/* reexport */ useCodeMirror)
|
|
22
152
|
});
|
|
23
153
|
|
|
154
|
+
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/defineProperty.js
|
|
155
|
+
function _defineProperty(obj, key, value) {
|
|
156
|
+
if (key in obj) {
|
|
157
|
+
Object.defineProperty(obj, key, {
|
|
158
|
+
value: value,
|
|
159
|
+
enumerable: true,
|
|
160
|
+
configurable: true,
|
|
161
|
+
writable: true
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
obj[key] = value;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return obj;
|
|
168
|
+
}
|
|
169
|
+
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/objectSpread2.js
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
function ownKeys(object, enumerableOnly) {
|
|
173
|
+
var keys = Object.keys(object);
|
|
174
|
+
|
|
175
|
+
if (Object.getOwnPropertySymbols) {
|
|
176
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
177
|
+
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
|
178
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
179
|
+
})), keys.push.apply(keys, symbols);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return keys;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function _objectSpread2(target) {
|
|
186
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
187
|
+
var source = null != arguments[i] ? arguments[i] : {};
|
|
188
|
+
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
|
|
189
|
+
_defineProperty(target, key, source[key]);
|
|
190
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
|
|
191
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return target;
|
|
196
|
+
}
|
|
197
|
+
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js
|
|
198
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
199
|
+
if (source == null) return {};
|
|
200
|
+
var target = {};
|
|
201
|
+
var sourceKeys = Object.keys(source);
|
|
202
|
+
var key, i;
|
|
203
|
+
|
|
204
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
|
205
|
+
key = sourceKeys[i];
|
|
206
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
207
|
+
target[key] = source[key];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return target;
|
|
211
|
+
}
|
|
212
|
+
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js
|
|
213
|
+
|
|
214
|
+
function _objectWithoutProperties(source, excluded) {
|
|
215
|
+
if (source == null) return {};
|
|
216
|
+
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
217
|
+
var key, i;
|
|
218
|
+
|
|
219
|
+
if (Object.getOwnPropertySymbols) {
|
|
220
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
221
|
+
|
|
222
|
+
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
223
|
+
key = sourceSymbolKeys[i];
|
|
224
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
225
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
226
|
+
target[key] = source[key];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return target;
|
|
231
|
+
}
|
|
232
|
+
// EXTERNAL MODULE: external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react"}
|
|
233
|
+
var external_root_React_commonjs2_react_commonjs_react_amd_react_ = __webpack_require__(787);
|
|
234
|
+
var external_root_React_commonjs2_react_commonjs_react_amd_react_default = /*#__PURE__*/__webpack_require__.n(external_root_React_commonjs2_react_commonjs_react_amd_react_);
|
|
24
235
|
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js
|
|
25
236
|
function _arrayWithHoles(arr) {
|
|
26
237
|
if (Array.isArray(arr)) return arr;
|
|
@@ -87,18 +298,14 @@ function _nonIterableRest() {
|
|
|
87
298
|
function _slicedToArray(arr, i) {
|
|
88
299
|
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
|
89
300
|
}
|
|
90
|
-
// EXTERNAL MODULE: external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react"}
|
|
91
|
-
var external_root_React_commonjs2_react_commonjs_react_amd_react_ = __webpack_require__(787);
|
|
92
|
-
// EXTERNAL MODULE: external {"root":["CM","@codemirror/basic-setup"],"commonjs":"@codemirror/basic-setup","commonjs2":"@codemirror/basic-setup"}
|
|
93
|
-
var basic_setup_ = __webpack_require__(573);
|
|
94
|
-
// EXTERNAL MODULE: external {"root":["CM","@codemirror/state"],"commonjs":"@codemirror/state","commonjs2":"@codemirror/state"}
|
|
95
|
-
var state_ = __webpack_require__(242);
|
|
96
301
|
// EXTERNAL MODULE: external {"root":["CM","@codemirror/view"],"commonjs":"@codemirror/view","commonjs2":"@codemirror/view"}
|
|
97
302
|
var view_ = __webpack_require__(105);
|
|
303
|
+
// EXTERNAL MODULE: external {"root":["CM","@codemirror/state"],"commonjs":"@codemirror/state","commonjs2":"@codemirror/state"}
|
|
304
|
+
var state_ = __webpack_require__(242);
|
|
98
305
|
;// CONCATENATED MODULE: ./node_modules/@lezer/common/dist/index.js
|
|
99
306
|
// FIXME profile adding a per-Tree TreeNode cache, validating it by
|
|
100
307
|
// parent pointer
|
|
101
|
-
/// The default maximum length of a `TreeBuffer` node
|
|
308
|
+
/// The default maximum length of a `TreeBuffer` node.
|
|
102
309
|
const DefaultBufferLength = 1024;
|
|
103
310
|
let nextPropID = 0;
|
|
104
311
|
class Range {
|
|
@@ -161,7 +368,7 @@ dist_NodeProp.contextHash = new dist_NodeProp({ perNode: true });
|
|
|
161
368
|
dist_NodeProp.lookAhead = new dist_NodeProp({ perNode: true });
|
|
162
369
|
/// This per-node prop is used to replace a given node, or part of a
|
|
163
370
|
/// node, with another tree. This is useful to include trees from
|
|
164
|
-
/// different languages.
|
|
371
|
+
/// different languages in mixed-language parsers.
|
|
165
372
|
dist_NodeProp.mounted = new dist_NodeProp({ perNode: true });
|
|
166
373
|
/// A mounted tree, which can be [stored](#common.NodeProp^mounted) on
|
|
167
374
|
/// a tree node to indicate that parts of its content are
|
|
@@ -207,6 +414,7 @@ class dist_NodeType {
|
|
|
207
414
|
this.id = id;
|
|
208
415
|
this.flags = flags;
|
|
209
416
|
}
|
|
417
|
+
/// Define a node type.
|
|
210
418
|
static define(spec) {
|
|
211
419
|
let props = spec.props && spec.props.length ? Object.create(null) : noProps;
|
|
212
420
|
let flags = (spec.top ? 1 /* Top */ : 0) | (spec.skipped ? 2 /* Skipped */ : 0) |
|
|
@@ -288,7 +496,7 @@ class NodeSet {
|
|
|
288
496
|
throw new RangeError("Node type ids should correspond to array positions when creating a node set");
|
|
289
497
|
}
|
|
290
498
|
/// Create a copy of this set with some node properties added. The
|
|
291
|
-
/// arguments to this method
|
|
499
|
+
/// arguments to this method can be created with
|
|
292
500
|
/// [`NodeProp.add`](#common.NodeProp.add).
|
|
293
501
|
extend(...props) {
|
|
294
502
|
let newTypes = [];
|
|
@@ -498,7 +706,7 @@ class FlatBufferCursor {
|
|
|
498
706
|
/// Tree buffers contain (type, start, end, endIndex) quads for each
|
|
499
707
|
/// node. In such a buffer, nodes are stored in prefix order (parents
|
|
500
708
|
/// before children, with the endIndex of the parent indicating which
|
|
501
|
-
/// children belong to it)
|
|
709
|
+
/// children belong to it).
|
|
502
710
|
class TreeBuffer {
|
|
503
711
|
/// Create a tree buffer.
|
|
504
712
|
constructor(
|
|
@@ -1402,7 +1610,10 @@ class NodeWeakMap {
|
|
|
1402
1610
|
/// [`applyChanges`](#common.TreeFragment^applyChanges) method to
|
|
1403
1611
|
/// update fragments for document changes.
|
|
1404
1612
|
class TreeFragment {
|
|
1405
|
-
/// Construct a tree fragment.
|
|
1613
|
+
/// Construct a tree fragment. You'll usually want to use
|
|
1614
|
+
/// [`addTree`](#common.TreeFragment^addTree) and
|
|
1615
|
+
/// [`applyChanges`](#common.TreeFragment^applyChanges) instead of
|
|
1616
|
+
/// calling this directly.
|
|
1406
1617
|
constructor(
|
|
1407
1618
|
/// The start of the unchanged range pointed to by this fragment.
|
|
1408
1619
|
/// This refers to an offset in the _updated_ document (as opposed
|
|
@@ -1517,11 +1728,6 @@ class StringInput {
|
|
|
1517
1728
|
/// function, runs the resulting [inner parses](#common.NestedParse),
|
|
1518
1729
|
/// and then [mounts](#common.NodeProp^mounted) their results onto the
|
|
1519
1730
|
/// tree.
|
|
1520
|
-
///
|
|
1521
|
-
/// The nesting function is passed a cursor to provide context for a
|
|
1522
|
-
/// node, but _should not_ move that cursor, only inspect its
|
|
1523
|
-
/// properties and optionally access its
|
|
1524
|
-
/// [node object](#common.TreeCursor.node).
|
|
1525
1731
|
function parseMixed(nest) {
|
|
1526
1732
|
return (parse, input, fragments, ranges) => new MixedParse(parse, nest, input, fragments, ranges);
|
|
1527
1733
|
}
|
|
@@ -2494,7 +2700,8 @@ const tags = {
|
|
|
2494
2700
|
/// * [`emphasis`](#highlight.tags.emphasis)
|
|
2495
2701
|
/// * [`strong`](#highlight.tags.strong)
|
|
2496
2702
|
/// * [`keyword`](#highlight.tags.keyword)
|
|
2497
|
-
/// * [`atom`](#highlight.tags.atom)
|
|
2703
|
+
/// * [`atom`](#highlight.tags.atom)
|
|
2704
|
+
/// * [`bool`](#highlight.tags.bool)
|
|
2498
2705
|
/// * [`url`](#highlight.tags.url)
|
|
2499
2706
|
/// * [`labelName`](#highlight.tags.labelName)
|
|
2500
2707
|
/// * [`inserted`](#highlight.tags.inserted)
|
|
@@ -2970,9 +3177,6 @@ let currentContext = null;
|
|
|
2970
3177
|
A parse context provided to parsers working on the editor content.
|
|
2971
3178
|
*/
|
|
2972
3179
|
class ParseContext {
|
|
2973
|
-
/**
|
|
2974
|
-
@internal
|
|
2975
|
-
*/
|
|
2976
3180
|
constructor(parser,
|
|
2977
3181
|
/**
|
|
2978
3182
|
The current editor state.
|
|
@@ -3023,6 +3227,12 @@ class ParseContext {
|
|
|
3023
3227
|
*/
|
|
3024
3228
|
this.tempSkipped = [];
|
|
3025
3229
|
}
|
|
3230
|
+
/**
|
|
3231
|
+
@internal
|
|
3232
|
+
*/
|
|
3233
|
+
static create(parser, state, viewport) {
|
|
3234
|
+
return new ParseContext(parser, state, [], dist_Tree.empty, 0, viewport, [], null);
|
|
3235
|
+
}
|
|
3026
3236
|
startParse() {
|
|
3027
3237
|
return this.parser.startParse(new DocInput(this.state.doc), this.fragments);
|
|
3028
3238
|
}
|
|
@@ -3228,7 +3438,7 @@ class LanguageState {
|
|
|
3228
3438
|
}
|
|
3229
3439
|
static init(state) {
|
|
3230
3440
|
let vpTo = Math.min(3000 /* InitViewport */, state.doc.length);
|
|
3231
|
-
let parseState =
|
|
3441
|
+
let parseState = ParseContext.create(state.facet(language).parser, state, { from: 0, to: vpTo });
|
|
3232
3442
|
if (!parseState.work(20 /* Apply */, vpTo))
|
|
3233
3443
|
parseState.takeTree();
|
|
3234
3444
|
return new LanguageState(parseState);
|
|
@@ -3472,13 +3682,13 @@ Facet that defines a way to provide a function that computes the
|
|
|
3472
3682
|
appropriate indentation depth at the start of a given line, or
|
|
3473
3683
|
`null` to indicate no appropriate indentation could be determined.
|
|
3474
3684
|
*/
|
|
3475
|
-
const indentService = /*@__PURE__*/
|
|
3685
|
+
const indentService = /*@__PURE__*/state_.Facet.define();
|
|
3476
3686
|
/**
|
|
3477
3687
|
Facet for overriding the unit by which indentation happens.
|
|
3478
3688
|
Should be a string consisting either entirely of spaces or
|
|
3479
3689
|
entirely of tabs. When not set, this defaults to 2 spaces.
|
|
3480
3690
|
*/
|
|
3481
|
-
const
|
|
3691
|
+
const dist_indentUnit = /*@__PURE__*/state_.Facet.define({
|
|
3482
3692
|
combine: values => {
|
|
3483
3693
|
if (!values.length)
|
|
3484
3694
|
return " ";
|
|
@@ -3494,7 +3704,7 @@ facet, and [`tabSize`](https://codemirror.net/6/docs/ref/#state.EditorState^tabS
|
|
|
3494
3704
|
contains tabs.
|
|
3495
3705
|
*/
|
|
3496
3706
|
function getIndentUnit(state) {
|
|
3497
|
-
let unit = state.facet(
|
|
3707
|
+
let unit = state.facet(dist_indentUnit);
|
|
3498
3708
|
return unit.charCodeAt(0) == 9 ? state.tabSize * unit.length : unit.length;
|
|
3499
3709
|
}
|
|
3500
3710
|
/**
|
|
@@ -3503,9 +3713,9 @@ Will use tabs for as much of the columns as possible when the
|
|
|
3503
3713
|
[`indentUnit`](https://codemirror.net/6/docs/ref/#language.indentUnit) facet contains
|
|
3504
3714
|
tabs.
|
|
3505
3715
|
*/
|
|
3506
|
-
function
|
|
3716
|
+
function indentString(state, cols) {
|
|
3507
3717
|
let result = "", ts = state.tabSize;
|
|
3508
|
-
if (state.facet(
|
|
3718
|
+
if (state.facet(dist_indentUnit).charCodeAt(0) == 9)
|
|
3509
3719
|
while (cols >= ts) {
|
|
3510
3720
|
result += "\t";
|
|
3511
3721
|
cols -= ts;
|
|
@@ -3522,9 +3732,9 @@ syntax tree for the [indent node prop](https://codemirror.net/6/docs/ref/#langua
|
|
|
3522
3732
|
and use that if found. Returns a number when an indentation could
|
|
3523
3733
|
be determined, and null otherwise.
|
|
3524
3734
|
*/
|
|
3525
|
-
function
|
|
3526
|
-
if (context instanceof EditorState)
|
|
3527
|
-
context = new
|
|
3735
|
+
function getIndentation(context, pos) {
|
|
3736
|
+
if (context instanceof state_.EditorState)
|
|
3737
|
+
context = new IndentContext(context);
|
|
3528
3738
|
for (let service of context.state.facet(indentService)) {
|
|
3529
3739
|
let result = service(context, pos);
|
|
3530
3740
|
if (result != null)
|
|
@@ -3539,7 +3749,7 @@ services](https://codemirror.net/6/docs/ref/#language.indentService). They provi
|
|
|
3539
3749
|
useful in indentation logic, and can selectively override the
|
|
3540
3750
|
indentation reported for some lines.
|
|
3541
3751
|
*/
|
|
3542
|
-
class
|
|
3752
|
+
class IndentContext {
|
|
3543
3753
|
/**
|
|
3544
3754
|
Create an indent context.
|
|
3545
3755
|
*/
|
|
@@ -3603,7 +3813,7 @@ class dist_IndentContext {
|
|
|
3603
3813
|
position in the given string.
|
|
3604
3814
|
*/
|
|
3605
3815
|
countColumn(line, pos = line.length) {
|
|
3606
|
-
return countColumn(line, this.state.tabSize, pos);
|
|
3816
|
+
return (0,state_.countColumn)(line, this.state.tabSize, pos);
|
|
3607
3817
|
}
|
|
3608
3818
|
/**
|
|
3609
3819
|
Find the indentation column of the line at the given point.
|
|
@@ -3646,7 +3856,7 @@ function indentStrategy(tree) {
|
|
|
3646
3856
|
if (strategy)
|
|
3647
3857
|
return strategy;
|
|
3648
3858
|
let first = tree.firstChild, close;
|
|
3649
|
-
if (first && (close = first.type.prop(
|
|
3859
|
+
if (first && (close = first.type.prop(dist_NodeProp.closedBy))) {
|
|
3650
3860
|
let last = tree.lastChild, closed = last && close.indexOf(last.name) > -1;
|
|
3651
3861
|
return cx => delimitedStrategy(cx, true, 1, undefined, closed && !ignoreClosed(cx) ? last.from : undefined);
|
|
3652
3862
|
}
|
|
@@ -3656,7 +3866,7 @@ function indentFrom(node, pos, base) {
|
|
|
3656
3866
|
for (; node; node = node.parent) {
|
|
3657
3867
|
let strategy = indentStrategy(node);
|
|
3658
3868
|
if (strategy)
|
|
3659
|
-
return strategy(
|
|
3869
|
+
return strategy(TreeIndentContext.create(base, pos, node));
|
|
3660
3870
|
}
|
|
3661
3871
|
return null;
|
|
3662
3872
|
}
|
|
@@ -3665,10 +3875,7 @@ function topIndent() { return 0; }
|
|
|
3665
3875
|
Objects of this type provide context information and helper
|
|
3666
3876
|
methods to indentation functions registered on syntax nodes.
|
|
3667
3877
|
*/
|
|
3668
|
-
class TreeIndentContext extends
|
|
3669
|
-
/**
|
|
3670
|
-
@internal
|
|
3671
|
-
*/
|
|
3878
|
+
class TreeIndentContext extends IndentContext {
|
|
3672
3879
|
constructor(base,
|
|
3673
3880
|
/**
|
|
3674
3881
|
The position at which indentation is being computed.
|
|
@@ -3685,6 +3892,12 @@ class TreeIndentContext extends (/* unused pure expression or super */ null && (
|
|
|
3685
3892
|
this.node = node;
|
|
3686
3893
|
}
|
|
3687
3894
|
/**
|
|
3895
|
+
@internal
|
|
3896
|
+
*/
|
|
3897
|
+
static create(base, pos, node) {
|
|
3898
|
+
return new TreeIndentContext(base, pos, node);
|
|
3899
|
+
}
|
|
3900
|
+
/**
|
|
3688
3901
|
Get the text directly after `this.pos`, either the entire line
|
|
3689
3902
|
or the next 100 characters, whichever is shorter.
|
|
3690
3903
|
*/
|
|
@@ -3802,7 +4015,7 @@ For example, `/^\s*\}$/` will reindent when a closing brace is
|
|
|
3802
4015
|
added at the start of a line.
|
|
3803
4016
|
*/
|
|
3804
4017
|
function indentOnInput() {
|
|
3805
|
-
return EditorState.transactionFilter.of(tr => {
|
|
4018
|
+
return state_.EditorState.transactionFilter.of(tr => {
|
|
3806
4019
|
if (!tr.docChanged || !tr.isUserEvent("input.type") && !tr.isUserEvent("input.complete"))
|
|
3807
4020
|
return tr;
|
|
3808
4021
|
let rules = tr.startState.languageDataAt("indentOnInput", tr.startState.selection.main.head);
|
|
@@ -3820,11 +4033,11 @@ function indentOnInput() {
|
|
|
3820
4033
|
if (line.from == last)
|
|
3821
4034
|
continue;
|
|
3822
4035
|
last = line.from;
|
|
3823
|
-
let indent =
|
|
4036
|
+
let indent = getIndentation(state, line.from);
|
|
3824
4037
|
if (indent == null)
|
|
3825
4038
|
continue;
|
|
3826
4039
|
let cur = /^\s*/.exec(line.text)[0];
|
|
3827
|
-
let norm =
|
|
4040
|
+
let norm = indentString(state, indent);
|
|
3828
4041
|
if (cur != norm)
|
|
3829
4042
|
changes.push({ from: line.from, to: line.from + cur.length, insert: norm });
|
|
3830
4043
|
}
|
|
@@ -4096,8 +4309,9 @@ const foldGutterDefaults = {
|
|
|
4096
4309
|
closedText: "›",
|
|
4097
4310
|
markerDOM: null,
|
|
4098
4311
|
domEventHandlers: {},
|
|
4312
|
+
foldingChanged: () => false
|
|
4099
4313
|
};
|
|
4100
|
-
class FoldMarker extends
|
|
4314
|
+
class FoldMarker extends view_.GutterMarker {
|
|
4101
4315
|
constructor(config, open) {
|
|
4102
4316
|
super();
|
|
4103
4317
|
this.config = config;
|
|
@@ -4121,7 +4335,7 @@ to fold or unfold the line).
|
|
|
4121
4335
|
function foldGutter(config = {}) {
|
|
4122
4336
|
let fullConfig = Object.assign(Object.assign({}, foldGutterDefaults), config);
|
|
4123
4337
|
let canFold = new FoldMarker(fullConfig, true), canUnfold = new FoldMarker(fullConfig, false);
|
|
4124
|
-
let markers = ViewPlugin.fromClass(class {
|
|
4338
|
+
let markers = view_.ViewPlugin.fromClass(class {
|
|
4125
4339
|
constructor(view) {
|
|
4126
4340
|
this.from = view.viewport.from;
|
|
4127
4341
|
this.markers = this.buildMarkers(view);
|
|
@@ -4130,11 +4344,12 @@ function foldGutter(config = {}) {
|
|
|
4130
4344
|
if (update.docChanged || update.viewportChanged ||
|
|
4131
4345
|
update.startState.facet(language) != update.state.facet(language) ||
|
|
4132
4346
|
update.startState.field(foldState, false) != update.state.field(foldState, false) ||
|
|
4133
|
-
dist_syntaxTree(update.startState) != dist_syntaxTree(update.state)
|
|
4347
|
+
dist_syntaxTree(update.startState) != dist_syntaxTree(update.state) ||
|
|
4348
|
+
fullConfig.foldingChanged(update))
|
|
4134
4349
|
this.markers = this.buildMarkers(update.view);
|
|
4135
4350
|
}
|
|
4136
4351
|
buildMarkers(view) {
|
|
4137
|
-
let builder = new RangeSetBuilder();
|
|
4352
|
+
let builder = new state_.RangeSetBuilder();
|
|
4138
4353
|
for (let line of view.viewportLineBlocks) {
|
|
4139
4354
|
let mark = findFold(view.state, line.from, line.to) ? canUnfold
|
|
4140
4355
|
: foldable(view.state, line.from, line.to) ? canFold : null;
|
|
@@ -4147,9 +4362,9 @@ function foldGutter(config = {}) {
|
|
|
4147
4362
|
let { domEventHandlers } = fullConfig;
|
|
4148
4363
|
return [
|
|
4149
4364
|
markers,
|
|
4150
|
-
gutter({
|
|
4365
|
+
(0,view_.gutter)({
|
|
4151
4366
|
class: "cm-foldGutter",
|
|
4152
|
-
markers(view) { var _a; return ((_a = view.plugin(markers)) === null || _a === void 0 ? void 0 : _a.markers) || RangeSet.empty; },
|
|
4367
|
+
markers(view) { var _a; return ((_a = view.plugin(markers)) === null || _a === void 0 ? void 0 : _a.markers) || state_.RangeSet.empty; },
|
|
4153
4368
|
initialSpacer() {
|
|
4154
4369
|
return new FoldMarker(fullConfig, false);
|
|
4155
4370
|
},
|
|
@@ -4200,6 +4415,7 @@ class HighlightStyle {
|
|
|
4200
4415
|
(modSpec || (modSpec = Object.create(null)))["." + cls] = spec;
|
|
4201
4416
|
return cls;
|
|
4202
4417
|
}
|
|
4418
|
+
const all = typeof options.all == "string" ? options.all : options.all ? def(options.all) : undefined;
|
|
4203
4419
|
const scopeOpt = options.scope;
|
|
4204
4420
|
this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data
|
|
4205
4421
|
: scopeOpt ? (type) => type == scopeOpt : undefined;
|
|
@@ -4207,7 +4423,7 @@ class HighlightStyle {
|
|
|
4207
4423
|
tag: style.tag,
|
|
4208
4424
|
class: style.class || def(Object.assign({}, style, { tag: null }))
|
|
4209
4425
|
})), {
|
|
4210
|
-
all
|
|
4426
|
+
all,
|
|
4211
4427
|
}).style;
|
|
4212
4428
|
this.module = modSpec ? new StyleModule(modSpec) : null;
|
|
4213
4429
|
this.themeType = options.themeType;
|
|
@@ -4250,14 +4466,14 @@ function syntaxHighlighting(highlighter, options) {
|
|
|
4250
4466
|
let ext = [treeHighlighter], themeType;
|
|
4251
4467
|
if (highlighter instanceof HighlightStyle) {
|
|
4252
4468
|
if (highlighter.module)
|
|
4253
|
-
ext.push(EditorView.styleModule.of(highlighter.module));
|
|
4469
|
+
ext.push(view_.EditorView.styleModule.of(highlighter.module));
|
|
4254
4470
|
themeType = highlighter.themeType;
|
|
4255
4471
|
}
|
|
4256
4472
|
if (options === null || options === void 0 ? void 0 : options.fallback)
|
|
4257
4473
|
ext.push(fallbackHighlighter.of(highlighter));
|
|
4258
4474
|
else if (themeType)
|
|
4259
|
-
ext.push(highlighterFacet.computeN([EditorView.darkTheme], state => {
|
|
4260
|
-
return state.facet(EditorView.darkTheme) == (themeType == "dark") ? [highlighter] : [];
|
|
4475
|
+
ext.push(highlighterFacet.computeN([view_.EditorView.darkTheme], state => {
|
|
4476
|
+
return state.facet(view_.EditorView.darkTheme) == (themeType == "dark") ? [highlighter] : [];
|
|
4261
4477
|
}));
|
|
4262
4478
|
else
|
|
4263
4479
|
ext.push(highlighterFacet.of(highlighter));
|
|
@@ -4394,11 +4610,11 @@ const bracketMatchingState = /*@__PURE__*/state_.StateField.define({
|
|
|
4394
4610
|
for (let range of tr.state.selection.ranges) {
|
|
4395
4611
|
if (!range.empty)
|
|
4396
4612
|
continue;
|
|
4397
|
-
let match =
|
|
4398
|
-
|| (range.head > 0 &&
|
|
4613
|
+
let match = matchBrackets(tr.state, range.head, -1, config)
|
|
4614
|
+
|| (range.head > 0 && matchBrackets(tr.state, range.head - 1, 1, config))
|
|
4399
4615
|
|| (config.afterCursor &&
|
|
4400
|
-
(
|
|
4401
|
-
(range.head < tr.state.doc.length &&
|
|
4616
|
+
(matchBrackets(tr.state, range.head, 1, config) ||
|
|
4617
|
+
(range.head < tr.state.doc.length && matchBrackets(tr.state, range.head + 1, -1, config))));
|
|
4402
4618
|
if (match)
|
|
4403
4619
|
decorations = decorations.concat(config.renderMatch(match, tr.state));
|
|
4404
4620
|
}
|
|
@@ -4436,7 +4652,7 @@ direction `dir`. Only the `brackets` and `maxScanDistance`
|
|
|
4436
4652
|
properties are used from `config`, if given. Returns null if no
|
|
4437
4653
|
bracket was found at `pos`, or a match result otherwise.
|
|
4438
4654
|
*/
|
|
4439
|
-
function
|
|
4655
|
+
function matchBrackets(state, pos, dir, config = {}) {
|
|
4440
4656
|
let maxScanDistance = config.maxScanDistance || DefaultScanDist, brackets = config.brackets || DefaultBrackets;
|
|
4441
4657
|
let tree = dist_syntaxTree(state), node = tree.resolveInner(pos, dir);
|
|
4442
4658
|
for (let cur = node; cur; cur = cur.parent) {
|
|
@@ -4526,7 +4742,7 @@ which uses it to tokenize the content.
|
|
|
4526
4742
|
*/
|
|
4527
4743
|
class StringStream {
|
|
4528
4744
|
/**
|
|
4529
|
-
|
|
4745
|
+
Create a stream.
|
|
4530
4746
|
*/
|
|
4531
4747
|
constructor(
|
|
4532
4748
|
/**
|
|
@@ -5057,7 +5273,7 @@ The line comment syntax is taken from the
|
|
|
5057
5273
|
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
|
5058
5274
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
|
5059
5275
|
*/
|
|
5060
|
-
const toggleLineComment = /*@__PURE__*/
|
|
5276
|
+
const toggleLineComment = /*@__PURE__*/command(changeLineComment, 0 /* Toggle */);
|
|
5061
5277
|
/**
|
|
5062
5278
|
Comment the current selection using line comments.
|
|
5063
5279
|
*/
|
|
@@ -5072,7 +5288,7 @@ The block comment syntax is taken from the
|
|
|
5072
5288
|
[`commentTokens`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) [language
|
|
5073
5289
|
data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt).
|
|
5074
5290
|
*/
|
|
5075
|
-
const toggleBlockComment = /*@__PURE__*/
|
|
5291
|
+
const toggleBlockComment = /*@__PURE__*/command(changeBlockComment, 0 /* Toggle */);
|
|
5076
5292
|
/**
|
|
5077
5293
|
Comment the current selection using block comments.
|
|
5078
5294
|
*/
|
|
@@ -5085,7 +5301,7 @@ const blockUncomment = /*@__PURE__*/(/* unused pure expression or super */ null
|
|
|
5085
5301
|
Comment or uncomment the lines around the current selection using
|
|
5086
5302
|
block comments.
|
|
5087
5303
|
*/
|
|
5088
|
-
const toggleBlockCommentByLine = /*@__PURE__*/
|
|
5304
|
+
const toggleBlockCommentByLine = /*@__PURE__*/command((o, s) => changeBlockComment(o, s, selectedLineRanges(s)), 0 /* Toggle */);
|
|
5089
5305
|
function getConfig(state, pos = state.selection.main.head) {
|
|
5090
5306
|
let data = state.languageDataAt("commentTokens", pos);
|
|
5091
5307
|
return data.length ? data[0] : {};
|
|
@@ -5289,7 +5505,7 @@ function dist_history(config = {}) {
|
|
|
5289
5505
|
return [
|
|
5290
5506
|
historyField_,
|
|
5291
5507
|
historyConfig.of(config),
|
|
5292
|
-
EditorView.domEventHandlers({
|
|
5508
|
+
view_.EditorView.domEventHandlers({
|
|
5293
5509
|
beforeinput(e, view) {
|
|
5294
5510
|
let command = e.inputType == "historyUndo" ? undo : e.inputType == "historyRedo" ? redo : null;
|
|
5295
5511
|
if (!command)
|
|
@@ -5693,8 +5909,8 @@ function interestingNode(state, node, bracketProp) {
|
|
|
5693
5909
|
return len && (len > 2 || /[^\s,.;:]/.test(state.sliceDoc(node.from, node.to))) || node.firstChild;
|
|
5694
5910
|
}
|
|
5695
5911
|
function moveBySyntax(state, start, forward) {
|
|
5696
|
-
let pos =
|
|
5697
|
-
let bracketProp = forward ?
|
|
5912
|
+
let pos = dist_syntaxTree(state).resolveInner(start.head);
|
|
5913
|
+
let bracketProp = forward ? dist_NodeProp.closedBy : dist_NodeProp.openedBy;
|
|
5698
5914
|
// Scan forward through child nodes to see if there's an interesting
|
|
5699
5915
|
// node ahead.
|
|
5700
5916
|
for (let at = start.head;;) {
|
|
@@ -5711,7 +5927,7 @@ function moveBySyntax(state, start, forward) {
|
|
|
5711
5927
|
newPos = forward ? match.end.to : match.end.from;
|
|
5712
5928
|
else
|
|
5713
5929
|
newPos = forward ? pos.to : pos.from;
|
|
5714
|
-
return EditorSelection.cursor(newPos, forward ? -1 : 1);
|
|
5930
|
+
return state_.EditorSelection.cursor(newPos, forward ? -1 : 1);
|
|
5715
5931
|
}
|
|
5716
5932
|
/**
|
|
5717
5933
|
Move the cursor over the next syntactic element to the left.
|
|
@@ -5737,10 +5953,12 @@ const cursorLineUp = view => cursorByLine(view, false);
|
|
|
5737
5953
|
Move the selection one line down.
|
|
5738
5954
|
*/
|
|
5739
5955
|
const cursorLineDown = view => cursorByLine(view, true);
|
|
5956
|
+
function pageHeight(view) {
|
|
5957
|
+
return Math.max(view.defaultLineHeight, Math.min(view.dom.clientHeight, innerHeight) - 5);
|
|
5958
|
+
}
|
|
5740
5959
|
function cursorByPage(view, forward) {
|
|
5741
5960
|
let { state } = view, selection = updateSel(state.selection, range => {
|
|
5742
|
-
return range.empty ? view.moveVertically(range, forward,
|
|
5743
|
-
: rangeEnd(range, forward);
|
|
5961
|
+
return range.empty ? view.moveVertically(range, forward, pageHeight(view)) : rangeEnd(range, forward);
|
|
5744
5962
|
});
|
|
5745
5963
|
if (selection.eq(state.selection))
|
|
5746
5964
|
return false;
|
|
@@ -5768,7 +5986,7 @@ function moveByLineBoundary(view, start, forward) {
|
|
|
5768
5986
|
if (!forward && moved.head == line.from && line.length) {
|
|
5769
5987
|
let space = /^\s*/.exec(view.state.sliceDoc(line.from, Math.min(line.from + 100, line.to)))[0].length;
|
|
5770
5988
|
if (space && start.head != line.from + space)
|
|
5771
|
-
moved = EditorSelection.cursor(line.from + space);
|
|
5989
|
+
moved = state_.EditorSelection.cursor(line.from + space);
|
|
5772
5990
|
}
|
|
5773
5991
|
return moved;
|
|
5774
5992
|
}
|
|
@@ -5802,7 +6020,7 @@ function toMatchingBracket(state, dispatch, extend) {
|
|
|
5802
6020
|
return range;
|
|
5803
6021
|
found = true;
|
|
5804
6022
|
let head = matching.start.from == range.head ? matching.end.to : matching.end.from;
|
|
5805
|
-
return extend ? EditorSelection.range(range.anchor, head) : EditorSelection.cursor(head);
|
|
6023
|
+
return extend ? state_.EditorSelection.range(range.anchor, head) : state_.EditorSelection.cursor(head);
|
|
5806
6024
|
});
|
|
5807
6025
|
if (!found)
|
|
5808
6026
|
return false;
|
|
@@ -5900,7 +6118,7 @@ Move the selection head one line down.
|
|
|
5900
6118
|
*/
|
|
5901
6119
|
const selectLineDown = view => selectByLine(view, true);
|
|
5902
6120
|
function selectByPage(view, forward) {
|
|
5903
|
-
return extendSel(view, range => view.moveVertically(range, forward,
|
|
6121
|
+
return extendSel(view, range => view.moveVertically(range, forward, pageHeight(view)));
|
|
5904
6122
|
}
|
|
5905
6123
|
/**
|
|
5906
6124
|
Move the selection head one page up.
|
|
@@ -5965,8 +6183,8 @@ const selectAll = ({ state, dispatch }) => {
|
|
|
5965
6183
|
Expand the selection to cover entire lines.
|
|
5966
6184
|
*/
|
|
5967
6185
|
const selectLine = ({ state, dispatch }) => {
|
|
5968
|
-
let ranges = selectedLineBlocks(state).map(({ from, to }) => EditorSelection.range(from, Math.min(to + 1, state.doc.length)));
|
|
5969
|
-
dispatch(state.update({ selection: EditorSelection.create(ranges), userEvent: "select" }));
|
|
6186
|
+
let ranges = selectedLineBlocks(state).map(({ from, to }) => state_.EditorSelection.range(from, Math.min(to + 1, state.doc.length)));
|
|
6187
|
+
dispatch(state.update({ selection: state_.EditorSelection.create(ranges), userEvent: "select" }));
|
|
5970
6188
|
return true;
|
|
5971
6189
|
};
|
|
5972
6190
|
/**
|
|
@@ -5978,12 +6196,12 @@ syntax tree.
|
|
|
5978
6196
|
const selectParentSyntax = ({ state, dispatch }) => {
|
|
5979
6197
|
let selection = updateSel(state.selection, range => {
|
|
5980
6198
|
var _a;
|
|
5981
|
-
let context =
|
|
6199
|
+
let context = dist_syntaxTree(state).resolveInner(range.head, 1);
|
|
5982
6200
|
while (!((context.from < range.from && context.to >= range.to) ||
|
|
5983
6201
|
(context.to > range.to && context.from <= range.from) ||
|
|
5984
6202
|
!((_a = context.parent) === null || _a === void 0 ? void 0 : _a.parent)))
|
|
5985
6203
|
context = context.parent;
|
|
5986
|
-
return EditorSelection.range(context.to, context.from);
|
|
6204
|
+
return state_.EditorSelection.range(context.to, context.from);
|
|
5987
6205
|
});
|
|
5988
6206
|
dispatch(setSel(state, selection));
|
|
5989
6207
|
return true;
|
|
@@ -5996,9 +6214,9 @@ non-empty, convert it to a cursor selection.
|
|
|
5996
6214
|
const simplifySelection = ({ state, dispatch }) => {
|
|
5997
6215
|
let cur = state.selection, selection = null;
|
|
5998
6216
|
if (cur.ranges.length > 1)
|
|
5999
|
-
selection = EditorSelection.create([cur.main]);
|
|
6217
|
+
selection = state_.EditorSelection.create([cur.main]);
|
|
6000
6218
|
else if (!cur.main.empty)
|
|
6001
|
-
selection = EditorSelection.create([EditorSelection.cursor(cur.main.head)]);
|
|
6219
|
+
selection = state_.EditorSelection.create([state_.EditorSelection.cursor(cur.main.head)]);
|
|
6002
6220
|
if (!selection)
|
|
6003
6221
|
return false;
|
|
6004
6222
|
dispatch(setSel(state, selection));
|
|
@@ -6202,12 +6420,12 @@ function moveLine(state, dispatch, forward) {
|
|
|
6202
6420
|
if (forward) {
|
|
6203
6421
|
changes.push({ from: block.to, to: nextLine.to }, { from: block.from, insert: nextLine.text + state.lineBreak });
|
|
6204
6422
|
for (let r of block.ranges)
|
|
6205
|
-
ranges.push(EditorSelection.range(Math.min(state.doc.length, r.anchor + size), Math.min(state.doc.length, r.head + size)));
|
|
6423
|
+
ranges.push(state_.EditorSelection.range(Math.min(state.doc.length, r.anchor + size), Math.min(state.doc.length, r.head + size)));
|
|
6206
6424
|
}
|
|
6207
6425
|
else {
|
|
6208
6426
|
changes.push({ from: nextLine.from, to: block.from }, { from: block.to, insert: state.lineBreak + nextLine.text });
|
|
6209
6427
|
for (let r of block.ranges)
|
|
6210
|
-
ranges.push(EditorSelection.range(r.anchor - size, r.head - size));
|
|
6428
|
+
ranges.push(state_.EditorSelection.range(r.anchor - size, r.head - size));
|
|
6211
6429
|
}
|
|
6212
6430
|
}
|
|
6213
6431
|
if (!changes.length)
|
|
@@ -6215,7 +6433,7 @@ function moveLine(state, dispatch, forward) {
|
|
|
6215
6433
|
dispatch(state.update({
|
|
6216
6434
|
changes,
|
|
6217
6435
|
scrollIntoView: true,
|
|
6218
|
-
selection: EditorSelection.create(ranges, state.selection.mainIndex),
|
|
6436
|
+
selection: state_.EditorSelection.create(ranges, state.selection.mainIndex),
|
|
6219
6437
|
userEvent: "move.line"
|
|
6220
6438
|
}));
|
|
6221
6439
|
return true;
|
|
@@ -6276,10 +6494,10 @@ const insertNewline = ({ state, dispatch }) => {
|
|
|
6276
6494
|
function isBetweenBrackets(state, pos) {
|
|
6277
6495
|
if (/\(\)|\[\]|\{\}/.test(state.sliceDoc(pos - 1, pos + 1)))
|
|
6278
6496
|
return { from: pos, to: pos };
|
|
6279
|
-
let context =
|
|
6497
|
+
let context = dist_syntaxTree(state).resolveInner(pos);
|
|
6280
6498
|
let before = context.childBefore(pos), after = context.childAfter(pos), closedBy;
|
|
6281
6499
|
if (before && after && before.to <= pos && after.from >= pos &&
|
|
6282
|
-
(closedBy = before.type.prop(
|
|
6500
|
+
(closedBy = before.type.prop(dist_NodeProp.closedBy)) && closedBy.indexOf(after.name) > -1 &&
|
|
6283
6501
|
state.doc.lineAt(before.to).from == state.doc.lineAt(after.from).from)
|
|
6284
6502
|
return { from: before.to, to: after.from };
|
|
6285
6503
|
return null;
|
|
@@ -6291,11 +6509,11 @@ will also delete that whitespace. When the cursor is between
|
|
|
6291
6509
|
matching brackets, an additional newline will be inserted after
|
|
6292
6510
|
the cursor.
|
|
6293
6511
|
*/
|
|
6294
|
-
const insertNewlineAndIndent = /*@__PURE__*/
|
|
6512
|
+
const insertNewlineAndIndent = /*@__PURE__*/newlineAndIndent(false);
|
|
6295
6513
|
/**
|
|
6296
6514
|
Create a blank, indented line below the current line.
|
|
6297
6515
|
*/
|
|
6298
|
-
const insertBlankLine = /*@__PURE__*/
|
|
6516
|
+
const insertBlankLine = /*@__PURE__*/newlineAndIndent(true);
|
|
6299
6517
|
function newlineAndIndent(atEof) {
|
|
6300
6518
|
return ({ state, dispatch }) => {
|
|
6301
6519
|
if (state.readOnly)
|
|
@@ -6318,8 +6536,8 @@ function newlineAndIndent(atEof) {
|
|
|
6318
6536
|
let insert = ["", indentString(state, indent)];
|
|
6319
6537
|
if (explode)
|
|
6320
6538
|
insert.push(indentString(state, cx.lineIndent(line.from, -1)));
|
|
6321
|
-
return { changes: { from, to, insert: Text.of(insert) },
|
|
6322
|
-
range: EditorSelection.cursor(from + 1 + insert[1].length) };
|
|
6539
|
+
return { changes: { from, to, insert: state_.Text.of(insert) },
|
|
6540
|
+
range: state_.EditorSelection.cursor(from + 1 + insert[1].length) };
|
|
6323
6541
|
});
|
|
6324
6542
|
dispatch(state.update(changes, { scrollIntoView: true, userEvent: "input" }));
|
|
6325
6543
|
return true;
|
|
@@ -6380,7 +6598,7 @@ const indentMore = ({ state, dispatch }) => {
|
|
|
6380
6598
|
if (state.readOnly)
|
|
6381
6599
|
return false;
|
|
6382
6600
|
dispatch(state.update(changeBySelectedLine(state, (line, changes) => {
|
|
6383
|
-
changes.push({ from: line.from, insert: state.facet(
|
|
6601
|
+
changes.push({ from: line.from, insert: state.facet(dist_indentUnit) });
|
|
6384
6602
|
}), { userEvent: "input.indent" }));
|
|
6385
6603
|
return true;
|
|
6386
6604
|
};
|
|
@@ -6396,7 +6614,7 @@ const indentLess = ({ state, dispatch }) => {
|
|
|
6396
6614
|
if (!space)
|
|
6397
6615
|
return;
|
|
6398
6616
|
let col = (0,state_.countColumn)(space, state.tabSize), keep = 0;
|
|
6399
|
-
let insert =
|
|
6617
|
+
let insert = indentString(state, Math.max(0, col - getIndentUnit(state)));
|
|
6400
6618
|
while (keep < space.length && keep < insert.length && space.charCodeAt(keep) == insert.charCodeAt(keep))
|
|
6401
6619
|
keep++;
|
|
6402
6620
|
changes.push({ from: line.from + keep, to: line.from + space.length, insert: insert.slice(keep) });
|
|
@@ -6481,7 +6699,7 @@ property changed to `mac`.)
|
|
|
6481
6699
|
- Cmd-Backspace (macOS): [`deleteToLineStart`](https://codemirror.net/6/docs/ref/#commands.deleteToLineStart).
|
|
6482
6700
|
- Cmd-Delete (macOS): [`deleteToLineEnd`](https://codemirror.net/6/docs/ref/#commands.deleteToLineEnd).
|
|
6483
6701
|
*/
|
|
6484
|
-
const standardKeymap = /*@__PURE__*/
|
|
6702
|
+
const standardKeymap = /*@__PURE__*/[
|
|
6485
6703
|
{ key: "ArrowLeft", run: cursorCharLeft, shift: selectCharLeft, preventDefault: true },
|
|
6486
6704
|
{ key: "Mod-ArrowLeft", mac: "Alt-ArrowLeft", run: cursorGroupLeft, shift: selectGroupLeft },
|
|
6487
6705
|
{ mac: "Cmd-ArrowLeft", run: cursorLineBoundaryBackward, shift: selectLineBoundaryBackward },
|
|
@@ -6508,7 +6726,7 @@ const standardKeymap = /*@__PURE__*/(/* unused pure expression or super */ null
|
|
|
6508
6726
|
{ key: "Mod-Delete", mac: "Alt-Delete", run: deleteGroupForward },
|
|
6509
6727
|
{ mac: "Mod-Backspace", run: deleteToLineStart },
|
|
6510
6728
|
{ mac: "Mod-Delete", run: deleteToLineEnd }
|
|
6511
|
-
].concat(/*@__PURE__*/emacsStyleKeymap.map(b => ({ mac: b.key, run: b.run, shift: b.shift })))
|
|
6729
|
+
].concat(/*@__PURE__*/emacsStyleKeymap.map(b => ({ mac: b.key, run: b.run, shift: b.shift })));
|
|
6512
6730
|
/**
|
|
6513
6731
|
The default keymap. Includes all bindings from
|
|
6514
6732
|
[`standardKeymap`](https://codemirror.net/6/docs/ref/#commands.standardKeymap) plus the following:
|
|
@@ -6531,7 +6749,7 @@ The default keymap. Includes all bindings from
|
|
|
6531
6749
|
- Ctrl-/ (Cmd-/ on macOS): [`toggleComment`](https://codemirror.net/6/docs/ref/#commands.toggleComment).
|
|
6532
6750
|
- Shift-Alt-a: [`toggleBlockComment`](https://codemirror.net/6/docs/ref/#commands.toggleBlockComment).
|
|
6533
6751
|
*/
|
|
6534
|
-
const defaultKeymap = /*@__PURE__*/
|
|
6752
|
+
const defaultKeymap = /*@__PURE__*/[
|
|
6535
6753
|
{ key: "Alt-ArrowLeft", mac: "Ctrl-ArrowLeft", run: cursorSyntaxLeft, shift: selectSyntaxLeft },
|
|
6536
6754
|
{ key: "Alt-ArrowRight", mac: "Ctrl-ArrowRight", run: cursorSyntaxRight, shift: selectSyntaxRight },
|
|
6537
6755
|
{ key: "Alt-ArrowUp", run: moveLineUp },
|
|
@@ -6549,7 +6767,7 @@ const defaultKeymap = /*@__PURE__*/(/* unused pure expression or super */ null &
|
|
|
6549
6767
|
{ key: "Shift-Mod-\\", run: cursorMatchingBracket },
|
|
6550
6768
|
{ key: "Mod-/", run: toggleComment },
|
|
6551
6769
|
{ key: "Alt-A", run: toggleBlockComment }
|
|
6552
|
-
].concat(standardKeymap)
|
|
6770
|
+
].concat(standardKeymap);
|
|
6553
6771
|
/**
|
|
6554
6772
|
A binding that binds Tab to [`indentMore`](https://codemirror.net/6/docs/ref/#commands.indentMore) and
|
|
6555
6773
|
Shift-Tab to [`indentLess`](https://codemirror.net/6/docs/ref/#commands.indentLess).
|
|
@@ -6560,285 +6778,3752 @@ const indentWithTab = { key: "Tab", run: indentMore, shift: indentLess };
|
|
|
6560
6778
|
|
|
6561
6779
|
|
|
6562
6780
|
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6781
|
+
;// CONCATENATED MODULE: ./node_modules/crelt/index.es.js
|
|
6782
|
+
function crelt() {
|
|
6783
|
+
var elt = arguments[0]
|
|
6784
|
+
if (typeof elt == "string") elt = document.createElement(elt)
|
|
6785
|
+
var i = 1, next = arguments[1]
|
|
6786
|
+
if (next && typeof next == "object" && next.nodeType == null && !Array.isArray(next)) {
|
|
6787
|
+
for (var name in next) if (Object.prototype.hasOwnProperty.call(next, name)) {
|
|
6788
|
+
var value = next[name]
|
|
6789
|
+
if (typeof value == "string") elt.setAttribute(name, value)
|
|
6790
|
+
else if (value != null) elt[name] = value
|
|
6791
|
+
}
|
|
6792
|
+
i++
|
|
6793
|
+
}
|
|
6794
|
+
for (; i < arguments.length; i++) add(elt, arguments[i])
|
|
6795
|
+
return elt
|
|
6796
|
+
}
|
|
6571
6797
|
|
|
6572
|
-
|
|
6798
|
+
function add(elt, child) {
|
|
6799
|
+
if (typeof child == "string") {
|
|
6800
|
+
elt.appendChild(document.createTextNode(child))
|
|
6801
|
+
} else if (child == null) {
|
|
6802
|
+
} else if (child.nodeType != null) {
|
|
6803
|
+
elt.appendChild(child)
|
|
6804
|
+
} else if (Array.isArray(child)) {
|
|
6805
|
+
for (var i = 0; i < child.length; i++) add(elt, child[i])
|
|
6806
|
+
} else {
|
|
6807
|
+
throw new RangeError("Unsupported child node: " + child)
|
|
6808
|
+
}
|
|
6809
|
+
}
|
|
6573
6810
|
|
|
6574
|
-
|
|
6575
|
-
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
6811
|
+
;// CONCATENATED MODULE: ./node_modules/@codemirror/search/dist/index.js
|
|
6576
6812
|
|
|
6577
|
-
|
|
6813
|
+
|
|
6814
|
+
|
|
6815
|
+
|
|
6816
|
+
const basicNormalize = typeof String.prototype.normalize == "function"
|
|
6817
|
+
? x => x.normalize("NFKD") : x => x;
|
|
6578
6818
|
/**
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6819
|
+
A search cursor provides an iterator over text matches in a
|
|
6820
|
+
document.
|
|
6821
|
+
*/
|
|
6822
|
+
class SearchCursor {
|
|
6823
|
+
/**
|
|
6824
|
+
Create a text cursor. The query is the search string, `from` to
|
|
6825
|
+
`to` provides the region to search.
|
|
6826
|
+
|
|
6827
|
+
When `normalize` is given, it will be called, on both the query
|
|
6828
|
+
string and the content it is matched against, before comparing.
|
|
6829
|
+
You can, for example, create a case-insensitive search by
|
|
6830
|
+
passing `s => s.toLowerCase()`.
|
|
6831
|
+
|
|
6832
|
+
Text is always normalized with
|
|
6833
|
+
[`.normalize("NFKD")`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize)
|
|
6834
|
+
(when supported).
|
|
6835
|
+
*/
|
|
6836
|
+
constructor(text, query, from = 0, to = text.length, normalize) {
|
|
6837
|
+
/**
|
|
6838
|
+
The current match (only holds a meaningful value after
|
|
6839
|
+
[`next`](https://codemirror.net/6/docs/ref/#search.SearchCursor.next) has been called and when
|
|
6840
|
+
`done` is false).
|
|
6841
|
+
*/
|
|
6842
|
+
this.value = { from: 0, to: 0 };
|
|
6843
|
+
/**
|
|
6844
|
+
Whether the end of the iterated region has been reached.
|
|
6845
|
+
*/
|
|
6846
|
+
this.done = false;
|
|
6847
|
+
this.matches = [];
|
|
6848
|
+
this.buffer = "";
|
|
6849
|
+
this.bufferPos = 0;
|
|
6850
|
+
this.iter = text.iterRange(from, to);
|
|
6851
|
+
this.bufferStart = from;
|
|
6852
|
+
this.normalize = normalize ? x => normalize(basicNormalize(x)) : basicNormalize;
|
|
6853
|
+
this.query = this.normalize(query);
|
|
6854
|
+
}
|
|
6855
|
+
peek() {
|
|
6856
|
+
if (this.bufferPos == this.buffer.length) {
|
|
6857
|
+
this.bufferStart += this.buffer.length;
|
|
6858
|
+
this.iter.next();
|
|
6859
|
+
if (this.iter.done)
|
|
6860
|
+
return -1;
|
|
6861
|
+
this.bufferPos = 0;
|
|
6862
|
+
this.buffer = this.iter.value;
|
|
6863
|
+
}
|
|
6864
|
+
return (0,state_.codePointAt)(this.buffer, this.bufferPos);
|
|
6865
|
+
}
|
|
6866
|
+
/**
|
|
6867
|
+
Look for the next match. Updates the iterator's
|
|
6868
|
+
[`value`](https://codemirror.net/6/docs/ref/#search.SearchCursor.value) and
|
|
6869
|
+
[`done`](https://codemirror.net/6/docs/ref/#search.SearchCursor.done) properties. Should be called
|
|
6870
|
+
at least once before using the cursor.
|
|
6871
|
+
*/
|
|
6872
|
+
next() {
|
|
6873
|
+
while (this.matches.length)
|
|
6874
|
+
this.matches.pop();
|
|
6875
|
+
return this.nextOverlapping();
|
|
6876
|
+
}
|
|
6877
|
+
/**
|
|
6878
|
+
The `next` method will ignore matches that partially overlap a
|
|
6879
|
+
previous match. This method behaves like `next`, but includes
|
|
6880
|
+
such matches.
|
|
6881
|
+
*/
|
|
6882
|
+
nextOverlapping() {
|
|
6883
|
+
for (;;) {
|
|
6884
|
+
let next = this.peek();
|
|
6885
|
+
if (next < 0) {
|
|
6886
|
+
this.done = true;
|
|
6887
|
+
return this;
|
|
6888
|
+
}
|
|
6889
|
+
let str = (0,state_.fromCodePoint)(next), start = this.bufferStart + this.bufferPos;
|
|
6890
|
+
this.bufferPos += (0,state_.codePointSize)(next);
|
|
6891
|
+
let norm = this.normalize(str);
|
|
6892
|
+
for (let i = 0, pos = start;; i++) {
|
|
6893
|
+
let code = norm.charCodeAt(i);
|
|
6894
|
+
let match = this.match(code, pos);
|
|
6895
|
+
if (match) {
|
|
6896
|
+
this.value = match;
|
|
6897
|
+
return this;
|
|
6898
|
+
}
|
|
6899
|
+
if (i == norm.length - 1)
|
|
6900
|
+
break;
|
|
6901
|
+
if (pos == start && i < str.length && str.charCodeAt(i) == code)
|
|
6902
|
+
pos++;
|
|
6903
|
+
}
|
|
6904
|
+
}
|
|
6905
|
+
}
|
|
6906
|
+
match(code, pos) {
|
|
6907
|
+
let match = null;
|
|
6908
|
+
for (let i = 0; i < this.matches.length; i += 2) {
|
|
6909
|
+
let index = this.matches[i], keep = false;
|
|
6910
|
+
if (this.query.charCodeAt(index) == code) {
|
|
6911
|
+
if (index == this.query.length - 1) {
|
|
6912
|
+
match = { from: this.matches[i + 1], to: pos + 1 };
|
|
6913
|
+
}
|
|
6914
|
+
else {
|
|
6915
|
+
this.matches[i]++;
|
|
6916
|
+
keep = true;
|
|
6917
|
+
}
|
|
6918
|
+
}
|
|
6919
|
+
if (!keep) {
|
|
6920
|
+
this.matches.splice(i, 2);
|
|
6921
|
+
i -= 2;
|
|
6922
|
+
}
|
|
6923
|
+
}
|
|
6924
|
+
if (this.query.charCodeAt(0) == code) {
|
|
6925
|
+
if (this.query.length == 1)
|
|
6926
|
+
match = { from: pos, to: pos + 1 };
|
|
6927
|
+
else
|
|
6928
|
+
this.matches.push(1, pos);
|
|
6929
|
+
}
|
|
6930
|
+
return match;
|
|
6931
|
+
}
|
|
6932
|
+
}
|
|
6933
|
+
if (typeof Symbol != "undefined")
|
|
6934
|
+
SearchCursor.prototype[Symbol.iterator] = function () { return this; };
|
|
6589
6935
|
|
|
6936
|
+
const empty = { from: -1, to: -1, match: /*@__PURE__*//.*/.exec("") };
|
|
6937
|
+
const baseFlags = "gm" + (/x/.unicode == null ? "" : "u");
|
|
6938
|
+
/**
|
|
6939
|
+
This class is similar to [`SearchCursor`](https://codemirror.net/6/docs/ref/#search.SearchCursor)
|
|
6940
|
+
but searches for a regular expression pattern instead of a plain
|
|
6941
|
+
string.
|
|
6942
|
+
*/
|
|
6943
|
+
class RegExpCursor {
|
|
6944
|
+
/**
|
|
6945
|
+
Create a cursor that will search the given range in the given
|
|
6946
|
+
document. `query` should be the raw pattern (as you'd pass it to
|
|
6947
|
+
`new RegExp`).
|
|
6948
|
+
*/
|
|
6949
|
+
constructor(text, query, options, from = 0, to = text.length) {
|
|
6950
|
+
this.to = to;
|
|
6951
|
+
this.curLine = "";
|
|
6952
|
+
/**
|
|
6953
|
+
Set to `true` when the cursor has reached the end of the search
|
|
6954
|
+
range.
|
|
6955
|
+
*/
|
|
6956
|
+
this.done = false;
|
|
6957
|
+
/**
|
|
6958
|
+
Will contain an object with the extent of the match and the
|
|
6959
|
+
match object when [`next`](https://codemirror.net/6/docs/ref/#search.RegExpCursor.next)
|
|
6960
|
+
sucessfully finds a match.
|
|
6961
|
+
*/
|
|
6962
|
+
this.value = empty;
|
|
6963
|
+
if (/\\[sWDnr]|\n|\r|\[\^/.test(query))
|
|
6964
|
+
return new MultilineRegExpCursor(text, query, options, from, to);
|
|
6965
|
+
this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : ""));
|
|
6966
|
+
this.iter = text.iter();
|
|
6967
|
+
let startLine = text.lineAt(from);
|
|
6968
|
+
this.curLineStart = startLine.from;
|
|
6969
|
+
this.matchPos = from;
|
|
6970
|
+
this.getLine(this.curLineStart);
|
|
6971
|
+
}
|
|
6972
|
+
getLine(skip) {
|
|
6973
|
+
this.iter.next(skip);
|
|
6974
|
+
if (this.iter.lineBreak) {
|
|
6975
|
+
this.curLine = "";
|
|
6976
|
+
}
|
|
6977
|
+
else {
|
|
6978
|
+
this.curLine = this.iter.value;
|
|
6979
|
+
if (this.curLineStart + this.curLine.length > this.to)
|
|
6980
|
+
this.curLine = this.curLine.slice(0, this.to - this.curLineStart);
|
|
6981
|
+
this.iter.next();
|
|
6982
|
+
}
|
|
6983
|
+
}
|
|
6984
|
+
nextLine() {
|
|
6985
|
+
this.curLineStart = this.curLineStart + this.curLine.length + 1;
|
|
6986
|
+
if (this.curLineStart > this.to)
|
|
6987
|
+
this.curLine = "";
|
|
6988
|
+
else
|
|
6989
|
+
this.getLine(0);
|
|
6990
|
+
}
|
|
6991
|
+
/**
|
|
6992
|
+
Move to the next match, if there is one.
|
|
6993
|
+
*/
|
|
6994
|
+
next() {
|
|
6995
|
+
for (let off = this.matchPos - this.curLineStart;;) {
|
|
6996
|
+
this.re.lastIndex = off;
|
|
6997
|
+
let match = this.matchPos <= this.to && this.re.exec(this.curLine);
|
|
6998
|
+
if (match) {
|
|
6999
|
+
let from = this.curLineStart + match.index, to = from + match[0].length;
|
|
7000
|
+
this.matchPos = to + (from == to ? 1 : 0);
|
|
7001
|
+
if (from == this.curLine.length)
|
|
7002
|
+
this.nextLine();
|
|
7003
|
+
if (from < to || from > this.value.to) {
|
|
7004
|
+
this.value = { from, to, match };
|
|
7005
|
+
return this;
|
|
7006
|
+
}
|
|
7007
|
+
off = this.matchPos - this.curLineStart;
|
|
7008
|
+
}
|
|
7009
|
+
else if (this.curLineStart + this.curLine.length < this.to) {
|
|
7010
|
+
this.nextLine();
|
|
7011
|
+
off = 0;
|
|
7012
|
+
}
|
|
7013
|
+
else {
|
|
7014
|
+
this.done = true;
|
|
7015
|
+
return this;
|
|
7016
|
+
}
|
|
7017
|
+
}
|
|
7018
|
+
}
|
|
7019
|
+
}
|
|
7020
|
+
const flattened = /*@__PURE__*/new WeakMap();
|
|
7021
|
+
// Reusable (partially) flattened document strings
|
|
7022
|
+
class FlattenedDoc {
|
|
7023
|
+
constructor(from, text) {
|
|
7024
|
+
this.from = from;
|
|
7025
|
+
this.text = text;
|
|
7026
|
+
}
|
|
7027
|
+
get to() { return this.from + this.text.length; }
|
|
7028
|
+
static get(doc, from, to) {
|
|
7029
|
+
let cached = flattened.get(doc);
|
|
7030
|
+
if (!cached || cached.from >= to || cached.to <= from) {
|
|
7031
|
+
let flat = new FlattenedDoc(from, doc.sliceString(from, to));
|
|
7032
|
+
flattened.set(doc, flat);
|
|
7033
|
+
return flat;
|
|
7034
|
+
}
|
|
7035
|
+
if (cached.from == from && cached.to == to)
|
|
7036
|
+
return cached;
|
|
7037
|
+
let { text, from: cachedFrom } = cached;
|
|
7038
|
+
if (cachedFrom > from) {
|
|
7039
|
+
text = doc.sliceString(from, cachedFrom) + text;
|
|
7040
|
+
cachedFrom = from;
|
|
7041
|
+
}
|
|
7042
|
+
if (cached.to < to)
|
|
7043
|
+
text += doc.sliceString(cached.to, to);
|
|
7044
|
+
flattened.set(doc, new FlattenedDoc(cachedFrom, text));
|
|
7045
|
+
return new FlattenedDoc(from, text.slice(from - cachedFrom, to - cachedFrom));
|
|
7046
|
+
}
|
|
7047
|
+
}
|
|
7048
|
+
class MultilineRegExpCursor {
|
|
7049
|
+
constructor(text, query, options, from, to) {
|
|
7050
|
+
this.text = text;
|
|
7051
|
+
this.to = to;
|
|
7052
|
+
this.done = false;
|
|
7053
|
+
this.value = empty;
|
|
7054
|
+
this.matchPos = from;
|
|
7055
|
+
this.re = new RegExp(query, baseFlags + ((options === null || options === void 0 ? void 0 : options.ignoreCase) ? "i" : ""));
|
|
7056
|
+
this.flat = FlattenedDoc.get(text, from, this.chunkEnd(from + 5000 /* Base */));
|
|
7057
|
+
}
|
|
7058
|
+
chunkEnd(pos) {
|
|
7059
|
+
return pos >= this.to ? this.to : this.text.lineAt(pos).to;
|
|
7060
|
+
}
|
|
7061
|
+
next() {
|
|
7062
|
+
for (;;) {
|
|
7063
|
+
let off = this.re.lastIndex = this.matchPos - this.flat.from;
|
|
7064
|
+
let match = this.re.exec(this.flat.text);
|
|
7065
|
+
// Skip empty matches directly after the last match
|
|
7066
|
+
if (match && !match[0] && match.index == off) {
|
|
7067
|
+
this.re.lastIndex = off + 1;
|
|
7068
|
+
match = this.re.exec(this.flat.text);
|
|
7069
|
+
}
|
|
7070
|
+
// If a match goes almost to the end of a noncomplete chunk, try
|
|
7071
|
+
// again, since it'll likely be able to match more
|
|
7072
|
+
if (match && this.flat.to < this.to && match.index + match[0].length > this.flat.text.length - 10)
|
|
7073
|
+
match = null;
|
|
7074
|
+
if (match) {
|
|
7075
|
+
let from = this.flat.from + match.index, to = from + match[0].length;
|
|
7076
|
+
this.value = { from, to, match };
|
|
7077
|
+
this.matchPos = to + (from == to ? 1 : 0);
|
|
7078
|
+
return this;
|
|
7079
|
+
}
|
|
7080
|
+
else {
|
|
7081
|
+
if (this.flat.to == this.to) {
|
|
7082
|
+
this.done = true;
|
|
7083
|
+
return this;
|
|
7084
|
+
}
|
|
7085
|
+
// Grow the flattened doc
|
|
7086
|
+
this.flat = FlattenedDoc.get(this.text, this.flat.from, this.chunkEnd(this.flat.from + this.flat.text.length * 2));
|
|
7087
|
+
}
|
|
7088
|
+
}
|
|
7089
|
+
}
|
|
7090
|
+
}
|
|
7091
|
+
if (typeof Symbol != "undefined") {
|
|
7092
|
+
RegExpCursor.prototype[Symbol.iterator] = MultilineRegExpCursor.prototype[Symbol.iterator] =
|
|
7093
|
+
function () { return this; };
|
|
7094
|
+
}
|
|
7095
|
+
function validRegExp(source) {
|
|
7096
|
+
try {
|
|
7097
|
+
new RegExp(source, baseFlags);
|
|
7098
|
+
return true;
|
|
7099
|
+
}
|
|
7100
|
+
catch (_a) {
|
|
7101
|
+
return false;
|
|
7102
|
+
}
|
|
7103
|
+
}
|
|
6590
7104
|
|
|
6591
|
-
|
|
7105
|
+
function createLineDialog(view) {
|
|
7106
|
+
let input = crelt("input", { class: "cm-textfield", name: "line" });
|
|
7107
|
+
let dom = crelt("form", {
|
|
7108
|
+
class: "cm-gotoLine",
|
|
7109
|
+
onkeydown: (event) => {
|
|
7110
|
+
if (event.keyCode == 27) { // Escape
|
|
7111
|
+
event.preventDefault();
|
|
7112
|
+
view.dispatch({ effects: dialogEffect.of(false) });
|
|
7113
|
+
view.focus();
|
|
7114
|
+
}
|
|
7115
|
+
else if (event.keyCode == 13) { // Enter
|
|
7116
|
+
event.preventDefault();
|
|
7117
|
+
go();
|
|
7118
|
+
}
|
|
7119
|
+
},
|
|
7120
|
+
onsubmit: (event) => {
|
|
7121
|
+
event.preventDefault();
|
|
7122
|
+
go();
|
|
7123
|
+
}
|
|
7124
|
+
}, crelt("label", view.state.phrase("Go to line"), ": ", input), " ", crelt("button", { class: "cm-button", type: "submit" }, view.state.phrase("go")));
|
|
7125
|
+
function go() {
|
|
7126
|
+
let match = /^([+-])?(\d+)?(:\d+)?(%)?$/.exec(input.value);
|
|
7127
|
+
if (!match)
|
|
7128
|
+
return;
|
|
7129
|
+
let { state } = view, startLine = state.doc.lineAt(state.selection.main.head);
|
|
7130
|
+
let [, sign, ln, cl, percent] = match;
|
|
7131
|
+
let col = cl ? +cl.slice(1) : 0;
|
|
7132
|
+
let line = ln ? +ln : startLine.number;
|
|
7133
|
+
if (ln && percent) {
|
|
7134
|
+
let pc = line / 100;
|
|
7135
|
+
if (sign)
|
|
7136
|
+
pc = pc * (sign == "-" ? -1 : 1) + (startLine.number / state.doc.lines);
|
|
7137
|
+
line = Math.round(state.doc.lines * pc);
|
|
7138
|
+
}
|
|
7139
|
+
else if (ln && sign) {
|
|
7140
|
+
line = line * (sign == "-" ? -1 : 1) + startLine.number;
|
|
7141
|
+
}
|
|
7142
|
+
let docLine = state.doc.line(Math.max(1, Math.min(state.doc.lines, line)));
|
|
7143
|
+
view.dispatch({
|
|
7144
|
+
effects: dialogEffect.of(false),
|
|
7145
|
+
selection: state_.EditorSelection.cursor(docLine.from + Math.max(0, Math.min(col, docLine.length))),
|
|
7146
|
+
scrollIntoView: true
|
|
7147
|
+
});
|
|
7148
|
+
view.focus();
|
|
7149
|
+
}
|
|
7150
|
+
return { dom };
|
|
7151
|
+
}
|
|
7152
|
+
const dialogEffect = /*@__PURE__*/state_.StateEffect.define();
|
|
7153
|
+
const dialogField = /*@__PURE__*/state_.StateField.define({
|
|
7154
|
+
create() { return true; },
|
|
7155
|
+
update(value, tr) {
|
|
7156
|
+
for (let e of tr.effects)
|
|
7157
|
+
if (e.is(dialogEffect))
|
|
7158
|
+
value = e.value;
|
|
7159
|
+
return value;
|
|
7160
|
+
},
|
|
7161
|
+
provide: f => view_.showPanel.from(f, val => val ? createLineDialog : null)
|
|
7162
|
+
});
|
|
7163
|
+
/**
|
|
7164
|
+
Command that shows a dialog asking the user for a line number, and
|
|
7165
|
+
when a valid position is provided, moves the cursor to that line.
|
|
7166
|
+
|
|
7167
|
+
Supports line numbers, relative line offsets prefixed with `+` or
|
|
7168
|
+
`-`, document percentages suffixed with `%`, and an optional
|
|
7169
|
+
column position by adding `:` and a second number after the line
|
|
7170
|
+
number.
|
|
7171
|
+
|
|
7172
|
+
The dialog can be styled with the `panel.gotoLine` theme
|
|
7173
|
+
selector.
|
|
7174
|
+
*/
|
|
7175
|
+
const gotoLine = view => {
|
|
7176
|
+
let panel = (0,view_.getPanel)(view, createLineDialog);
|
|
7177
|
+
if (!panel) {
|
|
7178
|
+
let effects = [dialogEffect.of(true)];
|
|
7179
|
+
if (view.state.field(dialogField, false) == null)
|
|
7180
|
+
effects.push(state_.StateEffect.appendConfig.of([dialogField, dist_baseTheme$1]));
|
|
7181
|
+
view.dispatch({ effects });
|
|
7182
|
+
panel = (0,view_.getPanel)(view, createLineDialog);
|
|
7183
|
+
}
|
|
7184
|
+
if (panel)
|
|
7185
|
+
panel.dom.querySelector("input").focus();
|
|
7186
|
+
return true;
|
|
7187
|
+
};
|
|
7188
|
+
const dist_baseTheme$1 = /*@__PURE__*/view_.EditorView.baseTheme({
|
|
7189
|
+
".cm-panel.cm-gotoLine": {
|
|
7190
|
+
padding: "2px 6px 4px",
|
|
7191
|
+
"& label": { fontSize: "80%" }
|
|
7192
|
+
}
|
|
7193
|
+
});
|
|
7194
|
+
|
|
7195
|
+
const defaultHighlightOptions = {
|
|
7196
|
+
highlightWordAroundCursor: false,
|
|
7197
|
+
minSelectionLength: 1,
|
|
7198
|
+
maxMatches: 100,
|
|
7199
|
+
wholeWords: false
|
|
7200
|
+
};
|
|
7201
|
+
const highlightConfig = /*@__PURE__*/state_.Facet.define({
|
|
7202
|
+
combine(options) {
|
|
7203
|
+
return (0,state_.combineConfig)(options, defaultHighlightOptions, {
|
|
7204
|
+
highlightWordAroundCursor: (a, b) => a || b,
|
|
7205
|
+
minSelectionLength: Math.min,
|
|
7206
|
+
maxMatches: Math.min
|
|
7207
|
+
});
|
|
7208
|
+
}
|
|
7209
|
+
});
|
|
7210
|
+
/**
|
|
7211
|
+
This extension highlights text that matches the selection. It uses
|
|
7212
|
+
the `"cm-selectionMatch"` class for the highlighting. When
|
|
7213
|
+
`highlightWordAroundCursor` is enabled, the word at the cursor
|
|
7214
|
+
itself will be highlighted with `"cm-selectionMatch-main"`.
|
|
7215
|
+
*/
|
|
7216
|
+
function highlightSelectionMatches(options) {
|
|
7217
|
+
let ext = [defaultTheme, matchHighlighter];
|
|
7218
|
+
if (options)
|
|
7219
|
+
ext.push(highlightConfig.of(options));
|
|
7220
|
+
return ext;
|
|
7221
|
+
}
|
|
7222
|
+
const matchDeco = /*@__PURE__*/view_.Decoration.mark({ class: "cm-selectionMatch" });
|
|
7223
|
+
const mainMatchDeco = /*@__PURE__*/view_.Decoration.mark({ class: "cm-selectionMatch cm-selectionMatch-main" });
|
|
7224
|
+
// Whether the characters directly outside the given positions are non-word characters
|
|
7225
|
+
function insideWordBoundaries(check, state, from, to) {
|
|
7226
|
+
return (from == 0 || check(state.sliceDoc(from - 1, from)) != state_.CharCategory.Word) &&
|
|
7227
|
+
(to == state.doc.length || check(state.sliceDoc(to, to + 1)) != state_.CharCategory.Word);
|
|
7228
|
+
}
|
|
7229
|
+
// Whether the characters directly at the given positions are word characters
|
|
7230
|
+
function insideWord(check, state, from, to) {
|
|
7231
|
+
return check(state.sliceDoc(from, from + 1)) == state_.CharCategory.Word
|
|
7232
|
+
&& check(state.sliceDoc(to - 1, to)) == state_.CharCategory.Word;
|
|
7233
|
+
}
|
|
7234
|
+
const matchHighlighter = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
|
|
7235
|
+
constructor(view) {
|
|
7236
|
+
this.decorations = this.getDeco(view);
|
|
7237
|
+
}
|
|
7238
|
+
update(update) {
|
|
7239
|
+
if (update.selectionSet || update.docChanged || update.viewportChanged)
|
|
7240
|
+
this.decorations = this.getDeco(update.view);
|
|
7241
|
+
}
|
|
7242
|
+
getDeco(view) {
|
|
7243
|
+
let conf = view.state.facet(highlightConfig);
|
|
7244
|
+
let { state } = view, sel = state.selection;
|
|
7245
|
+
if (sel.ranges.length > 1)
|
|
7246
|
+
return view_.Decoration.none;
|
|
7247
|
+
let range = sel.main, query, check = null;
|
|
7248
|
+
if (range.empty) {
|
|
7249
|
+
if (!conf.highlightWordAroundCursor)
|
|
7250
|
+
return view_.Decoration.none;
|
|
7251
|
+
let word = state.wordAt(range.head);
|
|
7252
|
+
if (!word)
|
|
7253
|
+
return view_.Decoration.none;
|
|
7254
|
+
check = state.charCategorizer(range.head);
|
|
7255
|
+
query = state.sliceDoc(word.from, word.to);
|
|
7256
|
+
}
|
|
7257
|
+
else {
|
|
7258
|
+
let len = range.to - range.from;
|
|
7259
|
+
if (len < conf.minSelectionLength || len > 200)
|
|
7260
|
+
return view_.Decoration.none;
|
|
7261
|
+
if (conf.wholeWords) {
|
|
7262
|
+
query = state.sliceDoc(range.from, range.to); // TODO: allow and include leading/trailing space?
|
|
7263
|
+
check = state.charCategorizer(range.head);
|
|
7264
|
+
if (!(insideWordBoundaries(check, state, range.from, range.to)
|
|
7265
|
+
&& insideWord(check, state, range.from, range.to)))
|
|
7266
|
+
return view_.Decoration.none;
|
|
7267
|
+
}
|
|
7268
|
+
else {
|
|
7269
|
+
query = state.sliceDoc(range.from, range.to).trim();
|
|
7270
|
+
if (!query)
|
|
7271
|
+
return view_.Decoration.none;
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
7274
|
+
let deco = [];
|
|
7275
|
+
for (let part of view.visibleRanges) {
|
|
7276
|
+
let cursor = new SearchCursor(state.doc, query, part.from, part.to);
|
|
7277
|
+
while (!cursor.next().done) {
|
|
7278
|
+
let { from, to } = cursor.value;
|
|
7279
|
+
if (!check || insideWordBoundaries(check, state, from, to)) {
|
|
7280
|
+
if (range.empty && from <= range.from && to >= range.to)
|
|
7281
|
+
deco.push(mainMatchDeco.range(from, to));
|
|
7282
|
+
else if (from >= range.to || to <= range.from)
|
|
7283
|
+
deco.push(matchDeco.range(from, to));
|
|
7284
|
+
if (deco.length > conf.maxMatches)
|
|
7285
|
+
return view_.Decoration.none;
|
|
7286
|
+
}
|
|
7287
|
+
}
|
|
7288
|
+
}
|
|
7289
|
+
return view_.Decoration.set(deco);
|
|
7290
|
+
}
|
|
7291
|
+
}, {
|
|
7292
|
+
decorations: v => v.decorations
|
|
7293
|
+
});
|
|
7294
|
+
const defaultTheme = /*@__PURE__*/view_.EditorView.baseTheme({
|
|
7295
|
+
".cm-selectionMatch": { backgroundColor: "#99ff7780" },
|
|
7296
|
+
".cm-searchMatch .cm-selectionMatch": { backgroundColor: "transparent" }
|
|
7297
|
+
});
|
|
7298
|
+
// Select the words around the cursors.
|
|
7299
|
+
const selectWord = ({ state, dispatch }) => {
|
|
7300
|
+
let { selection } = state;
|
|
7301
|
+
let newSel = state_.EditorSelection.create(selection.ranges.map(range => state.wordAt(range.head) || state_.EditorSelection.cursor(range.head)), selection.mainIndex);
|
|
7302
|
+
if (newSel.eq(selection))
|
|
7303
|
+
return false;
|
|
7304
|
+
dispatch(state.update({ selection: newSel }));
|
|
7305
|
+
return true;
|
|
7306
|
+
};
|
|
7307
|
+
// Find next occurrence of query relative to last cursor. Wrap around
|
|
7308
|
+
// the document if there are no more matches.
|
|
7309
|
+
function findNextOccurrence(state, query) {
|
|
7310
|
+
let { main, ranges } = state.selection;
|
|
7311
|
+
let word = state.wordAt(main.head), fullWord = word && word.from == main.from && word.to == main.to;
|
|
7312
|
+
for (let cycled = false, cursor = new SearchCursor(state.doc, query, ranges[ranges.length - 1].to);;) {
|
|
7313
|
+
cursor.next();
|
|
7314
|
+
if (cursor.done) {
|
|
7315
|
+
if (cycled)
|
|
7316
|
+
return null;
|
|
7317
|
+
cursor = new SearchCursor(state.doc, query, 0, Math.max(0, ranges[ranges.length - 1].from - 1));
|
|
7318
|
+
cycled = true;
|
|
7319
|
+
}
|
|
7320
|
+
else {
|
|
7321
|
+
if (cycled && ranges.some(r => r.from == cursor.value.from))
|
|
7322
|
+
continue;
|
|
7323
|
+
if (fullWord) {
|
|
7324
|
+
let word = state.wordAt(cursor.value.from);
|
|
7325
|
+
if (!word || word.from != cursor.value.from || word.to != cursor.value.to)
|
|
7326
|
+
continue;
|
|
7327
|
+
}
|
|
7328
|
+
return cursor.value;
|
|
7329
|
+
}
|
|
7330
|
+
}
|
|
7331
|
+
}
|
|
7332
|
+
/**
|
|
7333
|
+
Select next occurrence of the current selection. Expand selection
|
|
7334
|
+
to the surrounding word when the selection is empty.
|
|
7335
|
+
*/
|
|
7336
|
+
const selectNextOccurrence = ({ state, dispatch }) => {
|
|
7337
|
+
let { ranges } = state.selection;
|
|
7338
|
+
if (ranges.some(sel => sel.from === sel.to))
|
|
7339
|
+
return selectWord({ state, dispatch });
|
|
7340
|
+
let searchedText = state.sliceDoc(ranges[0].from, ranges[0].to);
|
|
7341
|
+
if (state.selection.ranges.some(r => state.sliceDoc(r.from, r.to) != searchedText))
|
|
7342
|
+
return false;
|
|
7343
|
+
let range = findNextOccurrence(state, searchedText);
|
|
7344
|
+
if (!range)
|
|
7345
|
+
return false;
|
|
7346
|
+
dispatch(state.update({
|
|
7347
|
+
selection: state.selection.addRange(state_.EditorSelection.range(range.from, range.to), false),
|
|
7348
|
+
effects: view_.EditorView.scrollIntoView(range.to)
|
|
7349
|
+
}));
|
|
7350
|
+
return true;
|
|
7351
|
+
};
|
|
7352
|
+
|
|
7353
|
+
const searchConfigFacet = /*@__PURE__*/state_.Facet.define({
|
|
7354
|
+
combine(configs) {
|
|
7355
|
+
var _a;
|
|
7356
|
+
return {
|
|
7357
|
+
top: configs.reduce((val, conf) => val !== null && val !== void 0 ? val : conf.top, undefined) || false,
|
|
7358
|
+
caseSensitive: configs.reduce((val, conf) => val !== null && val !== void 0 ? val : conf.caseSensitive, undefined) || false,
|
|
7359
|
+
createPanel: ((_a = configs.find(c => c.createPanel)) === null || _a === void 0 ? void 0 : _a.createPanel) || (view => new SearchPanel(view))
|
|
7360
|
+
};
|
|
7361
|
+
}
|
|
7362
|
+
});
|
|
7363
|
+
/**
|
|
7364
|
+
Add search state to the editor configuration, and optionally
|
|
7365
|
+
configure the search extension.
|
|
7366
|
+
([`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) will automatically
|
|
7367
|
+
enable this if it isn't already on).
|
|
7368
|
+
*/
|
|
7369
|
+
function search(config) {
|
|
7370
|
+
return config ? [searchConfigFacet.of(config), searchExtensions] : searchExtensions;
|
|
7371
|
+
}
|
|
7372
|
+
/**
|
|
7373
|
+
A search query. Part of the editor's search state.
|
|
7374
|
+
*/
|
|
7375
|
+
class SearchQuery {
|
|
7376
|
+
/**
|
|
7377
|
+
Create a query object.
|
|
7378
|
+
*/
|
|
7379
|
+
constructor(config) {
|
|
7380
|
+
this.search = config.search;
|
|
7381
|
+
this.caseSensitive = !!config.caseSensitive;
|
|
7382
|
+
this.regexp = !!config.regexp;
|
|
7383
|
+
this.replace = config.replace || "";
|
|
7384
|
+
this.valid = !!this.search && (!this.regexp || validRegExp(this.search));
|
|
7385
|
+
this.unquoted = config.literal ? this.search : this.search.replace(/\\([nrt\\])/g, (_, ch) => ch == "n" ? "\n" : ch == "r" ? "\r" : ch == "t" ? "\t" : "\\");
|
|
7386
|
+
}
|
|
7387
|
+
/**
|
|
7388
|
+
Compare this query to another query.
|
|
7389
|
+
*/
|
|
7390
|
+
eq(other) {
|
|
7391
|
+
return this.search == other.search && this.replace == other.replace &&
|
|
7392
|
+
this.caseSensitive == other.caseSensitive && this.regexp == other.regexp;
|
|
7393
|
+
}
|
|
7394
|
+
/**
|
|
7395
|
+
@internal
|
|
7396
|
+
*/
|
|
7397
|
+
create() {
|
|
7398
|
+
return this.regexp ? new RegExpQuery(this) : new StringQuery(this);
|
|
7399
|
+
}
|
|
7400
|
+
/**
|
|
7401
|
+
Get a search cursor for this query, searching through the given
|
|
7402
|
+
range in the given document.
|
|
7403
|
+
*/
|
|
7404
|
+
getCursor(doc, from = 0, to = doc.length) {
|
|
7405
|
+
return this.regexp ? regexpCursor(this, doc, from, to) : stringCursor(this, doc, from, to);
|
|
7406
|
+
}
|
|
7407
|
+
}
|
|
7408
|
+
class QueryType {
|
|
7409
|
+
constructor(spec) {
|
|
7410
|
+
this.spec = spec;
|
|
7411
|
+
}
|
|
7412
|
+
}
|
|
7413
|
+
function stringCursor(spec, doc, from, to) {
|
|
7414
|
+
return new SearchCursor(doc, spec.unquoted, from, to, spec.caseSensitive ? undefined : x => x.toLowerCase());
|
|
7415
|
+
}
|
|
7416
|
+
class StringQuery extends QueryType {
|
|
7417
|
+
constructor(spec) {
|
|
7418
|
+
super(spec);
|
|
7419
|
+
}
|
|
7420
|
+
nextMatch(doc, curFrom, curTo) {
|
|
7421
|
+
let cursor = stringCursor(this.spec, doc, curTo, doc.length).nextOverlapping();
|
|
7422
|
+
if (cursor.done)
|
|
7423
|
+
cursor = stringCursor(this.spec, doc, 0, curFrom).nextOverlapping();
|
|
7424
|
+
return cursor.done ? null : cursor.value;
|
|
7425
|
+
}
|
|
7426
|
+
// Searching in reverse is, rather than implementing inverted search
|
|
7427
|
+
// cursor, done by scanning chunk after chunk forward.
|
|
7428
|
+
prevMatchInRange(doc, from, to) {
|
|
7429
|
+
for (let pos = to;;) {
|
|
7430
|
+
let start = Math.max(from, pos - 10000 /* ChunkSize */ - this.spec.unquoted.length);
|
|
7431
|
+
let cursor = stringCursor(this.spec, doc, start, pos), range = null;
|
|
7432
|
+
while (!cursor.nextOverlapping().done)
|
|
7433
|
+
range = cursor.value;
|
|
7434
|
+
if (range)
|
|
7435
|
+
return range;
|
|
7436
|
+
if (start == from)
|
|
7437
|
+
return null;
|
|
7438
|
+
pos -= 10000 /* ChunkSize */;
|
|
7439
|
+
}
|
|
7440
|
+
}
|
|
7441
|
+
prevMatch(doc, curFrom, curTo) {
|
|
7442
|
+
return this.prevMatchInRange(doc, 0, curFrom) ||
|
|
7443
|
+
this.prevMatchInRange(doc, curTo, doc.length);
|
|
7444
|
+
}
|
|
7445
|
+
getReplacement(_result) { return this.spec.replace; }
|
|
7446
|
+
matchAll(doc, limit) {
|
|
7447
|
+
let cursor = stringCursor(this.spec, doc, 0, doc.length), ranges = [];
|
|
7448
|
+
while (!cursor.next().done) {
|
|
7449
|
+
if (ranges.length >= limit)
|
|
7450
|
+
return null;
|
|
7451
|
+
ranges.push(cursor.value);
|
|
7452
|
+
}
|
|
7453
|
+
return ranges;
|
|
7454
|
+
}
|
|
7455
|
+
highlight(doc, from, to, add) {
|
|
7456
|
+
let cursor = stringCursor(this.spec, doc, Math.max(0, from - this.spec.unquoted.length), Math.min(to + this.spec.unquoted.length, doc.length));
|
|
7457
|
+
while (!cursor.next().done)
|
|
7458
|
+
add(cursor.value.from, cursor.value.to);
|
|
7459
|
+
}
|
|
7460
|
+
}
|
|
7461
|
+
function regexpCursor(spec, doc, from, to) {
|
|
7462
|
+
return new RegExpCursor(doc, spec.search, spec.caseSensitive ? undefined : { ignoreCase: true }, from, to);
|
|
7463
|
+
}
|
|
7464
|
+
class RegExpQuery extends QueryType {
|
|
7465
|
+
nextMatch(doc, curFrom, curTo) {
|
|
7466
|
+
let cursor = regexpCursor(this.spec, doc, curTo, doc.length).next();
|
|
7467
|
+
if (cursor.done)
|
|
7468
|
+
cursor = regexpCursor(this.spec, doc, 0, curFrom).next();
|
|
7469
|
+
return cursor.done ? null : cursor.value;
|
|
7470
|
+
}
|
|
7471
|
+
prevMatchInRange(doc, from, to) {
|
|
7472
|
+
for (let size = 1;; size++) {
|
|
7473
|
+
let start = Math.max(from, to - size * 10000 /* ChunkSize */);
|
|
7474
|
+
let cursor = regexpCursor(this.spec, doc, start, to), range = null;
|
|
7475
|
+
while (!cursor.next().done)
|
|
7476
|
+
range = cursor.value;
|
|
7477
|
+
if (range && (start == from || range.from > start + 10))
|
|
7478
|
+
return range;
|
|
7479
|
+
if (start == from)
|
|
7480
|
+
return null;
|
|
7481
|
+
}
|
|
7482
|
+
}
|
|
7483
|
+
prevMatch(doc, curFrom, curTo) {
|
|
7484
|
+
return this.prevMatchInRange(doc, 0, curFrom) ||
|
|
7485
|
+
this.prevMatchInRange(doc, curTo, doc.length);
|
|
7486
|
+
}
|
|
7487
|
+
getReplacement(result) {
|
|
7488
|
+
return this.spec.replace.replace(/\$([$&\d+])/g, (m, i) => i == "$" ? "$"
|
|
7489
|
+
: i == "&" ? result.match[0]
|
|
7490
|
+
: i != "0" && +i < result.match.length ? result.match[i]
|
|
7491
|
+
: m);
|
|
7492
|
+
}
|
|
7493
|
+
matchAll(doc, limit) {
|
|
7494
|
+
let cursor = regexpCursor(this.spec, doc, 0, doc.length), ranges = [];
|
|
7495
|
+
while (!cursor.next().done) {
|
|
7496
|
+
if (ranges.length >= limit)
|
|
7497
|
+
return null;
|
|
7498
|
+
ranges.push(cursor.value);
|
|
7499
|
+
}
|
|
7500
|
+
return ranges;
|
|
7501
|
+
}
|
|
7502
|
+
highlight(doc, from, to, add) {
|
|
7503
|
+
let cursor = regexpCursor(this.spec, doc, Math.max(0, from - 250 /* HighlightMargin */), Math.min(to + 250 /* HighlightMargin */, doc.length));
|
|
7504
|
+
while (!cursor.next().done)
|
|
7505
|
+
add(cursor.value.from, cursor.value.to);
|
|
7506
|
+
}
|
|
7507
|
+
}
|
|
7508
|
+
/**
|
|
7509
|
+
A state effect that updates the current search query. Note that
|
|
7510
|
+
this only has an effect if the search state has been initialized
|
|
7511
|
+
(by including [`search`](https://codemirror.net/6/docs/ref/#search.search) in your configuration or
|
|
7512
|
+
by running [`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel) at least
|
|
7513
|
+
once).
|
|
7514
|
+
*/
|
|
7515
|
+
const setSearchQuery = /*@__PURE__*/state_.StateEffect.define();
|
|
7516
|
+
const togglePanel = /*@__PURE__*/state_.StateEffect.define();
|
|
7517
|
+
const searchState = /*@__PURE__*/state_.StateField.define({
|
|
7518
|
+
create(state) {
|
|
7519
|
+
return new SearchState(defaultQuery(state).create(), null);
|
|
7520
|
+
},
|
|
7521
|
+
update(value, tr) {
|
|
7522
|
+
for (let effect of tr.effects) {
|
|
7523
|
+
if (effect.is(setSearchQuery))
|
|
7524
|
+
value = new SearchState(effect.value.create(), value.panel);
|
|
7525
|
+
else if (effect.is(togglePanel))
|
|
7526
|
+
value = new SearchState(value.query, effect.value ? createSearchPanel : null);
|
|
7527
|
+
}
|
|
7528
|
+
return value;
|
|
7529
|
+
},
|
|
7530
|
+
provide: f => view_.showPanel.from(f, val => val.panel)
|
|
7531
|
+
});
|
|
7532
|
+
/**
|
|
7533
|
+
Get the current search query from an editor state.
|
|
7534
|
+
*/
|
|
7535
|
+
function getSearchQuery(state) {
|
|
7536
|
+
let curState = state.field(searchState, false);
|
|
7537
|
+
return curState ? curState.query.spec : defaultQuery(state);
|
|
7538
|
+
}
|
|
7539
|
+
class SearchState {
|
|
7540
|
+
constructor(query, panel) {
|
|
7541
|
+
this.query = query;
|
|
7542
|
+
this.panel = panel;
|
|
7543
|
+
}
|
|
7544
|
+
}
|
|
7545
|
+
const matchMark = /*@__PURE__*/view_.Decoration.mark({ class: "cm-searchMatch" }), selectedMatchMark = /*@__PURE__*/view_.Decoration.mark({ class: "cm-searchMatch cm-searchMatch-selected" });
|
|
7546
|
+
const searchHighlighter = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
|
|
7547
|
+
constructor(view) {
|
|
7548
|
+
this.view = view;
|
|
7549
|
+
this.decorations = this.highlight(view.state.field(searchState));
|
|
7550
|
+
}
|
|
7551
|
+
update(update) {
|
|
7552
|
+
let state = update.state.field(searchState);
|
|
7553
|
+
if (state != update.startState.field(searchState) || update.docChanged || update.selectionSet || update.viewportChanged)
|
|
7554
|
+
this.decorations = this.highlight(state);
|
|
7555
|
+
}
|
|
7556
|
+
highlight({ query, panel }) {
|
|
7557
|
+
if (!panel || !query.spec.valid)
|
|
7558
|
+
return view_.Decoration.none;
|
|
7559
|
+
let { view } = this;
|
|
7560
|
+
let builder = new state_.RangeSetBuilder();
|
|
7561
|
+
for (let i = 0, ranges = view.visibleRanges, l = ranges.length; i < l; i++) {
|
|
7562
|
+
let { from, to } = ranges[i];
|
|
7563
|
+
while (i < l - 1 && to > ranges[i + 1].from - 2 * 250 /* HighlightMargin */)
|
|
7564
|
+
to = ranges[++i].to;
|
|
7565
|
+
query.highlight(view.state.doc, from, to, (from, to) => {
|
|
7566
|
+
let selected = view.state.selection.ranges.some(r => r.from == from && r.to == to);
|
|
7567
|
+
builder.add(from, to, selected ? selectedMatchMark : matchMark);
|
|
7568
|
+
});
|
|
7569
|
+
}
|
|
7570
|
+
return builder.finish();
|
|
7571
|
+
}
|
|
7572
|
+
}, {
|
|
7573
|
+
decorations: v => v.decorations
|
|
7574
|
+
});
|
|
7575
|
+
function searchCommand(f) {
|
|
7576
|
+
return view => {
|
|
7577
|
+
let state = view.state.field(searchState, false);
|
|
7578
|
+
return state && state.query.spec.valid ? f(view, state) : openSearchPanel(view);
|
|
7579
|
+
};
|
|
7580
|
+
}
|
|
7581
|
+
/**
|
|
7582
|
+
Open the search panel if it isn't already open, and move the
|
|
7583
|
+
selection to the first match after the current main selection.
|
|
7584
|
+
Will wrap around to the start of the document when it reaches the
|
|
7585
|
+
end.
|
|
7586
|
+
*/
|
|
7587
|
+
const findNext = /*@__PURE__*/searchCommand((view, { query }) => {
|
|
7588
|
+
let { from, to } = view.state.selection.main;
|
|
7589
|
+
let next = query.nextMatch(view.state.doc, from, to);
|
|
7590
|
+
if (!next || next.from == from && next.to == to)
|
|
7591
|
+
return false;
|
|
7592
|
+
view.dispatch({
|
|
7593
|
+
selection: { anchor: next.from, head: next.to },
|
|
7594
|
+
scrollIntoView: true,
|
|
7595
|
+
effects: announceMatch(view, next),
|
|
7596
|
+
userEvent: "select.search"
|
|
7597
|
+
});
|
|
7598
|
+
return true;
|
|
7599
|
+
});
|
|
7600
|
+
/**
|
|
7601
|
+
Move the selection to the previous instance of the search query,
|
|
7602
|
+
before the current main selection. Will wrap past the start
|
|
7603
|
+
of the document to start searching at the end again.
|
|
7604
|
+
*/
|
|
7605
|
+
const findPrevious = /*@__PURE__*/searchCommand((view, { query }) => {
|
|
7606
|
+
let { state } = view, { from, to } = state.selection.main;
|
|
7607
|
+
let range = query.prevMatch(state.doc, from, to);
|
|
7608
|
+
if (!range)
|
|
7609
|
+
return false;
|
|
7610
|
+
view.dispatch({
|
|
7611
|
+
selection: { anchor: range.from, head: range.to },
|
|
7612
|
+
scrollIntoView: true,
|
|
7613
|
+
effects: announceMatch(view, range),
|
|
7614
|
+
userEvent: "select.search"
|
|
7615
|
+
});
|
|
7616
|
+
return true;
|
|
7617
|
+
});
|
|
7618
|
+
/**
|
|
7619
|
+
Select all instances of the search query.
|
|
7620
|
+
*/
|
|
7621
|
+
const selectMatches = /*@__PURE__*/searchCommand((view, { query }) => {
|
|
7622
|
+
let ranges = query.matchAll(view.state.doc, 1000);
|
|
7623
|
+
if (!ranges || !ranges.length)
|
|
7624
|
+
return false;
|
|
7625
|
+
view.dispatch({
|
|
7626
|
+
selection: state_.EditorSelection.create(ranges.map(r => state_.EditorSelection.range(r.from, r.to))),
|
|
7627
|
+
userEvent: "select.search.matches"
|
|
7628
|
+
});
|
|
7629
|
+
return true;
|
|
7630
|
+
});
|
|
7631
|
+
/**
|
|
7632
|
+
Select all instances of the currently selected text.
|
|
7633
|
+
*/
|
|
7634
|
+
const selectSelectionMatches = ({ state, dispatch }) => {
|
|
7635
|
+
let sel = state.selection;
|
|
7636
|
+
if (sel.ranges.length > 1 || sel.main.empty)
|
|
7637
|
+
return false;
|
|
7638
|
+
let { from, to } = sel.main;
|
|
7639
|
+
let ranges = [], main = 0;
|
|
7640
|
+
for (let cur = new SearchCursor(state.doc, state.sliceDoc(from, to)); !cur.next().done;) {
|
|
7641
|
+
if (ranges.length > 1000)
|
|
7642
|
+
return false;
|
|
7643
|
+
if (cur.value.from == from)
|
|
7644
|
+
main = ranges.length;
|
|
7645
|
+
ranges.push(state_.EditorSelection.range(cur.value.from, cur.value.to));
|
|
7646
|
+
}
|
|
7647
|
+
dispatch(state.update({
|
|
7648
|
+
selection: state_.EditorSelection.create(ranges, main),
|
|
7649
|
+
userEvent: "select.search.matches"
|
|
7650
|
+
}));
|
|
7651
|
+
return true;
|
|
7652
|
+
};
|
|
7653
|
+
/**
|
|
7654
|
+
Replace the current match of the search query.
|
|
7655
|
+
*/
|
|
7656
|
+
const replaceNext = /*@__PURE__*/searchCommand((view, { query }) => {
|
|
7657
|
+
let { state } = view, { from, to } = state.selection.main;
|
|
7658
|
+
if (state.readOnly)
|
|
7659
|
+
return false;
|
|
7660
|
+
let next = query.nextMatch(state.doc, from, from);
|
|
7661
|
+
if (!next)
|
|
7662
|
+
return false;
|
|
7663
|
+
let changes = [], selection, replacement;
|
|
7664
|
+
let announce = [];
|
|
7665
|
+
if (next.from == from && next.to == to) {
|
|
7666
|
+
replacement = state.toText(query.getReplacement(next));
|
|
7667
|
+
changes.push({ from: next.from, to: next.to, insert: replacement });
|
|
7668
|
+
next = query.nextMatch(state.doc, next.from, next.to);
|
|
7669
|
+
announce.push(view_.EditorView.announce.of(state.phrase("replaced match on line $", state.doc.lineAt(from).number) + "."));
|
|
7670
|
+
}
|
|
7671
|
+
if (next) {
|
|
7672
|
+
let off = changes.length == 0 || changes[0].from >= next.to ? 0 : next.to - next.from - replacement.length;
|
|
7673
|
+
selection = { anchor: next.from - off, head: next.to - off };
|
|
7674
|
+
announce.push(announceMatch(view, next));
|
|
7675
|
+
}
|
|
7676
|
+
view.dispatch({
|
|
7677
|
+
changes, selection,
|
|
7678
|
+
scrollIntoView: !!selection,
|
|
7679
|
+
effects: announce,
|
|
7680
|
+
userEvent: "input.replace"
|
|
7681
|
+
});
|
|
7682
|
+
return true;
|
|
7683
|
+
});
|
|
7684
|
+
/**
|
|
7685
|
+
Replace all instances of the search query with the given
|
|
7686
|
+
replacement.
|
|
7687
|
+
*/
|
|
7688
|
+
const replaceAll = /*@__PURE__*/searchCommand((view, { query }) => {
|
|
7689
|
+
if (view.state.readOnly)
|
|
7690
|
+
return false;
|
|
7691
|
+
let changes = query.matchAll(view.state.doc, 1e9).map(match => {
|
|
7692
|
+
let { from, to } = match;
|
|
7693
|
+
return { from, to, insert: query.getReplacement(match) };
|
|
7694
|
+
});
|
|
7695
|
+
if (!changes.length)
|
|
7696
|
+
return false;
|
|
7697
|
+
let announceText = view.state.phrase("replaced $ matches", changes.length) + ".";
|
|
7698
|
+
view.dispatch({
|
|
7699
|
+
changes,
|
|
7700
|
+
effects: view_.EditorView.announce.of(announceText),
|
|
7701
|
+
userEvent: "input.replace.all"
|
|
7702
|
+
});
|
|
7703
|
+
return true;
|
|
7704
|
+
});
|
|
7705
|
+
function createSearchPanel(view) {
|
|
7706
|
+
return view.state.facet(searchConfigFacet).createPanel(view);
|
|
7707
|
+
}
|
|
7708
|
+
function defaultQuery(state, fallback) {
|
|
7709
|
+
var _a;
|
|
7710
|
+
let sel = state.selection.main;
|
|
7711
|
+
let selText = sel.empty || sel.to > sel.from + 100 ? "" : state.sliceDoc(sel.from, sel.to);
|
|
7712
|
+
let caseSensitive = (_a = fallback === null || fallback === void 0 ? void 0 : fallback.caseSensitive) !== null && _a !== void 0 ? _a : state.facet(searchConfigFacet).caseSensitive;
|
|
7713
|
+
return fallback && !selText ? fallback : new SearchQuery({ search: selText.replace(/\n/g, "\\n"), caseSensitive });
|
|
7714
|
+
}
|
|
7715
|
+
/**
|
|
7716
|
+
Make sure the search panel is open and focused.
|
|
7717
|
+
*/
|
|
7718
|
+
const openSearchPanel = view => {
|
|
7719
|
+
let state = view.state.field(searchState, false);
|
|
7720
|
+
if (state && state.panel) {
|
|
7721
|
+
let panel = (0,view_.getPanel)(view, createSearchPanel);
|
|
7722
|
+
if (!panel)
|
|
7723
|
+
return false;
|
|
7724
|
+
let searchInput = panel.dom.querySelector("[main-field]");
|
|
7725
|
+
if (searchInput && searchInput != view.root.activeElement) {
|
|
7726
|
+
let query = defaultQuery(view.state, state.query.spec);
|
|
7727
|
+
if (query.valid)
|
|
7728
|
+
view.dispatch({ effects: setSearchQuery.of(query) });
|
|
7729
|
+
searchInput.focus();
|
|
7730
|
+
searchInput.select();
|
|
7731
|
+
}
|
|
7732
|
+
}
|
|
7733
|
+
else {
|
|
7734
|
+
view.dispatch({ effects: [
|
|
7735
|
+
togglePanel.of(true),
|
|
7736
|
+
state ? setSearchQuery.of(defaultQuery(view.state, state.query.spec)) : state_.StateEffect.appendConfig.of(searchExtensions)
|
|
7737
|
+
] });
|
|
7738
|
+
}
|
|
7739
|
+
return true;
|
|
7740
|
+
};
|
|
7741
|
+
/**
|
|
7742
|
+
Close the search panel.
|
|
7743
|
+
*/
|
|
7744
|
+
const closeSearchPanel = view => {
|
|
7745
|
+
let state = view.state.field(searchState, false);
|
|
7746
|
+
if (!state || !state.panel)
|
|
7747
|
+
return false;
|
|
7748
|
+
let panel = (0,view_.getPanel)(view, createSearchPanel);
|
|
7749
|
+
if (panel && panel.dom.contains(view.root.activeElement))
|
|
7750
|
+
view.focus();
|
|
7751
|
+
view.dispatch({ effects: togglePanel.of(false) });
|
|
7752
|
+
return true;
|
|
7753
|
+
};
|
|
7754
|
+
/**
|
|
7755
|
+
Default search-related key bindings.
|
|
7756
|
+
|
|
7757
|
+
- Mod-f: [`openSearchPanel`](https://codemirror.net/6/docs/ref/#search.openSearchPanel)
|
|
7758
|
+
- F3, Mod-g: [`findNext`](https://codemirror.net/6/docs/ref/#search.findNext)
|
|
7759
|
+
- Shift-F3, Shift-Mod-g: [`findPrevious`](https://codemirror.net/6/docs/ref/#search.findPrevious)
|
|
7760
|
+
- Alt-g: [`gotoLine`](https://codemirror.net/6/docs/ref/#search.gotoLine)
|
|
7761
|
+
- Mod-d: [`selectNextOccurrence`](https://codemirror.net/6/docs/ref/#search.selectNextOccurrence)
|
|
7762
|
+
*/
|
|
7763
|
+
const searchKeymap = [
|
|
7764
|
+
{ key: "Mod-f", run: openSearchPanel, scope: "editor search-panel" },
|
|
7765
|
+
{ key: "F3", run: findNext, shift: findPrevious, scope: "editor search-panel", preventDefault: true },
|
|
7766
|
+
{ key: "Mod-g", run: findNext, shift: findPrevious, scope: "editor search-panel", preventDefault: true },
|
|
7767
|
+
{ key: "Escape", run: closeSearchPanel, scope: "editor search-panel" },
|
|
7768
|
+
{ key: "Mod-Shift-l", run: selectSelectionMatches },
|
|
7769
|
+
{ key: "Alt-g", run: gotoLine },
|
|
7770
|
+
{ key: "Mod-d", run: selectNextOccurrence, preventDefault: true },
|
|
7771
|
+
];
|
|
7772
|
+
class SearchPanel {
|
|
7773
|
+
constructor(view) {
|
|
7774
|
+
this.view = view;
|
|
7775
|
+
let query = this.query = view.state.field(searchState).query.spec;
|
|
7776
|
+
this.commit = this.commit.bind(this);
|
|
7777
|
+
this.searchField = crelt("input", {
|
|
7778
|
+
value: query.search,
|
|
7779
|
+
placeholder: phrase(view, "Find"),
|
|
7780
|
+
"aria-label": phrase(view, "Find"),
|
|
7781
|
+
class: "cm-textfield",
|
|
7782
|
+
name: "search",
|
|
7783
|
+
"main-field": "true",
|
|
7784
|
+
onchange: this.commit,
|
|
7785
|
+
onkeyup: this.commit
|
|
7786
|
+
});
|
|
7787
|
+
this.replaceField = crelt("input", {
|
|
7788
|
+
value: query.replace,
|
|
7789
|
+
placeholder: phrase(view, "Replace"),
|
|
7790
|
+
"aria-label": phrase(view, "Replace"),
|
|
7791
|
+
class: "cm-textfield",
|
|
7792
|
+
name: "replace",
|
|
7793
|
+
onchange: this.commit,
|
|
7794
|
+
onkeyup: this.commit
|
|
7795
|
+
});
|
|
7796
|
+
this.caseField = crelt("input", {
|
|
7797
|
+
type: "checkbox",
|
|
7798
|
+
name: "case",
|
|
7799
|
+
checked: query.caseSensitive,
|
|
7800
|
+
onchange: this.commit
|
|
7801
|
+
});
|
|
7802
|
+
this.reField = crelt("input", {
|
|
7803
|
+
type: "checkbox",
|
|
7804
|
+
name: "re",
|
|
7805
|
+
checked: query.regexp,
|
|
7806
|
+
onchange: this.commit
|
|
7807
|
+
});
|
|
7808
|
+
function button(name, onclick, content) {
|
|
7809
|
+
return crelt("button", { class: "cm-button", name, onclick, type: "button" }, content);
|
|
7810
|
+
}
|
|
7811
|
+
this.dom = crelt("div", { onkeydown: (e) => this.keydown(e), class: "cm-search" }, [
|
|
7812
|
+
this.searchField,
|
|
7813
|
+
button("next", () => findNext(view), [phrase(view, "next")]),
|
|
7814
|
+
button("prev", () => findPrevious(view), [phrase(view, "previous")]),
|
|
7815
|
+
button("select", () => selectMatches(view), [phrase(view, "all")]),
|
|
7816
|
+
crelt("label", null, [this.caseField, phrase(view, "match case")]),
|
|
7817
|
+
crelt("label", null, [this.reField, phrase(view, "regexp")]),
|
|
7818
|
+
...view.state.readOnly ? [] : [
|
|
7819
|
+
crelt("br"),
|
|
7820
|
+
this.replaceField,
|
|
7821
|
+
button("replace", () => replaceNext(view), [phrase(view, "replace")]),
|
|
7822
|
+
button("replaceAll", () => replaceAll(view), [phrase(view, "replace all")]),
|
|
7823
|
+
crelt("button", {
|
|
7824
|
+
name: "close",
|
|
7825
|
+
onclick: () => closeSearchPanel(view),
|
|
7826
|
+
"aria-label": phrase(view, "close"),
|
|
7827
|
+
type: "button"
|
|
7828
|
+
}, ["×"])
|
|
7829
|
+
]
|
|
7830
|
+
]);
|
|
7831
|
+
}
|
|
7832
|
+
commit() {
|
|
7833
|
+
let query = new SearchQuery({
|
|
7834
|
+
search: this.searchField.value,
|
|
7835
|
+
caseSensitive: this.caseField.checked,
|
|
7836
|
+
regexp: this.reField.checked,
|
|
7837
|
+
replace: this.replaceField.value
|
|
7838
|
+
});
|
|
7839
|
+
if (!query.eq(this.query)) {
|
|
7840
|
+
this.query = query;
|
|
7841
|
+
this.view.dispatch({ effects: setSearchQuery.of(query) });
|
|
7842
|
+
}
|
|
7843
|
+
}
|
|
7844
|
+
keydown(e) {
|
|
7845
|
+
if ((0,view_.runScopeHandlers)(this.view, e, "search-panel")) {
|
|
7846
|
+
e.preventDefault();
|
|
7847
|
+
}
|
|
7848
|
+
else if (e.keyCode == 13 && e.target == this.searchField) {
|
|
7849
|
+
e.preventDefault();
|
|
7850
|
+
(e.shiftKey ? findPrevious : findNext)(this.view);
|
|
7851
|
+
}
|
|
7852
|
+
else if (e.keyCode == 13 && e.target == this.replaceField) {
|
|
7853
|
+
e.preventDefault();
|
|
7854
|
+
replaceNext(this.view);
|
|
7855
|
+
}
|
|
7856
|
+
}
|
|
7857
|
+
update(update) {
|
|
7858
|
+
for (let tr of update.transactions)
|
|
7859
|
+
for (let effect of tr.effects) {
|
|
7860
|
+
if (effect.is(setSearchQuery) && !effect.value.eq(this.query))
|
|
7861
|
+
this.setQuery(effect.value);
|
|
7862
|
+
}
|
|
7863
|
+
}
|
|
7864
|
+
setQuery(query) {
|
|
7865
|
+
this.query = query;
|
|
7866
|
+
this.searchField.value = query.search;
|
|
7867
|
+
this.replaceField.value = query.replace;
|
|
7868
|
+
this.caseField.checked = query.caseSensitive;
|
|
7869
|
+
this.reField.checked = query.regexp;
|
|
7870
|
+
}
|
|
7871
|
+
mount() {
|
|
7872
|
+
this.searchField.select();
|
|
7873
|
+
}
|
|
7874
|
+
get pos() { return 80; }
|
|
7875
|
+
get top() { return this.view.state.facet(searchConfigFacet).top; }
|
|
7876
|
+
}
|
|
7877
|
+
function phrase(view, phrase) { return view.state.phrase(phrase); }
|
|
7878
|
+
const AnnounceMargin = 30;
|
|
7879
|
+
const Break = /[\s\.,:;?!]/;
|
|
7880
|
+
function announceMatch(view, { from, to }) {
|
|
7881
|
+
let line = view.state.doc.lineAt(from), lineEnd = view.state.doc.lineAt(to).to;
|
|
7882
|
+
let start = Math.max(line.from, from - AnnounceMargin), end = Math.min(lineEnd, to + AnnounceMargin);
|
|
7883
|
+
let text = view.state.sliceDoc(start, end);
|
|
7884
|
+
if (start != line.from) {
|
|
7885
|
+
for (let i = 0; i < AnnounceMargin; i++)
|
|
7886
|
+
if (!Break.test(text[i + 1]) && Break.test(text[i])) {
|
|
7887
|
+
text = text.slice(i);
|
|
7888
|
+
break;
|
|
7889
|
+
}
|
|
7890
|
+
}
|
|
7891
|
+
if (end != lineEnd) {
|
|
7892
|
+
for (let i = text.length - 1; i > text.length - AnnounceMargin; i--)
|
|
7893
|
+
if (!Break.test(text[i - 1]) && Break.test(text[i])) {
|
|
7894
|
+
text = text.slice(0, i);
|
|
7895
|
+
break;
|
|
7896
|
+
}
|
|
7897
|
+
}
|
|
7898
|
+
return view_.EditorView.announce.of(`${view.state.phrase("current match")}. ${text} ${view.state.phrase("on line")} ${line.number}.`);
|
|
7899
|
+
}
|
|
7900
|
+
const dist_baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({
|
|
7901
|
+
".cm-panel.cm-search": {
|
|
7902
|
+
padding: "2px 6px 4px",
|
|
7903
|
+
position: "relative",
|
|
7904
|
+
"& [name=close]": {
|
|
7905
|
+
position: "absolute",
|
|
7906
|
+
top: "0",
|
|
7907
|
+
right: "4px",
|
|
7908
|
+
backgroundColor: "inherit",
|
|
7909
|
+
border: "none",
|
|
7910
|
+
font: "inherit",
|
|
7911
|
+
padding: 0,
|
|
7912
|
+
margin: 0
|
|
7913
|
+
},
|
|
7914
|
+
"& input, & button, & label": {
|
|
7915
|
+
margin: ".2em .6em .2em 0"
|
|
7916
|
+
},
|
|
7917
|
+
"& input[type=checkbox]": {
|
|
7918
|
+
marginRight: ".2em"
|
|
7919
|
+
},
|
|
7920
|
+
"& label": {
|
|
7921
|
+
fontSize: "80%",
|
|
7922
|
+
whiteSpace: "pre"
|
|
7923
|
+
}
|
|
7924
|
+
},
|
|
7925
|
+
"&light .cm-searchMatch": { backgroundColor: "#ffff0054" },
|
|
7926
|
+
"&dark .cm-searchMatch": { backgroundColor: "#00ffff8a" },
|
|
7927
|
+
"&light .cm-searchMatch-selected": { backgroundColor: "#ff6a0054" },
|
|
7928
|
+
"&dark .cm-searchMatch-selected": { backgroundColor: "#ff00ff8a" }
|
|
7929
|
+
});
|
|
7930
|
+
const searchExtensions = [
|
|
7931
|
+
searchState,
|
|
7932
|
+
/*@__PURE__*/state_.Prec.lowest(searchHighlighter),
|
|
7933
|
+
dist_baseTheme
|
|
7934
|
+
];
|
|
7935
|
+
|
|
7936
|
+
|
|
7937
|
+
|
|
7938
|
+
;// CONCATENATED MODULE: ./node_modules/@codemirror/autocomplete/dist/index.js
|
|
7939
|
+
|
|
7940
|
+
|
|
7941
|
+
|
|
7942
|
+
|
|
7943
|
+
/**
|
|
7944
|
+
An instance of this is passed to completion source functions.
|
|
7945
|
+
*/
|
|
7946
|
+
class CompletionContext {
|
|
7947
|
+
/**
|
|
7948
|
+
Create a new completion context. (Mostly useful for testing
|
|
7949
|
+
completion sources—in the editor, the extension will create
|
|
7950
|
+
these for you.)
|
|
7951
|
+
*/
|
|
7952
|
+
constructor(
|
|
7953
|
+
/**
|
|
7954
|
+
The editor state that the completion happens in.
|
|
7955
|
+
*/
|
|
7956
|
+
state,
|
|
7957
|
+
/**
|
|
7958
|
+
The position at which the completion is happening.
|
|
7959
|
+
*/
|
|
7960
|
+
pos,
|
|
7961
|
+
/**
|
|
7962
|
+
Indicates whether completion was activated explicitly, or
|
|
7963
|
+
implicitly by typing. The usual way to respond to this is to
|
|
7964
|
+
only return completions when either there is part of a
|
|
7965
|
+
completable entity before the cursor, or `explicit` is true.
|
|
7966
|
+
*/
|
|
7967
|
+
explicit) {
|
|
7968
|
+
this.state = state;
|
|
7969
|
+
this.pos = pos;
|
|
7970
|
+
this.explicit = explicit;
|
|
7971
|
+
/**
|
|
7972
|
+
@internal
|
|
7973
|
+
*/
|
|
7974
|
+
this.abortListeners = [];
|
|
7975
|
+
}
|
|
7976
|
+
/**
|
|
7977
|
+
Get the extent, content, and (if there is a token) type of the
|
|
7978
|
+
token before `this.pos`.
|
|
7979
|
+
*/
|
|
7980
|
+
tokenBefore(types) {
|
|
7981
|
+
let token = dist_syntaxTree(this.state).resolveInner(this.pos, -1);
|
|
7982
|
+
while (token && types.indexOf(token.name) < 0)
|
|
7983
|
+
token = token.parent;
|
|
7984
|
+
return token ? { from: token.from, to: this.pos,
|
|
7985
|
+
text: this.state.sliceDoc(token.from, this.pos),
|
|
7986
|
+
type: token.type } : null;
|
|
7987
|
+
}
|
|
7988
|
+
/**
|
|
7989
|
+
Get the match of the given expression directly before the
|
|
7990
|
+
cursor.
|
|
7991
|
+
*/
|
|
7992
|
+
matchBefore(expr) {
|
|
7993
|
+
let line = this.state.doc.lineAt(this.pos);
|
|
7994
|
+
let start = Math.max(line.from, this.pos - 250);
|
|
7995
|
+
let str = line.text.slice(start - line.from, this.pos - line.from);
|
|
7996
|
+
let found = str.search(ensureAnchor(expr, false));
|
|
7997
|
+
return found < 0 ? null : { from: start + found, to: this.pos, text: str.slice(found) };
|
|
7998
|
+
}
|
|
7999
|
+
/**
|
|
8000
|
+
Yields true when the query has been aborted. Can be useful in
|
|
8001
|
+
asynchronous queries to avoid doing work that will be ignored.
|
|
8002
|
+
*/
|
|
8003
|
+
get aborted() { return this.abortListeners == null; }
|
|
8004
|
+
/**
|
|
8005
|
+
Allows you to register abort handlers, which will be called when
|
|
8006
|
+
the query is
|
|
8007
|
+
[aborted](https://codemirror.net/6/docs/ref/#autocomplete.CompletionContext.aborted).
|
|
8008
|
+
*/
|
|
8009
|
+
addEventListener(type, listener) {
|
|
8010
|
+
if (type == "abort" && this.abortListeners)
|
|
8011
|
+
this.abortListeners.push(listener);
|
|
8012
|
+
}
|
|
8013
|
+
}
|
|
8014
|
+
function toSet(chars) {
|
|
8015
|
+
let flat = Object.keys(chars).join("");
|
|
8016
|
+
let words = /\w/.test(flat);
|
|
8017
|
+
if (words)
|
|
8018
|
+
flat = flat.replace(/\w/g, "");
|
|
8019
|
+
return `[${words ? "\\w" : ""}${flat.replace(/[^\w\s]/g, "\\$&")}]`;
|
|
8020
|
+
}
|
|
8021
|
+
function prefixMatch(options) {
|
|
8022
|
+
let first = Object.create(null), rest = Object.create(null);
|
|
8023
|
+
for (let { label } of options) {
|
|
8024
|
+
first[label[0]] = true;
|
|
8025
|
+
for (let i = 1; i < label.length; i++)
|
|
8026
|
+
rest[label[i]] = true;
|
|
8027
|
+
}
|
|
8028
|
+
let source = toSet(first) + toSet(rest) + "*$";
|
|
8029
|
+
return [new RegExp("^" + source), new RegExp(source)];
|
|
8030
|
+
}
|
|
8031
|
+
/**
|
|
8032
|
+
Given a a fixed array of options, return an autocompleter that
|
|
8033
|
+
completes them.
|
|
8034
|
+
*/
|
|
8035
|
+
function completeFromList(list) {
|
|
8036
|
+
let options = list.map(o => typeof o == "string" ? { label: o } : o);
|
|
8037
|
+
let [validFor, match] = options.every(o => /^\w+$/.test(o.label)) ? [/\w*$/, /\w+$/] : prefixMatch(options);
|
|
8038
|
+
return (context) => {
|
|
8039
|
+
let token = context.matchBefore(match);
|
|
8040
|
+
return token || context.explicit ? { from: token ? token.from : context.pos, options, validFor } : null;
|
|
8041
|
+
};
|
|
8042
|
+
}
|
|
8043
|
+
/**
|
|
8044
|
+
Wrap the given completion source so that it will only fire when the
|
|
8045
|
+
cursor is in a syntax node with one of the given names.
|
|
8046
|
+
*/
|
|
8047
|
+
function ifIn(nodes, source) {
|
|
8048
|
+
return (context) => {
|
|
8049
|
+
for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent)
|
|
8050
|
+
if (nodes.indexOf(pos.name) > -1)
|
|
8051
|
+
return source(context);
|
|
8052
|
+
return null;
|
|
8053
|
+
};
|
|
8054
|
+
}
|
|
8055
|
+
/**
|
|
8056
|
+
Wrap the given completion source so that it will not fire when the
|
|
8057
|
+
cursor is in a syntax node with one of the given names.
|
|
8058
|
+
*/
|
|
8059
|
+
function ifNotIn(nodes, source) {
|
|
8060
|
+
return (context) => {
|
|
8061
|
+
for (let pos = syntaxTree(context.state).resolveInner(context.pos, -1); pos; pos = pos.parent)
|
|
8062
|
+
if (nodes.indexOf(pos.name) > -1)
|
|
8063
|
+
return null;
|
|
8064
|
+
return source(context);
|
|
8065
|
+
};
|
|
8066
|
+
}
|
|
8067
|
+
class Option {
|
|
8068
|
+
constructor(completion, source, match) {
|
|
8069
|
+
this.completion = completion;
|
|
8070
|
+
this.source = source;
|
|
8071
|
+
this.match = match;
|
|
8072
|
+
}
|
|
8073
|
+
}
|
|
8074
|
+
function cur(state) { return state.selection.main.head; }
|
|
8075
|
+
// Make sure the given regexp has a $ at its end and, if `start` is
|
|
8076
|
+
// true, a ^ at its start.
|
|
8077
|
+
function ensureAnchor(expr, start) {
|
|
8078
|
+
var _a;
|
|
8079
|
+
let { source } = expr;
|
|
8080
|
+
let addStart = start && source[0] != "^", addEnd = source[source.length - 1] != "$";
|
|
8081
|
+
if (!addStart && !addEnd)
|
|
8082
|
+
return expr;
|
|
8083
|
+
return new RegExp(`${addStart ? "^" : ""}(?:${source})${addEnd ? "$" : ""}`, (_a = expr.flags) !== null && _a !== void 0 ? _a : (expr.ignoreCase ? "i" : ""));
|
|
8084
|
+
}
|
|
8085
|
+
/**
|
|
8086
|
+
This annotation is added to transactions that are produced by
|
|
8087
|
+
picking a completion.
|
|
8088
|
+
*/
|
|
8089
|
+
const pickedCompletion = /*@__PURE__*/(/* unused pure expression or super */ null && (Annotation.define()));
|
|
8090
|
+
/**
|
|
8091
|
+
Helper function that returns a transaction spec which inserts a
|
|
8092
|
+
completion's text in the main selection range, and any other
|
|
8093
|
+
selection range that has the same text in front of it.
|
|
8094
|
+
*/
|
|
8095
|
+
function insertCompletionText(state, text, from, to) {
|
|
8096
|
+
return Object.assign(Object.assign({}, state.changeByRange(range => {
|
|
8097
|
+
if (range == state.selection.main)
|
|
8098
|
+
return {
|
|
8099
|
+
changes: { from: from, to: to, insert: text },
|
|
8100
|
+
range: state_.EditorSelection.cursor(from + text.length)
|
|
8101
|
+
};
|
|
8102
|
+
let len = to - from;
|
|
8103
|
+
if (!range.empty ||
|
|
8104
|
+
len && state.sliceDoc(range.from - len, range.from) != state.sliceDoc(from, to))
|
|
8105
|
+
return { range };
|
|
8106
|
+
return {
|
|
8107
|
+
changes: { from: range.from - len, to: range.from, insert: text },
|
|
8108
|
+
range: state_.EditorSelection.cursor(range.from - len + text.length)
|
|
8109
|
+
};
|
|
8110
|
+
})), { userEvent: "input.complete" });
|
|
8111
|
+
}
|
|
8112
|
+
function applyCompletion(view, option) {
|
|
8113
|
+
const apply = option.completion.apply || option.completion.label;
|
|
8114
|
+
let result = option.source;
|
|
8115
|
+
if (typeof apply == "string")
|
|
8116
|
+
view.dispatch(insertCompletionText(view.state, apply, result.from, result.to));
|
|
8117
|
+
else
|
|
8118
|
+
apply(view, option.completion, result.from, result.to);
|
|
8119
|
+
}
|
|
8120
|
+
const SourceCache = /*@__PURE__*/new WeakMap();
|
|
8121
|
+
function asSource(source) {
|
|
8122
|
+
if (!Array.isArray(source))
|
|
8123
|
+
return source;
|
|
8124
|
+
let known = SourceCache.get(source);
|
|
8125
|
+
if (!known)
|
|
8126
|
+
SourceCache.set(source, known = completeFromList(source));
|
|
8127
|
+
return known;
|
|
8128
|
+
}
|
|
6592
8129
|
|
|
6593
|
-
|
|
6594
|
-
|
|
8130
|
+
// A pattern matcher for fuzzy completion matching. Create an instance
|
|
8131
|
+
// once for a pattern, and then use that to match any number of
|
|
8132
|
+
// completions.
|
|
8133
|
+
class FuzzyMatcher {
|
|
8134
|
+
constructor(pattern) {
|
|
8135
|
+
this.pattern = pattern;
|
|
8136
|
+
this.chars = [];
|
|
8137
|
+
this.folded = [];
|
|
8138
|
+
// Buffers reused by calls to `match` to track matched character
|
|
8139
|
+
// positions.
|
|
8140
|
+
this.any = [];
|
|
8141
|
+
this.precise = [];
|
|
8142
|
+
this.byWord = [];
|
|
8143
|
+
for (let p = 0; p < pattern.length;) {
|
|
8144
|
+
let char = (0,state_.codePointAt)(pattern, p), size = (0,state_.codePointSize)(char);
|
|
8145
|
+
this.chars.push(char);
|
|
8146
|
+
let part = pattern.slice(p, p + size), upper = part.toUpperCase();
|
|
8147
|
+
this.folded.push((0,state_.codePointAt)(upper == part ? part.toLowerCase() : upper, 0));
|
|
8148
|
+
p += size;
|
|
8149
|
+
}
|
|
8150
|
+
this.astral = pattern.length != this.chars.length;
|
|
8151
|
+
}
|
|
8152
|
+
// Matches a given word (completion) against the pattern (input).
|
|
8153
|
+
// Will return null for no match, and otherwise an array that starts
|
|
8154
|
+
// with the match score, followed by any number of `from, to` pairs
|
|
8155
|
+
// indicating the matched parts of `word`.
|
|
8156
|
+
//
|
|
8157
|
+
// The score is a number that is more negative the worse the match
|
|
8158
|
+
// is. See `Penalty` above.
|
|
8159
|
+
match(word) {
|
|
8160
|
+
if (this.pattern.length == 0)
|
|
8161
|
+
return [0];
|
|
8162
|
+
if (word.length < this.pattern.length)
|
|
8163
|
+
return null;
|
|
8164
|
+
let { chars, folded, any, precise, byWord } = this;
|
|
8165
|
+
// For single-character queries, only match when they occur right
|
|
8166
|
+
// at the start
|
|
8167
|
+
if (chars.length == 1) {
|
|
8168
|
+
let first = (0,state_.codePointAt)(word, 0);
|
|
8169
|
+
return first == chars[0] ? [0, 0, (0,state_.codePointSize)(first)]
|
|
8170
|
+
: first == folded[0] ? [-200 /* CaseFold */, 0, (0,state_.codePointSize)(first)] : null;
|
|
8171
|
+
}
|
|
8172
|
+
let direct = word.indexOf(this.pattern);
|
|
8173
|
+
if (direct == 0)
|
|
8174
|
+
return [0, 0, this.pattern.length];
|
|
8175
|
+
let len = chars.length, anyTo = 0;
|
|
8176
|
+
if (direct < 0) {
|
|
8177
|
+
for (let i = 0, e = Math.min(word.length, 200); i < e && anyTo < len;) {
|
|
8178
|
+
let next = (0,state_.codePointAt)(word, i);
|
|
8179
|
+
if (next == chars[anyTo] || next == folded[anyTo])
|
|
8180
|
+
any[anyTo++] = i;
|
|
8181
|
+
i += (0,state_.codePointSize)(next);
|
|
8182
|
+
}
|
|
8183
|
+
// No match, exit immediately
|
|
8184
|
+
if (anyTo < len)
|
|
8185
|
+
return null;
|
|
8186
|
+
}
|
|
8187
|
+
// This tracks the extent of the precise (non-folded, not
|
|
8188
|
+
// necessarily adjacent) match
|
|
8189
|
+
let preciseTo = 0;
|
|
8190
|
+
// Tracks whether there is a match that hits only characters that
|
|
8191
|
+
// appear to be starting words. `byWordFolded` is set to true when
|
|
8192
|
+
// a case folded character is encountered in such a match
|
|
8193
|
+
let byWordTo = 0, byWordFolded = false;
|
|
8194
|
+
// If we've found a partial adjacent match, these track its state
|
|
8195
|
+
let adjacentTo = 0, adjacentStart = -1, adjacentEnd = -1;
|
|
8196
|
+
let hasLower = /[a-z]/.test(word), wordAdjacent = true;
|
|
8197
|
+
// Go over the option's text, scanning for the various kinds of matches
|
|
8198
|
+
for (let i = 0, e = Math.min(word.length, 200), prevType = 0 /* NonWord */; i < e && byWordTo < len;) {
|
|
8199
|
+
let next = (0,state_.codePointAt)(word, i);
|
|
8200
|
+
if (direct < 0) {
|
|
8201
|
+
if (preciseTo < len && next == chars[preciseTo])
|
|
8202
|
+
precise[preciseTo++] = i;
|
|
8203
|
+
if (adjacentTo < len) {
|
|
8204
|
+
if (next == chars[adjacentTo] || next == folded[adjacentTo]) {
|
|
8205
|
+
if (adjacentTo == 0)
|
|
8206
|
+
adjacentStart = i;
|
|
8207
|
+
adjacentEnd = i + 1;
|
|
8208
|
+
adjacentTo++;
|
|
8209
|
+
}
|
|
8210
|
+
else {
|
|
8211
|
+
adjacentTo = 0;
|
|
8212
|
+
}
|
|
8213
|
+
}
|
|
8214
|
+
}
|
|
8215
|
+
let ch, type = next < 0xff
|
|
8216
|
+
? (next >= 48 && next <= 57 || next >= 97 && next <= 122 ? 2 /* Lower */ : next >= 65 && next <= 90 ? 1 /* Upper */ : 0 /* NonWord */)
|
|
8217
|
+
: ((ch = (0,state_.fromCodePoint)(next)) != ch.toLowerCase() ? 1 /* Upper */ : ch != ch.toUpperCase() ? 2 /* Lower */ : 0 /* NonWord */);
|
|
8218
|
+
if (!i || type == 1 /* Upper */ && hasLower || prevType == 0 /* NonWord */ && type != 0 /* NonWord */) {
|
|
8219
|
+
if (chars[byWordTo] == next || (folded[byWordTo] == next && (byWordFolded = true)))
|
|
8220
|
+
byWord[byWordTo++] = i;
|
|
8221
|
+
else if (byWord.length)
|
|
8222
|
+
wordAdjacent = false;
|
|
8223
|
+
}
|
|
8224
|
+
prevType = type;
|
|
8225
|
+
i += (0,state_.codePointSize)(next);
|
|
8226
|
+
}
|
|
8227
|
+
if (byWordTo == len && byWord[0] == 0 && wordAdjacent)
|
|
8228
|
+
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0), byWord, word);
|
|
8229
|
+
if (adjacentTo == len && adjacentStart == 0)
|
|
8230
|
+
return [-200 /* CaseFold */ - word.length, 0, adjacentEnd];
|
|
8231
|
+
if (direct > -1)
|
|
8232
|
+
return [-700 /* NotStart */ - word.length, direct, direct + this.pattern.length];
|
|
8233
|
+
if (adjacentTo == len)
|
|
8234
|
+
return [-200 /* CaseFold */ + -700 /* NotStart */ - word.length, adjacentStart, adjacentEnd];
|
|
8235
|
+
if (byWordTo == len)
|
|
8236
|
+
return this.result(-100 /* ByWord */ + (byWordFolded ? -200 /* CaseFold */ : 0) + -700 /* NotStart */ +
|
|
8237
|
+
(wordAdjacent ? 0 : -1100 /* Gap */), byWord, word);
|
|
8238
|
+
return chars.length == 2 ? null : this.result((any[0] ? -700 /* NotStart */ : 0) + -200 /* CaseFold */ + -1100 /* Gap */, any, word);
|
|
8239
|
+
}
|
|
8240
|
+
result(score, positions, word) {
|
|
8241
|
+
let result = [score - word.length], i = 1;
|
|
8242
|
+
for (let pos of positions) {
|
|
8243
|
+
let to = pos + (this.astral ? (0,state_.codePointSize)((0,state_.codePointAt)(word, pos)) : 1);
|
|
8244
|
+
if (i > 1 && result[i - 1] == pos)
|
|
8245
|
+
result[i - 1] = to;
|
|
8246
|
+
else {
|
|
8247
|
+
result[i++] = pos;
|
|
8248
|
+
result[i++] = to;
|
|
8249
|
+
}
|
|
8250
|
+
}
|
|
8251
|
+
return result;
|
|
8252
|
+
}
|
|
8253
|
+
}
|
|
6595
8254
|
|
|
8255
|
+
const completionConfig = /*@__PURE__*/state_.Facet.define({
|
|
8256
|
+
combine(configs) {
|
|
8257
|
+
return (0,state_.combineConfig)(configs, {
|
|
8258
|
+
activateOnTyping: true,
|
|
8259
|
+
override: null,
|
|
8260
|
+
closeOnBlur: true,
|
|
8261
|
+
maxRenderedOptions: 100,
|
|
8262
|
+
defaultKeymap: true,
|
|
8263
|
+
optionClass: () => "",
|
|
8264
|
+
aboveCursor: false,
|
|
8265
|
+
icons: true,
|
|
8266
|
+
addToOptions: []
|
|
8267
|
+
}, {
|
|
8268
|
+
defaultKeymap: (a, b) => a && b,
|
|
8269
|
+
closeOnBlur: (a, b) => a && b,
|
|
8270
|
+
icons: (a, b) => a && b,
|
|
8271
|
+
optionClass: (a, b) => c => joinClass(a(c), b(c)),
|
|
8272
|
+
addToOptions: (a, b) => a.concat(b)
|
|
8273
|
+
});
|
|
8274
|
+
}
|
|
8275
|
+
});
|
|
8276
|
+
function joinClass(a, b) {
|
|
8277
|
+
return a ? b ? a + " " + b : a : b;
|
|
8278
|
+
}
|
|
6596
8279
|
|
|
8280
|
+
function optionContent(config) {
|
|
8281
|
+
let content = config.addToOptions.slice();
|
|
8282
|
+
if (config.icons)
|
|
8283
|
+
content.push({
|
|
8284
|
+
render(completion) {
|
|
8285
|
+
let icon = document.createElement("div");
|
|
8286
|
+
icon.classList.add("cm-completionIcon");
|
|
8287
|
+
if (completion.type)
|
|
8288
|
+
icon.classList.add(...completion.type.split(/\s+/g).map(cls => "cm-completionIcon-" + cls));
|
|
8289
|
+
icon.setAttribute("aria-hidden", "true");
|
|
8290
|
+
return icon;
|
|
8291
|
+
},
|
|
8292
|
+
position: 20
|
|
8293
|
+
});
|
|
8294
|
+
content.push({
|
|
8295
|
+
render(completion, _s, match) {
|
|
8296
|
+
let labelElt = document.createElement("span");
|
|
8297
|
+
labelElt.className = "cm-completionLabel";
|
|
8298
|
+
let { label } = completion, off = 0;
|
|
8299
|
+
for (let j = 1; j < match.length;) {
|
|
8300
|
+
let from = match[j++], to = match[j++];
|
|
8301
|
+
if (from > off)
|
|
8302
|
+
labelElt.appendChild(document.createTextNode(label.slice(off, from)));
|
|
8303
|
+
let span = labelElt.appendChild(document.createElement("span"));
|
|
8304
|
+
span.appendChild(document.createTextNode(label.slice(from, to)));
|
|
8305
|
+
span.className = "cm-completionMatchedText";
|
|
8306
|
+
off = to;
|
|
8307
|
+
}
|
|
8308
|
+
if (off < label.length)
|
|
8309
|
+
labelElt.appendChild(document.createTextNode(label.slice(off)));
|
|
8310
|
+
return labelElt;
|
|
8311
|
+
},
|
|
8312
|
+
position: 50
|
|
8313
|
+
}, {
|
|
8314
|
+
render(completion) {
|
|
8315
|
+
if (!completion.detail)
|
|
8316
|
+
return null;
|
|
8317
|
+
let detailElt = document.createElement("span");
|
|
8318
|
+
detailElt.className = "cm-completionDetail";
|
|
8319
|
+
detailElt.textContent = completion.detail;
|
|
8320
|
+
return detailElt;
|
|
8321
|
+
},
|
|
8322
|
+
position: 80
|
|
8323
|
+
});
|
|
8324
|
+
return content.sort((a, b) => a.position - b.position).map(a => a.render);
|
|
8325
|
+
}
|
|
8326
|
+
function rangeAroundSelected(total, selected, max) {
|
|
8327
|
+
if (total <= max)
|
|
8328
|
+
return { from: 0, to: total };
|
|
8329
|
+
if (selected <= (total >> 1)) {
|
|
8330
|
+
let off = Math.floor(selected / max);
|
|
8331
|
+
return { from: off * max, to: (off + 1) * max };
|
|
8332
|
+
}
|
|
8333
|
+
let off = Math.floor((total - selected) / max);
|
|
8334
|
+
return { from: total - (off + 1) * max, to: total - off * max };
|
|
8335
|
+
}
|
|
8336
|
+
class CompletionTooltip {
|
|
8337
|
+
constructor(view, stateField) {
|
|
8338
|
+
this.view = view;
|
|
8339
|
+
this.stateField = stateField;
|
|
8340
|
+
this.info = null;
|
|
8341
|
+
this.placeInfo = {
|
|
8342
|
+
read: () => this.measureInfo(),
|
|
8343
|
+
write: (pos) => this.positionInfo(pos),
|
|
8344
|
+
key: this
|
|
8345
|
+
};
|
|
8346
|
+
let cState = view.state.field(stateField);
|
|
8347
|
+
let { options, selected } = cState.open;
|
|
8348
|
+
let config = view.state.facet(completionConfig);
|
|
8349
|
+
this.optionContent = optionContent(config);
|
|
8350
|
+
this.optionClass = config.optionClass;
|
|
8351
|
+
this.range = rangeAroundSelected(options.length, selected, config.maxRenderedOptions);
|
|
8352
|
+
this.dom = document.createElement("div");
|
|
8353
|
+
this.dom.className = "cm-tooltip-autocomplete";
|
|
8354
|
+
this.dom.addEventListener("mousedown", (e) => {
|
|
8355
|
+
for (let dom = e.target, match; dom && dom != this.dom; dom = dom.parentNode) {
|
|
8356
|
+
if (dom.nodeName == "LI" && (match = /-(\d+)$/.exec(dom.id)) && +match[1] < options.length) {
|
|
8357
|
+
applyCompletion(view, options[+match[1]]);
|
|
8358
|
+
e.preventDefault();
|
|
8359
|
+
return;
|
|
8360
|
+
}
|
|
8361
|
+
}
|
|
8362
|
+
});
|
|
8363
|
+
this.list = this.dom.appendChild(this.createListBox(options, cState.id, this.range));
|
|
8364
|
+
this.list.addEventListener("scroll", () => {
|
|
8365
|
+
if (this.info)
|
|
8366
|
+
this.view.requestMeasure(this.placeInfo);
|
|
8367
|
+
});
|
|
8368
|
+
}
|
|
8369
|
+
mount() { this.updateSel(); }
|
|
8370
|
+
update(update) {
|
|
8371
|
+
if (update.state.field(this.stateField) != update.startState.field(this.stateField))
|
|
8372
|
+
this.updateSel();
|
|
8373
|
+
}
|
|
8374
|
+
positioned() {
|
|
8375
|
+
if (this.info)
|
|
8376
|
+
this.view.requestMeasure(this.placeInfo);
|
|
8377
|
+
}
|
|
8378
|
+
updateSel() {
|
|
8379
|
+
let cState = this.view.state.field(this.stateField), open = cState.open;
|
|
8380
|
+
if (open.selected < this.range.from || open.selected >= this.range.to) {
|
|
8381
|
+
this.range = rangeAroundSelected(open.options.length, open.selected, this.view.state.facet(completionConfig).maxRenderedOptions);
|
|
8382
|
+
this.list.remove();
|
|
8383
|
+
this.list = this.dom.appendChild(this.createListBox(open.options, cState.id, this.range));
|
|
8384
|
+
this.list.addEventListener("scroll", () => {
|
|
8385
|
+
if (this.info)
|
|
8386
|
+
this.view.requestMeasure(this.placeInfo);
|
|
8387
|
+
});
|
|
8388
|
+
}
|
|
8389
|
+
if (this.updateSelectedOption(open.selected)) {
|
|
8390
|
+
if (this.info) {
|
|
8391
|
+
this.info.remove();
|
|
8392
|
+
this.info = null;
|
|
8393
|
+
}
|
|
8394
|
+
let { completion } = open.options[open.selected];
|
|
8395
|
+
let { info } = completion;
|
|
8396
|
+
if (!info)
|
|
8397
|
+
return;
|
|
8398
|
+
let infoResult = typeof info === 'string' ? document.createTextNode(info) : info(completion);
|
|
8399
|
+
if (!infoResult)
|
|
8400
|
+
return;
|
|
8401
|
+
if ('then' in infoResult) {
|
|
8402
|
+
infoResult.then(node => {
|
|
8403
|
+
if (node && this.view.state.field(this.stateField, false) == cState)
|
|
8404
|
+
this.addInfoPane(node);
|
|
8405
|
+
}).catch(e => (0,view_.logException)(this.view.state, e, "completion info"));
|
|
8406
|
+
}
|
|
8407
|
+
else {
|
|
8408
|
+
this.addInfoPane(infoResult);
|
|
8409
|
+
}
|
|
8410
|
+
}
|
|
8411
|
+
}
|
|
8412
|
+
addInfoPane(content) {
|
|
8413
|
+
let dom = this.info = document.createElement("div");
|
|
8414
|
+
dom.className = "cm-tooltip cm-completionInfo";
|
|
8415
|
+
dom.appendChild(content);
|
|
8416
|
+
this.dom.appendChild(dom);
|
|
8417
|
+
this.view.requestMeasure(this.placeInfo);
|
|
8418
|
+
}
|
|
8419
|
+
updateSelectedOption(selected) {
|
|
8420
|
+
let set = null;
|
|
8421
|
+
for (let opt = this.list.firstChild, i = this.range.from; opt; opt = opt.nextSibling, i++) {
|
|
8422
|
+
if (i == selected) {
|
|
8423
|
+
if (!opt.hasAttribute("aria-selected")) {
|
|
8424
|
+
opt.setAttribute("aria-selected", "true");
|
|
8425
|
+
set = opt;
|
|
8426
|
+
}
|
|
8427
|
+
}
|
|
8428
|
+
else {
|
|
8429
|
+
if (opt.hasAttribute("aria-selected"))
|
|
8430
|
+
opt.removeAttribute("aria-selected");
|
|
8431
|
+
}
|
|
8432
|
+
}
|
|
8433
|
+
if (set)
|
|
8434
|
+
scrollIntoView(this.list, set);
|
|
8435
|
+
return set;
|
|
8436
|
+
}
|
|
8437
|
+
measureInfo() {
|
|
8438
|
+
let sel = this.dom.querySelector("[aria-selected]");
|
|
8439
|
+
if (!sel || !this.info)
|
|
8440
|
+
return null;
|
|
8441
|
+
let listRect = this.dom.getBoundingClientRect();
|
|
8442
|
+
let infoRect = this.info.getBoundingClientRect();
|
|
8443
|
+
let selRect = sel.getBoundingClientRect();
|
|
8444
|
+
if (selRect.top > Math.min(innerHeight, listRect.bottom) - 10 || selRect.bottom < Math.max(0, listRect.top) + 10)
|
|
8445
|
+
return null;
|
|
8446
|
+
let top = Math.max(0, Math.min(selRect.top, innerHeight - infoRect.height)) - listRect.top;
|
|
8447
|
+
let left = this.view.textDirection == view_.Direction.RTL;
|
|
8448
|
+
let spaceLeft = listRect.left, spaceRight = innerWidth - listRect.right;
|
|
8449
|
+
if (left && spaceLeft < Math.min(infoRect.width, spaceRight))
|
|
8450
|
+
left = false;
|
|
8451
|
+
else if (!left && spaceRight < Math.min(infoRect.width, spaceLeft))
|
|
8452
|
+
left = true;
|
|
8453
|
+
return { top, left };
|
|
8454
|
+
}
|
|
8455
|
+
positionInfo(pos) {
|
|
8456
|
+
if (this.info) {
|
|
8457
|
+
this.info.style.top = (pos ? pos.top : -1e6) + "px";
|
|
8458
|
+
if (pos) {
|
|
8459
|
+
this.info.classList.toggle("cm-completionInfo-left", pos.left);
|
|
8460
|
+
this.info.classList.toggle("cm-completionInfo-right", !pos.left);
|
|
8461
|
+
}
|
|
8462
|
+
}
|
|
8463
|
+
}
|
|
8464
|
+
createListBox(options, id, range) {
|
|
8465
|
+
const ul = document.createElement("ul");
|
|
8466
|
+
ul.id = id;
|
|
8467
|
+
ul.setAttribute("role", "listbox");
|
|
8468
|
+
ul.setAttribute("aria-expanded", "true");
|
|
8469
|
+
ul.setAttribute("aria-label", this.view.state.phrase("Completions"));
|
|
8470
|
+
for (let i = range.from; i < range.to; i++) {
|
|
8471
|
+
let { completion, match } = options[i];
|
|
8472
|
+
const li = ul.appendChild(document.createElement("li"));
|
|
8473
|
+
li.id = id + "-" + i;
|
|
8474
|
+
li.setAttribute("role", "option");
|
|
8475
|
+
let cls = this.optionClass(completion);
|
|
8476
|
+
if (cls)
|
|
8477
|
+
li.className = cls;
|
|
8478
|
+
for (let source of this.optionContent) {
|
|
8479
|
+
let node = source(completion, this.view.state, match);
|
|
8480
|
+
if (node)
|
|
8481
|
+
li.appendChild(node);
|
|
8482
|
+
}
|
|
8483
|
+
}
|
|
8484
|
+
if (range.from)
|
|
8485
|
+
ul.classList.add("cm-completionListIncompleteTop");
|
|
8486
|
+
if (range.to < options.length)
|
|
8487
|
+
ul.classList.add("cm-completionListIncompleteBottom");
|
|
8488
|
+
return ul;
|
|
8489
|
+
}
|
|
8490
|
+
}
|
|
8491
|
+
// We allocate a new function instance every time the completion
|
|
8492
|
+
// changes to force redrawing/repositioning of the tooltip
|
|
8493
|
+
function completionTooltip(stateField) {
|
|
8494
|
+
return (view) => new CompletionTooltip(view, stateField);
|
|
8495
|
+
}
|
|
8496
|
+
function scrollIntoView(container, element) {
|
|
8497
|
+
let parent = container.getBoundingClientRect();
|
|
8498
|
+
let self = element.getBoundingClientRect();
|
|
8499
|
+
if (self.top < parent.top)
|
|
8500
|
+
container.scrollTop -= parent.top - self.top;
|
|
8501
|
+
else if (self.bottom > parent.bottom)
|
|
8502
|
+
container.scrollTop += self.bottom - parent.bottom;
|
|
8503
|
+
}
|
|
6597
8504
|
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
8505
|
+
// Used to pick a preferred option when two options with the same
|
|
8506
|
+
// label occur in the result.
|
|
8507
|
+
function score(option) {
|
|
8508
|
+
return (option.boost || 0) * 100 + (option.apply ? 10 : 0) + (option.info ? 5 : 0) +
|
|
8509
|
+
(option.type ? 1 : 0);
|
|
8510
|
+
}
|
|
8511
|
+
function sortOptions(active, state) {
|
|
8512
|
+
let options = [], i = 0;
|
|
8513
|
+
for (let a of active)
|
|
8514
|
+
if (a.hasResult()) {
|
|
8515
|
+
if (a.result.filter === false) {
|
|
8516
|
+
let getMatch = a.result.getMatch;
|
|
8517
|
+
for (let option of a.result.options) {
|
|
8518
|
+
let match = [1e9 - i++];
|
|
8519
|
+
if (getMatch)
|
|
8520
|
+
for (let n of getMatch(option))
|
|
8521
|
+
match.push(n);
|
|
8522
|
+
options.push(new Option(option, a, match));
|
|
8523
|
+
}
|
|
8524
|
+
}
|
|
8525
|
+
else {
|
|
8526
|
+
let matcher = new FuzzyMatcher(state.sliceDoc(a.from, a.to)), match;
|
|
8527
|
+
for (let option of a.result.options)
|
|
8528
|
+
if (match = matcher.match(option.label)) {
|
|
8529
|
+
if (option.boost != null)
|
|
8530
|
+
match[0] += option.boost;
|
|
8531
|
+
options.push(new Option(option, a, match));
|
|
8532
|
+
}
|
|
8533
|
+
}
|
|
8534
|
+
}
|
|
8535
|
+
let result = [], prev = null;
|
|
8536
|
+
for (let opt of options.sort(cmpOption)) {
|
|
8537
|
+
if (!prev || prev.label != opt.completion.label || prev.detail != opt.completion.detail ||
|
|
8538
|
+
(prev.type != null && opt.completion.type != null && prev.type != opt.completion.type) ||
|
|
8539
|
+
prev.apply != opt.completion.apply)
|
|
8540
|
+
result.push(opt);
|
|
8541
|
+
else if (score(opt.completion) > score(prev))
|
|
8542
|
+
result[result.length - 1] = opt;
|
|
8543
|
+
prev = opt.completion;
|
|
8544
|
+
}
|
|
8545
|
+
return result;
|
|
8546
|
+
}
|
|
8547
|
+
class CompletionDialog {
|
|
8548
|
+
constructor(options, attrs, tooltip, timestamp, selected) {
|
|
8549
|
+
this.options = options;
|
|
8550
|
+
this.attrs = attrs;
|
|
8551
|
+
this.tooltip = tooltip;
|
|
8552
|
+
this.timestamp = timestamp;
|
|
8553
|
+
this.selected = selected;
|
|
8554
|
+
}
|
|
8555
|
+
setSelected(selected, id) {
|
|
8556
|
+
return selected == this.selected || selected >= this.options.length ? this
|
|
8557
|
+
: new CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected);
|
|
8558
|
+
}
|
|
8559
|
+
static build(active, state, id, prev, conf) {
|
|
8560
|
+
let options = sortOptions(active, state);
|
|
8561
|
+
if (!options.length)
|
|
8562
|
+
return null;
|
|
8563
|
+
let selected = 0;
|
|
8564
|
+
if (prev && prev.selected) {
|
|
8565
|
+
let selectedValue = prev.options[prev.selected].completion;
|
|
8566
|
+
for (let i = 0; i < options.length; i++)
|
|
8567
|
+
if (options[i].completion == selectedValue) {
|
|
8568
|
+
selected = i;
|
|
8569
|
+
break;
|
|
8570
|
+
}
|
|
8571
|
+
}
|
|
8572
|
+
return new CompletionDialog(options, makeAttrs(id, selected), {
|
|
8573
|
+
pos: active.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
|
8574
|
+
create: completionTooltip(completionState),
|
|
8575
|
+
above: conf.aboveCursor,
|
|
8576
|
+
}, prev ? prev.timestamp : Date.now(), selected);
|
|
8577
|
+
}
|
|
8578
|
+
map(changes) {
|
|
8579
|
+
return new CompletionDialog(this.options, this.attrs, Object.assign(Object.assign({}, this.tooltip), { pos: changes.mapPos(this.tooltip.pos) }), this.timestamp, this.selected);
|
|
8580
|
+
}
|
|
8581
|
+
}
|
|
8582
|
+
class CompletionState {
|
|
8583
|
+
constructor(active, id, open) {
|
|
8584
|
+
this.active = active;
|
|
8585
|
+
this.id = id;
|
|
8586
|
+
this.open = open;
|
|
8587
|
+
}
|
|
8588
|
+
static start() {
|
|
8589
|
+
return new CompletionState(dist_none, "cm-ac-" + Math.floor(Math.random() * 2e6).toString(36), null);
|
|
8590
|
+
}
|
|
8591
|
+
update(tr) {
|
|
8592
|
+
let { state } = tr, conf = state.facet(completionConfig);
|
|
8593
|
+
let sources = conf.override ||
|
|
8594
|
+
state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
|
8595
|
+
let active = sources.map(source => {
|
|
8596
|
+
let value = this.active.find(s => s.source == source) ||
|
|
8597
|
+
new ActiveSource(source, this.active.some(a => a.state != 0 /* Inactive */) ? 1 /* Pending */ : 0 /* Inactive */);
|
|
8598
|
+
return value.update(tr, conf);
|
|
8599
|
+
});
|
|
8600
|
+
if (active.length == this.active.length && active.every((a, i) => a == this.active[i]))
|
|
8601
|
+
active = this.active;
|
|
8602
|
+
let open = tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) ||
|
|
8603
|
+
!sameResults(active, this.active) ? CompletionDialog.build(active, state, this.id, this.open, conf)
|
|
8604
|
+
: this.open && tr.docChanged ? this.open.map(tr.changes) : this.open;
|
|
8605
|
+
if (!open && active.every(a => a.state != 1 /* Pending */) && active.some(a => a.hasResult()))
|
|
8606
|
+
active = active.map(a => a.hasResult() ? new ActiveSource(a.source, 0 /* Inactive */) : a);
|
|
8607
|
+
for (let effect of tr.effects)
|
|
8608
|
+
if (effect.is(setSelectedEffect))
|
|
8609
|
+
open = open && open.setSelected(effect.value, this.id);
|
|
8610
|
+
return active == this.active && open == this.open ? this : new CompletionState(active, this.id, open);
|
|
8611
|
+
}
|
|
8612
|
+
get tooltip() { return this.open ? this.open.tooltip : null; }
|
|
8613
|
+
get attrs() { return this.open ? this.open.attrs : baseAttrs; }
|
|
8614
|
+
}
|
|
8615
|
+
function sameResults(a, b) {
|
|
8616
|
+
if (a == b)
|
|
8617
|
+
return true;
|
|
8618
|
+
for (let iA = 0, iB = 0;;) {
|
|
8619
|
+
while (iA < a.length && !a[iA].hasResult)
|
|
8620
|
+
iA++;
|
|
8621
|
+
while (iB < b.length && !b[iB].hasResult)
|
|
8622
|
+
iB++;
|
|
8623
|
+
let endA = iA == a.length, endB = iB == b.length;
|
|
8624
|
+
if (endA || endB)
|
|
8625
|
+
return endA == endB;
|
|
8626
|
+
if (a[iA++].result != b[iB++].result)
|
|
8627
|
+
return false;
|
|
8628
|
+
}
|
|
8629
|
+
}
|
|
8630
|
+
const baseAttrs = {
|
|
8631
|
+
"aria-autocomplete": "list"
|
|
8632
|
+
};
|
|
8633
|
+
function makeAttrs(id, selected) {
|
|
8634
|
+
return {
|
|
8635
|
+
"aria-autocomplete": "list",
|
|
8636
|
+
"aria-haspopup": "listbox",
|
|
8637
|
+
"aria-activedescendant": id + "-" + selected,
|
|
8638
|
+
"aria-controls": id
|
|
8639
|
+
};
|
|
8640
|
+
}
|
|
8641
|
+
const dist_none = [];
|
|
8642
|
+
function cmpOption(a, b) {
|
|
8643
|
+
let dScore = b.match[0] - a.match[0];
|
|
8644
|
+
if (dScore)
|
|
8645
|
+
return dScore;
|
|
8646
|
+
return a.completion.label.localeCompare(b.completion.label);
|
|
8647
|
+
}
|
|
8648
|
+
function getUserEvent(tr) {
|
|
8649
|
+
return tr.isUserEvent("input.type") ? "input" : tr.isUserEvent("delete.backward") ? "delete" : null;
|
|
8650
|
+
}
|
|
8651
|
+
class ActiveSource {
|
|
8652
|
+
constructor(source, state, explicitPos = -1) {
|
|
8653
|
+
this.source = source;
|
|
8654
|
+
this.state = state;
|
|
8655
|
+
this.explicitPos = explicitPos;
|
|
8656
|
+
}
|
|
8657
|
+
hasResult() { return false; }
|
|
8658
|
+
update(tr, conf) {
|
|
8659
|
+
let event = getUserEvent(tr), value = this;
|
|
8660
|
+
if (event)
|
|
8661
|
+
value = value.handleUserEvent(tr, event, conf);
|
|
8662
|
+
else if (tr.docChanged)
|
|
8663
|
+
value = value.handleChange(tr);
|
|
8664
|
+
else if (tr.selection && value.state != 0 /* Inactive */)
|
|
8665
|
+
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
8666
|
+
for (let effect of tr.effects) {
|
|
8667
|
+
if (effect.is(startCompletionEffect))
|
|
8668
|
+
value = new ActiveSource(value.source, 1 /* Pending */, effect.value ? cur(tr.state) : -1);
|
|
8669
|
+
else if (effect.is(closeCompletionEffect))
|
|
8670
|
+
value = new ActiveSource(value.source, 0 /* Inactive */);
|
|
8671
|
+
else if (effect.is(setActiveEffect))
|
|
8672
|
+
for (let active of effect.value)
|
|
8673
|
+
if (active.source == value.source)
|
|
8674
|
+
value = active;
|
|
8675
|
+
}
|
|
8676
|
+
return value;
|
|
8677
|
+
}
|
|
8678
|
+
handleUserEvent(tr, type, conf) {
|
|
8679
|
+
return type == "delete" || !conf.activateOnTyping ? this.map(tr.changes) : new ActiveSource(this.source, 1 /* Pending */);
|
|
8680
|
+
}
|
|
8681
|
+
handleChange(tr) {
|
|
8682
|
+
return tr.changes.touchesRange(cur(tr.startState)) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
8683
|
+
}
|
|
8684
|
+
map(changes) {
|
|
8685
|
+
return changes.empty || this.explicitPos < 0 ? this : new ActiveSource(this.source, this.state, changes.mapPos(this.explicitPos));
|
|
8686
|
+
}
|
|
8687
|
+
}
|
|
8688
|
+
class ActiveResult extends ActiveSource {
|
|
8689
|
+
constructor(source, explicitPos, result, from, to) {
|
|
8690
|
+
super(source, 2 /* Result */, explicitPos);
|
|
8691
|
+
this.result = result;
|
|
8692
|
+
this.from = from;
|
|
8693
|
+
this.to = to;
|
|
8694
|
+
}
|
|
8695
|
+
hasResult() { return true; }
|
|
8696
|
+
handleUserEvent(tr, type, conf) {
|
|
8697
|
+
var _a;
|
|
8698
|
+
let from = tr.changes.mapPos(this.from), to = tr.changes.mapPos(this.to, 1);
|
|
8699
|
+
let pos = cur(tr.state);
|
|
8700
|
+
if ((this.explicitPos < 0 ? pos <= from : pos < this.from) ||
|
|
8701
|
+
pos > to ||
|
|
8702
|
+
type == "delete" && cur(tr.startState) == this.from)
|
|
8703
|
+
return new ActiveSource(this.source, type == "input" && conf.activateOnTyping ? 1 /* Pending */ : 0 /* Inactive */);
|
|
8704
|
+
let explicitPos = this.explicitPos < 0 ? -1 : tr.changes.mapPos(this.explicitPos), updated;
|
|
8705
|
+
if (checkValid(this.result.validFor, tr.state, from, to))
|
|
8706
|
+
return new ActiveResult(this.source, explicitPos, this.result, from, to);
|
|
8707
|
+
if (this.result.update &&
|
|
8708
|
+
(updated = this.result.update(this.result, from, to, new CompletionContext(tr.state, pos, explicitPos >= 0))))
|
|
8709
|
+
return new ActiveResult(this.source, explicitPos, updated, updated.from, (_a = updated.to) !== null && _a !== void 0 ? _a : cur(tr.state));
|
|
8710
|
+
return new ActiveSource(this.source, 1 /* Pending */, explicitPos);
|
|
8711
|
+
}
|
|
8712
|
+
handleChange(tr) {
|
|
8713
|
+
return tr.changes.touchesRange(this.from, this.to) ? new ActiveSource(this.source, 0 /* Inactive */) : this.map(tr.changes);
|
|
8714
|
+
}
|
|
8715
|
+
map(mapping) {
|
|
8716
|
+
return mapping.empty ? this :
|
|
8717
|
+
new ActiveResult(this.source, this.explicitPos < 0 ? -1 : mapping.mapPos(this.explicitPos), this.result, mapping.mapPos(this.from), mapping.mapPos(this.to, 1));
|
|
8718
|
+
}
|
|
8719
|
+
}
|
|
8720
|
+
function checkValid(validFor, state, from, to) {
|
|
8721
|
+
if (!validFor)
|
|
8722
|
+
return false;
|
|
8723
|
+
let text = state.sliceDoc(from, to);
|
|
8724
|
+
return typeof validFor == "function" ? validFor(text, from, to, state) : ensureAnchor(validFor, true).test(text);
|
|
8725
|
+
}
|
|
8726
|
+
const startCompletionEffect = /*@__PURE__*/state_.StateEffect.define();
|
|
8727
|
+
const closeCompletionEffect = /*@__PURE__*/state_.StateEffect.define();
|
|
8728
|
+
const setActiveEffect = /*@__PURE__*/state_.StateEffect.define({
|
|
8729
|
+
map(sources, mapping) { return sources.map(s => s.map(mapping)); }
|
|
8730
|
+
});
|
|
8731
|
+
const setSelectedEffect = /*@__PURE__*/state_.StateEffect.define();
|
|
8732
|
+
const completionState = /*@__PURE__*/state_.StateField.define({
|
|
8733
|
+
create() { return CompletionState.start(); },
|
|
8734
|
+
update(value, tr) { return value.update(tr); },
|
|
8735
|
+
provide: f => [
|
|
8736
|
+
view_.showTooltip.from(f, val => val.tooltip),
|
|
8737
|
+
view_.EditorView.contentAttributes.from(f, state => state.attrs)
|
|
8738
|
+
]
|
|
8739
|
+
});
|
|
6601
8740
|
|
|
8741
|
+
const CompletionInteractMargin = 75;
|
|
8742
|
+
/**
|
|
8743
|
+
Returns a command that moves the completion selection forward or
|
|
8744
|
+
backward by the given amount.
|
|
8745
|
+
*/
|
|
8746
|
+
function moveCompletionSelection(forward, by = "option") {
|
|
8747
|
+
return (view) => {
|
|
8748
|
+
let cState = view.state.field(completionState, false);
|
|
8749
|
+
if (!cState || !cState.open || Date.now() - cState.open.timestamp < CompletionInteractMargin)
|
|
8750
|
+
return false;
|
|
8751
|
+
let step = 1, tooltip;
|
|
8752
|
+
if (by == "page" && (tooltip = (0,view_.getTooltip)(view, cState.open.tooltip)))
|
|
8753
|
+
step = Math.max(2, Math.floor(tooltip.dom.offsetHeight /
|
|
8754
|
+
tooltip.dom.querySelector("li").offsetHeight) - 1);
|
|
8755
|
+
let selected = cState.open.selected + step * (forward ? 1 : -1), { length } = cState.open.options;
|
|
8756
|
+
if (selected < 0)
|
|
8757
|
+
selected = by == "page" ? 0 : length - 1;
|
|
8758
|
+
else if (selected >= length)
|
|
8759
|
+
selected = by == "page" ? length - 1 : 0;
|
|
8760
|
+
view.dispatch({ effects: setSelectedEffect.of(selected) });
|
|
8761
|
+
return true;
|
|
8762
|
+
};
|
|
8763
|
+
}
|
|
8764
|
+
/**
|
|
8765
|
+
Accept the current completion.
|
|
8766
|
+
*/
|
|
8767
|
+
const acceptCompletion = (view) => {
|
|
8768
|
+
let cState = view.state.field(completionState, false);
|
|
8769
|
+
if (view.state.readOnly || !cState || !cState.open || Date.now() - cState.open.timestamp < CompletionInteractMargin)
|
|
8770
|
+
return false;
|
|
8771
|
+
applyCompletion(view, cState.open.options[cState.open.selected]);
|
|
8772
|
+
return true;
|
|
8773
|
+
};
|
|
8774
|
+
/**
|
|
8775
|
+
Explicitly start autocompletion.
|
|
8776
|
+
*/
|
|
8777
|
+
const startCompletion = (view) => {
|
|
8778
|
+
let cState = view.state.field(completionState, false);
|
|
8779
|
+
if (!cState)
|
|
8780
|
+
return false;
|
|
8781
|
+
view.dispatch({ effects: startCompletionEffect.of(true) });
|
|
8782
|
+
return true;
|
|
8783
|
+
};
|
|
8784
|
+
/**
|
|
8785
|
+
Close the currently active completion.
|
|
8786
|
+
*/
|
|
8787
|
+
const closeCompletion = (view) => {
|
|
8788
|
+
let cState = view.state.field(completionState, false);
|
|
8789
|
+
if (!cState || !cState.active.some(a => a.state != 0 /* Inactive */))
|
|
8790
|
+
return false;
|
|
8791
|
+
view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
8792
|
+
return true;
|
|
8793
|
+
};
|
|
8794
|
+
class RunningQuery {
|
|
8795
|
+
constructor(active, context) {
|
|
8796
|
+
this.active = active;
|
|
8797
|
+
this.context = context;
|
|
8798
|
+
this.time = Date.now();
|
|
8799
|
+
this.updates = [];
|
|
8800
|
+
// Note that 'undefined' means 'not done yet', whereas 'null' means
|
|
8801
|
+
// 'query returned null'.
|
|
8802
|
+
this.done = undefined;
|
|
8803
|
+
}
|
|
8804
|
+
}
|
|
8805
|
+
const DebounceTime = 50, MaxUpdateCount = 50, MinAbortTime = 1000;
|
|
8806
|
+
const completionPlugin = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
|
|
8807
|
+
constructor(view) {
|
|
8808
|
+
this.view = view;
|
|
8809
|
+
this.debounceUpdate = -1;
|
|
8810
|
+
this.running = [];
|
|
8811
|
+
this.debounceAccept = -1;
|
|
8812
|
+
this.composing = 0 /* None */;
|
|
8813
|
+
for (let active of view.state.field(completionState).active)
|
|
8814
|
+
if (active.state == 1 /* Pending */)
|
|
8815
|
+
this.startQuery(active);
|
|
8816
|
+
}
|
|
8817
|
+
update(update) {
|
|
8818
|
+
let cState = update.state.field(completionState);
|
|
8819
|
+
if (!update.selectionSet && !update.docChanged && update.startState.field(completionState) == cState)
|
|
8820
|
+
return;
|
|
8821
|
+
let doesReset = update.transactions.some(tr => {
|
|
8822
|
+
return (tr.selection || tr.docChanged) && !getUserEvent(tr);
|
|
8823
|
+
});
|
|
8824
|
+
for (let i = 0; i < this.running.length; i++) {
|
|
8825
|
+
let query = this.running[i];
|
|
8826
|
+
if (doesReset ||
|
|
8827
|
+
query.updates.length + update.transactions.length > MaxUpdateCount && Date.now() - query.time > MinAbortTime) {
|
|
8828
|
+
for (let handler of query.context.abortListeners) {
|
|
8829
|
+
try {
|
|
8830
|
+
handler();
|
|
8831
|
+
}
|
|
8832
|
+
catch (e) {
|
|
8833
|
+
(0,view_.logException)(this.view.state, e);
|
|
8834
|
+
}
|
|
8835
|
+
}
|
|
8836
|
+
query.context.abortListeners = null;
|
|
8837
|
+
this.running.splice(i--, 1);
|
|
8838
|
+
}
|
|
8839
|
+
else {
|
|
8840
|
+
query.updates.push(...update.transactions);
|
|
8841
|
+
}
|
|
8842
|
+
}
|
|
8843
|
+
if (this.debounceUpdate > -1)
|
|
8844
|
+
clearTimeout(this.debounceUpdate);
|
|
8845
|
+
this.debounceUpdate = cState.active.some(a => a.state == 1 /* Pending */ && !this.running.some(q => q.active.source == a.source))
|
|
8846
|
+
? setTimeout(() => this.startUpdate(), DebounceTime) : -1;
|
|
8847
|
+
if (this.composing != 0 /* None */)
|
|
8848
|
+
for (let tr of update.transactions) {
|
|
8849
|
+
if (getUserEvent(tr) == "input")
|
|
8850
|
+
this.composing = 2 /* Changed */;
|
|
8851
|
+
else if (this.composing == 2 /* Changed */ && tr.selection)
|
|
8852
|
+
this.composing = 3 /* ChangedAndMoved */;
|
|
8853
|
+
}
|
|
8854
|
+
}
|
|
8855
|
+
startUpdate() {
|
|
8856
|
+
this.debounceUpdate = -1;
|
|
8857
|
+
let { state } = this.view, cState = state.field(completionState);
|
|
8858
|
+
for (let active of cState.active) {
|
|
8859
|
+
if (active.state == 1 /* Pending */ && !this.running.some(r => r.active.source == active.source))
|
|
8860
|
+
this.startQuery(active);
|
|
8861
|
+
}
|
|
8862
|
+
}
|
|
8863
|
+
startQuery(active) {
|
|
8864
|
+
let { state } = this.view, pos = cur(state);
|
|
8865
|
+
let context = new CompletionContext(state, pos, active.explicitPos == pos);
|
|
8866
|
+
let pending = new RunningQuery(active, context);
|
|
8867
|
+
this.running.push(pending);
|
|
8868
|
+
Promise.resolve(active.source(context)).then(result => {
|
|
8869
|
+
if (!pending.context.aborted) {
|
|
8870
|
+
pending.done = result || null;
|
|
8871
|
+
this.scheduleAccept();
|
|
8872
|
+
}
|
|
8873
|
+
}, err => {
|
|
8874
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
8875
|
+
(0,view_.logException)(this.view.state, err);
|
|
8876
|
+
});
|
|
8877
|
+
}
|
|
8878
|
+
scheduleAccept() {
|
|
8879
|
+
if (this.running.every(q => q.done !== undefined))
|
|
8880
|
+
this.accept();
|
|
8881
|
+
else if (this.debounceAccept < 0)
|
|
8882
|
+
this.debounceAccept = setTimeout(() => this.accept(), DebounceTime);
|
|
8883
|
+
}
|
|
8884
|
+
// For each finished query in this.running, try to create a result
|
|
8885
|
+
// or, if appropriate, restart the query.
|
|
8886
|
+
accept() {
|
|
8887
|
+
var _a;
|
|
8888
|
+
if (this.debounceAccept > -1)
|
|
8889
|
+
clearTimeout(this.debounceAccept);
|
|
8890
|
+
this.debounceAccept = -1;
|
|
8891
|
+
let updated = [];
|
|
8892
|
+
let conf = this.view.state.facet(completionConfig);
|
|
8893
|
+
for (let i = 0; i < this.running.length; i++) {
|
|
8894
|
+
let query = this.running[i];
|
|
8895
|
+
if (query.done === undefined)
|
|
8896
|
+
continue;
|
|
8897
|
+
this.running.splice(i--, 1);
|
|
8898
|
+
if (query.done) {
|
|
8899
|
+
let active = new ActiveResult(query.active.source, query.active.explicitPos, query.done, query.done.from, (_a = query.done.to) !== null && _a !== void 0 ? _a : cur(query.updates.length ? query.updates[0].startState : this.view.state));
|
|
8900
|
+
// Replay the transactions that happened since the start of
|
|
8901
|
+
// the request and see if that preserves the result
|
|
8902
|
+
for (let tr of query.updates)
|
|
8903
|
+
active = active.update(tr, conf);
|
|
8904
|
+
if (active.hasResult()) {
|
|
8905
|
+
updated.push(active);
|
|
8906
|
+
continue;
|
|
8907
|
+
}
|
|
8908
|
+
}
|
|
8909
|
+
let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source);
|
|
8910
|
+
if (current && current.state == 1 /* Pending */) {
|
|
8911
|
+
if (query.done == null) {
|
|
8912
|
+
// Explicitly failed. Should clear the pending status if it
|
|
8913
|
+
// hasn't been re-set in the meantime.
|
|
8914
|
+
let active = new ActiveSource(query.active.source, 0 /* Inactive */);
|
|
8915
|
+
for (let tr of query.updates)
|
|
8916
|
+
active = active.update(tr, conf);
|
|
8917
|
+
if (active.state != 1 /* Pending */)
|
|
8918
|
+
updated.push(active);
|
|
8919
|
+
}
|
|
8920
|
+
else {
|
|
8921
|
+
// Cleared by subsequent transactions. Restart.
|
|
8922
|
+
this.startQuery(current);
|
|
8923
|
+
}
|
|
8924
|
+
}
|
|
8925
|
+
}
|
|
8926
|
+
if (updated.length)
|
|
8927
|
+
this.view.dispatch({ effects: setActiveEffect.of(updated) });
|
|
8928
|
+
}
|
|
8929
|
+
}, {
|
|
8930
|
+
eventHandlers: {
|
|
8931
|
+
blur() {
|
|
8932
|
+
let state = this.view.state.field(completionState, false);
|
|
8933
|
+
if (state && state.tooltip && this.view.state.facet(completionConfig).closeOnBlur)
|
|
8934
|
+
this.view.dispatch({ effects: closeCompletionEffect.of(null) });
|
|
8935
|
+
},
|
|
8936
|
+
compositionstart() {
|
|
8937
|
+
this.composing = 1 /* Started */;
|
|
8938
|
+
},
|
|
8939
|
+
compositionend() {
|
|
8940
|
+
if (this.composing == 3 /* ChangedAndMoved */) {
|
|
8941
|
+
// Safari fires compositionend events synchronously, possibly
|
|
8942
|
+
// from inside an update, so dispatch asynchronously to avoid reentrancy
|
|
8943
|
+
setTimeout(() => this.view.dispatch({ effects: startCompletionEffect.of(false) }), 20);
|
|
8944
|
+
}
|
|
8945
|
+
this.composing = 0 /* None */;
|
|
8946
|
+
}
|
|
8947
|
+
}
|
|
8948
|
+
});
|
|
6602
8949
|
|
|
6603
|
-
|
|
8950
|
+
const autocomplete_dist_baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({
|
|
8951
|
+
".cm-tooltip.cm-tooltip-autocomplete": {
|
|
8952
|
+
"& > ul": {
|
|
8953
|
+
fontFamily: "monospace",
|
|
8954
|
+
whiteSpace: "nowrap",
|
|
8955
|
+
overflow: "hidden auto",
|
|
8956
|
+
maxWidth_fallback: "700px",
|
|
8957
|
+
maxWidth: "min(700px, 95vw)",
|
|
8958
|
+
minWidth: "250px",
|
|
8959
|
+
maxHeight: "10em",
|
|
8960
|
+
listStyle: "none",
|
|
8961
|
+
margin: 0,
|
|
8962
|
+
padding: 0,
|
|
8963
|
+
"& > li": {
|
|
8964
|
+
overflowX: "hidden",
|
|
8965
|
+
textOverflow: "ellipsis",
|
|
8966
|
+
cursor: "pointer",
|
|
8967
|
+
padding: "1px 3px",
|
|
8968
|
+
lineHeight: 1.2
|
|
8969
|
+
},
|
|
8970
|
+
}
|
|
8971
|
+
},
|
|
8972
|
+
"&light .cm-tooltip-autocomplete ul li[aria-selected]": {
|
|
8973
|
+
background: "#17c",
|
|
8974
|
+
color: "white",
|
|
8975
|
+
},
|
|
8976
|
+
"&dark .cm-tooltip-autocomplete ul li[aria-selected]": {
|
|
8977
|
+
background: "#347",
|
|
8978
|
+
color: "white",
|
|
8979
|
+
},
|
|
8980
|
+
".cm-completionListIncompleteTop:before, .cm-completionListIncompleteBottom:after": {
|
|
8981
|
+
content: '"···"',
|
|
8982
|
+
opacity: 0.5,
|
|
8983
|
+
display: "block",
|
|
8984
|
+
textAlign: "center"
|
|
8985
|
+
},
|
|
8986
|
+
".cm-tooltip.cm-completionInfo": {
|
|
8987
|
+
position: "absolute",
|
|
8988
|
+
padding: "3px 9px",
|
|
8989
|
+
width: "max-content",
|
|
8990
|
+
maxWidth: "300px",
|
|
8991
|
+
},
|
|
8992
|
+
".cm-completionInfo.cm-completionInfo-left": { right: "100%" },
|
|
8993
|
+
".cm-completionInfo.cm-completionInfo-right": { left: "100%" },
|
|
8994
|
+
"&light .cm-snippetField": { backgroundColor: "#00000022" },
|
|
8995
|
+
"&dark .cm-snippetField": { backgroundColor: "#ffffff22" },
|
|
8996
|
+
".cm-snippetFieldPosition": {
|
|
8997
|
+
verticalAlign: "text-top",
|
|
8998
|
+
width: 0,
|
|
8999
|
+
height: "1.15em",
|
|
9000
|
+
margin: "0 -0.7px -.7em",
|
|
9001
|
+
borderLeft: "1.4px dotted #888"
|
|
9002
|
+
},
|
|
9003
|
+
".cm-completionMatchedText": {
|
|
9004
|
+
textDecoration: "underline"
|
|
9005
|
+
},
|
|
9006
|
+
".cm-completionDetail": {
|
|
9007
|
+
marginLeft: "0.5em",
|
|
9008
|
+
fontStyle: "italic"
|
|
9009
|
+
},
|
|
9010
|
+
".cm-completionIcon": {
|
|
9011
|
+
fontSize: "90%",
|
|
9012
|
+
width: ".8em",
|
|
9013
|
+
display: "inline-block",
|
|
9014
|
+
textAlign: "center",
|
|
9015
|
+
paddingRight: ".6em",
|
|
9016
|
+
opacity: "0.6"
|
|
9017
|
+
},
|
|
9018
|
+
".cm-completionIcon-function, .cm-completionIcon-method": {
|
|
9019
|
+
"&:after": { content: "'ƒ'" }
|
|
9020
|
+
},
|
|
9021
|
+
".cm-completionIcon-class": {
|
|
9022
|
+
"&:after": { content: "'○'" }
|
|
9023
|
+
},
|
|
9024
|
+
".cm-completionIcon-interface": {
|
|
9025
|
+
"&:after": { content: "'◌'" }
|
|
9026
|
+
},
|
|
9027
|
+
".cm-completionIcon-variable": {
|
|
9028
|
+
"&:after": { content: "'𝑥'" }
|
|
9029
|
+
},
|
|
9030
|
+
".cm-completionIcon-constant": {
|
|
9031
|
+
"&:after": { content: "'𝐶'" }
|
|
9032
|
+
},
|
|
9033
|
+
".cm-completionIcon-type": {
|
|
9034
|
+
"&:after": { content: "'𝑡'" }
|
|
9035
|
+
},
|
|
9036
|
+
".cm-completionIcon-enum": {
|
|
9037
|
+
"&:after": { content: "'∪'" }
|
|
9038
|
+
},
|
|
9039
|
+
".cm-completionIcon-property": {
|
|
9040
|
+
"&:after": { content: "'□'" }
|
|
9041
|
+
},
|
|
9042
|
+
".cm-completionIcon-keyword": {
|
|
9043
|
+
"&:after": { content: "'🔑\uFE0E'" } // Disable emoji rendering
|
|
9044
|
+
},
|
|
9045
|
+
".cm-completionIcon-namespace": {
|
|
9046
|
+
"&:after": { content: "'▢'" }
|
|
9047
|
+
},
|
|
9048
|
+
".cm-completionIcon-text": {
|
|
9049
|
+
"&:after": { content: "'abc'", fontSize: "50%", verticalAlign: "middle" }
|
|
9050
|
+
}
|
|
9051
|
+
});
|
|
6604
9052
|
|
|
6605
|
-
|
|
6606
|
-
|
|
9053
|
+
class FieldPos {
|
|
9054
|
+
constructor(field, line, from, to) {
|
|
9055
|
+
this.field = field;
|
|
9056
|
+
this.line = line;
|
|
9057
|
+
this.from = from;
|
|
9058
|
+
this.to = to;
|
|
9059
|
+
}
|
|
9060
|
+
}
|
|
9061
|
+
class FieldRange {
|
|
9062
|
+
constructor(field, from, to) {
|
|
9063
|
+
this.field = field;
|
|
9064
|
+
this.from = from;
|
|
9065
|
+
this.to = to;
|
|
9066
|
+
}
|
|
9067
|
+
map(changes) {
|
|
9068
|
+
let from = changes.mapPos(this.from, -1, MapMode.TrackDel);
|
|
9069
|
+
let to = changes.mapPos(this.to, 1, MapMode.TrackDel);
|
|
9070
|
+
return from == null || to == null ? null : new FieldRange(this.field, from, to);
|
|
9071
|
+
}
|
|
9072
|
+
}
|
|
9073
|
+
class Snippet {
|
|
9074
|
+
constructor(lines, fieldPositions) {
|
|
9075
|
+
this.lines = lines;
|
|
9076
|
+
this.fieldPositions = fieldPositions;
|
|
9077
|
+
}
|
|
9078
|
+
instantiate(state, pos) {
|
|
9079
|
+
let text = [], lineStart = [pos];
|
|
9080
|
+
let lineObj = state.doc.lineAt(pos), baseIndent = /^\s*/.exec(lineObj.text)[0];
|
|
9081
|
+
for (let line of this.lines) {
|
|
9082
|
+
if (text.length) {
|
|
9083
|
+
let indent = baseIndent, tabs = /^\t*/.exec(line)[0].length;
|
|
9084
|
+
for (let i = 0; i < tabs; i++)
|
|
9085
|
+
indent += state.facet(indentUnit);
|
|
9086
|
+
lineStart.push(pos + indent.length - tabs);
|
|
9087
|
+
line = indent + line.slice(tabs);
|
|
9088
|
+
}
|
|
9089
|
+
text.push(line);
|
|
9090
|
+
pos += line.length + 1;
|
|
9091
|
+
}
|
|
9092
|
+
let ranges = this.fieldPositions.map(pos => new FieldRange(pos.field, lineStart[pos.line] + pos.from, lineStart[pos.line] + pos.to));
|
|
9093
|
+
return { text, ranges };
|
|
9094
|
+
}
|
|
9095
|
+
static parse(template) {
|
|
9096
|
+
let fields = [];
|
|
9097
|
+
let lines = [], positions = [], m;
|
|
9098
|
+
for (let line of template.split(/\r\n?|\n/)) {
|
|
9099
|
+
while (m = /[#$]\{(?:(\d+)(?::([^}]*))?|([^}]*))\}/.exec(line)) {
|
|
9100
|
+
let seq = m[1] ? +m[1] : null, name = m[2] || m[3] || "", found = -1;
|
|
9101
|
+
for (let i = 0; i < fields.length; i++) {
|
|
9102
|
+
if (seq != null ? fields[i].seq == seq : name ? fields[i].name == name : false)
|
|
9103
|
+
found = i;
|
|
9104
|
+
}
|
|
9105
|
+
if (found < 0) {
|
|
9106
|
+
let i = 0;
|
|
9107
|
+
while (i < fields.length && (seq == null || (fields[i].seq != null && fields[i].seq < seq)))
|
|
9108
|
+
i++;
|
|
9109
|
+
fields.splice(i, 0, { seq, name });
|
|
9110
|
+
found = i;
|
|
9111
|
+
for (let pos of positions)
|
|
9112
|
+
if (pos.field >= found)
|
|
9113
|
+
pos.field++;
|
|
9114
|
+
}
|
|
9115
|
+
positions.push(new FieldPos(found, lines.length, m.index, m.index + name.length));
|
|
9116
|
+
line = line.slice(0, m.index) + name + line.slice(m.index + m[0].length);
|
|
9117
|
+
}
|
|
9118
|
+
lines.push(line);
|
|
9119
|
+
}
|
|
9120
|
+
return new Snippet(lines, positions);
|
|
9121
|
+
}
|
|
9122
|
+
}
|
|
9123
|
+
let fieldMarker = /*@__PURE__*/view_.Decoration.widget({ widget: /*@__PURE__*/new class extends view_.WidgetType {
|
|
9124
|
+
toDOM() {
|
|
9125
|
+
let span = document.createElement("span");
|
|
9126
|
+
span.className = "cm-snippetFieldPosition";
|
|
9127
|
+
return span;
|
|
9128
|
+
}
|
|
9129
|
+
ignoreEvent() { return false; }
|
|
9130
|
+
} });
|
|
9131
|
+
let fieldRange = /*@__PURE__*/view_.Decoration.mark({ class: "cm-snippetField" });
|
|
9132
|
+
class ActiveSnippet {
|
|
9133
|
+
constructor(ranges, active) {
|
|
9134
|
+
this.ranges = ranges;
|
|
9135
|
+
this.active = active;
|
|
9136
|
+
this.deco = view_.Decoration.set(ranges.map(r => (r.from == r.to ? fieldMarker : fieldRange).range(r.from, r.to)));
|
|
9137
|
+
}
|
|
9138
|
+
map(changes) {
|
|
9139
|
+
let ranges = [];
|
|
9140
|
+
for (let r of this.ranges) {
|
|
9141
|
+
let mapped = r.map(changes);
|
|
9142
|
+
if (!mapped)
|
|
9143
|
+
return null;
|
|
9144
|
+
ranges.push(mapped);
|
|
9145
|
+
}
|
|
9146
|
+
return new ActiveSnippet(ranges, this.active);
|
|
9147
|
+
}
|
|
9148
|
+
selectionInsideField(sel) {
|
|
9149
|
+
return sel.ranges.every(range => this.ranges.some(r => r.field == this.active && r.from <= range.from && r.to >= range.to));
|
|
9150
|
+
}
|
|
9151
|
+
}
|
|
9152
|
+
const setActive = /*@__PURE__*/state_.StateEffect.define({
|
|
9153
|
+
map(value, changes) { return value && value.map(changes); }
|
|
9154
|
+
});
|
|
9155
|
+
const moveToField = /*@__PURE__*/state_.StateEffect.define();
|
|
9156
|
+
const snippetState = /*@__PURE__*/state_.StateField.define({
|
|
9157
|
+
create() { return null; },
|
|
9158
|
+
update(value, tr) {
|
|
9159
|
+
for (let effect of tr.effects) {
|
|
9160
|
+
if (effect.is(setActive))
|
|
9161
|
+
return effect.value;
|
|
9162
|
+
if (effect.is(moveToField) && value)
|
|
9163
|
+
return new ActiveSnippet(value.ranges, effect.value);
|
|
9164
|
+
}
|
|
9165
|
+
if (value && tr.docChanged)
|
|
9166
|
+
value = value.map(tr.changes);
|
|
9167
|
+
if (value && tr.selection && !value.selectionInsideField(tr.selection))
|
|
9168
|
+
value = null;
|
|
9169
|
+
return value;
|
|
9170
|
+
},
|
|
9171
|
+
provide: f => view_.EditorView.decorations.from(f, val => val ? val.deco : view_.Decoration.none)
|
|
9172
|
+
});
|
|
9173
|
+
function fieldSelection(ranges, field) {
|
|
9174
|
+
return state_.EditorSelection.create(ranges.filter(r => r.field == field).map(r => state_.EditorSelection.range(r.from, r.to)));
|
|
9175
|
+
}
|
|
9176
|
+
/**
|
|
9177
|
+
Convert a snippet template to a function that can
|
|
9178
|
+
[apply](https://codemirror.net/6/docs/ref/#autocomplete.Completion.apply) it. Snippets are written
|
|
9179
|
+
using syntax like this:
|
|
6607
9180
|
|
|
6608
|
-
|
|
9181
|
+
"for (let ${index} = 0; ${index} < ${end}; ${index}++) {\n\t${}\n}"
|
|
6609
9182
|
|
|
6610
|
-
|
|
9183
|
+
Each `${}` placeholder (you may also use `#{}`) indicates a field
|
|
9184
|
+
that the user can fill in. Its name, if any, will be the default
|
|
9185
|
+
content for the field.
|
|
6611
9186
|
|
|
6612
|
-
|
|
6613
|
-
|
|
9187
|
+
When the snippet is activated by calling the returned function,
|
|
9188
|
+
the code is inserted at the given position. Newlines in the
|
|
9189
|
+
template are indented by the indentation of the start line, plus
|
|
9190
|
+
one [indent unit](https://codemirror.net/6/docs/ref/#language.indentUnit) per tab character after
|
|
9191
|
+
the newline.
|
|
6614
9192
|
|
|
6615
|
-
|
|
9193
|
+
On activation, (all instances of) the first field are selected.
|
|
9194
|
+
The user can move between fields with Tab and Shift-Tab as long as
|
|
9195
|
+
the fields are active. Moving to the last field or moving the
|
|
9196
|
+
cursor out of the current field deactivates the fields.
|
|
6616
9197
|
|
|
6617
|
-
|
|
9198
|
+
The order of fields defaults to textual order, but you can add
|
|
9199
|
+
numbers to placeholders (`${1}` or `${1:defaultText}`) to provide
|
|
9200
|
+
a custom order.
|
|
9201
|
+
*/
|
|
9202
|
+
function snippet(template) {
|
|
9203
|
+
let snippet = Snippet.parse(template);
|
|
9204
|
+
return (editor, _completion, from, to) => {
|
|
9205
|
+
let { text, ranges } = snippet.instantiate(editor.state, from);
|
|
9206
|
+
let spec = {
|
|
9207
|
+
changes: { from, to, insert: Text.of(text) },
|
|
9208
|
+
scrollIntoView: true
|
|
9209
|
+
};
|
|
9210
|
+
if (ranges.length)
|
|
9211
|
+
spec.selection = fieldSelection(ranges, 0);
|
|
9212
|
+
if (ranges.length > 1) {
|
|
9213
|
+
let active = new ActiveSnippet(ranges, 0);
|
|
9214
|
+
let effects = spec.effects = [setActive.of(active)];
|
|
9215
|
+
if (editor.state.field(snippetState, false) === undefined)
|
|
9216
|
+
effects.push(StateEffect.appendConfig.of([snippetState, addSnippetKeymap, snippetPointerHandler, autocomplete_dist_baseTheme]));
|
|
9217
|
+
}
|
|
9218
|
+
editor.dispatch(editor.state.update(spec));
|
|
9219
|
+
};
|
|
9220
|
+
}
|
|
9221
|
+
function moveField(dir) {
|
|
9222
|
+
return ({ state, dispatch }) => {
|
|
9223
|
+
let active = state.field(snippetState, false);
|
|
9224
|
+
if (!active || dir < 0 && active.active == 0)
|
|
9225
|
+
return false;
|
|
9226
|
+
let next = active.active + dir, last = dir > 0 && !active.ranges.some(r => r.field == next + dir);
|
|
9227
|
+
dispatch(state.update({
|
|
9228
|
+
selection: fieldSelection(active.ranges, next),
|
|
9229
|
+
effects: setActive.of(last ? null : new ActiveSnippet(active.ranges, next))
|
|
9230
|
+
}));
|
|
9231
|
+
return true;
|
|
9232
|
+
};
|
|
9233
|
+
}
|
|
9234
|
+
/**
|
|
9235
|
+
A command that clears the active snippet, if any.
|
|
9236
|
+
*/
|
|
9237
|
+
const clearSnippet = ({ state, dispatch }) => {
|
|
9238
|
+
let active = state.field(snippetState, false);
|
|
9239
|
+
if (!active)
|
|
9240
|
+
return false;
|
|
9241
|
+
dispatch(state.update({ effects: setActive.of(null) }));
|
|
9242
|
+
return true;
|
|
9243
|
+
};
|
|
9244
|
+
/**
|
|
9245
|
+
Move to the next snippet field, if available.
|
|
9246
|
+
*/
|
|
9247
|
+
const nextSnippetField = /*@__PURE__*/moveField(1);
|
|
9248
|
+
/**
|
|
9249
|
+
Move to the previous snippet field, if available.
|
|
9250
|
+
*/
|
|
9251
|
+
const prevSnippetField = /*@__PURE__*/moveField(-1);
|
|
9252
|
+
const defaultSnippetKeymap = [
|
|
9253
|
+
{ key: "Tab", run: nextSnippetField, shift: prevSnippetField },
|
|
9254
|
+
{ key: "Escape", run: clearSnippet }
|
|
9255
|
+
];
|
|
9256
|
+
/**
|
|
9257
|
+
A facet that can be used to configure the key bindings used by
|
|
9258
|
+
snippets. The default binds Tab to
|
|
9259
|
+
[`nextSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.nextSnippetField), Shift-Tab to
|
|
9260
|
+
[`prevSnippetField`](https://codemirror.net/6/docs/ref/#autocomplete.prevSnippetField), and Escape
|
|
9261
|
+
to [`clearSnippet`](https://codemirror.net/6/docs/ref/#autocomplete.clearSnippet).
|
|
9262
|
+
*/
|
|
9263
|
+
const snippetKeymap = /*@__PURE__*/state_.Facet.define({
|
|
9264
|
+
combine(maps) { return maps.length ? maps[0] : defaultSnippetKeymap; }
|
|
9265
|
+
});
|
|
9266
|
+
const addSnippetKeymap = /*@__PURE__*/state_.Prec.highest(/*@__PURE__*/view_.keymap.compute([snippetKeymap], state => state.facet(snippetKeymap)));
|
|
9267
|
+
/**
|
|
9268
|
+
Create a completion from a snippet. Returns an object with the
|
|
9269
|
+
properties from `completion`, plus an `apply` function that
|
|
9270
|
+
applies the snippet.
|
|
9271
|
+
*/
|
|
9272
|
+
function snippetCompletion(template, completion) {
|
|
9273
|
+
return Object.assign(Object.assign({}, completion), { apply: snippet(template) });
|
|
9274
|
+
}
|
|
9275
|
+
const snippetPointerHandler = /*@__PURE__*/view_.EditorView.domEventHandlers({
|
|
9276
|
+
mousedown(event, view) {
|
|
9277
|
+
let active = view.state.field(snippetState, false), pos;
|
|
9278
|
+
if (!active || (pos = view.posAtCoords({ x: event.clientX, y: event.clientY })) == null)
|
|
9279
|
+
return false;
|
|
9280
|
+
let match = active.ranges.find(r => r.from <= pos && r.to >= pos);
|
|
9281
|
+
if (!match || match.field == active.active)
|
|
9282
|
+
return false;
|
|
9283
|
+
view.dispatch({
|
|
9284
|
+
selection: fieldSelection(active.ranges, match.field),
|
|
9285
|
+
effects: setActive.of(active.ranges.some(r => r.field > match.field) ? new ActiveSnippet(active.ranges, match.field) : null)
|
|
9286
|
+
});
|
|
9287
|
+
return true;
|
|
9288
|
+
}
|
|
9289
|
+
});
|
|
6618
9290
|
|
|
6619
|
-
|
|
6620
|
-
|
|
9291
|
+
function wordRE(wordChars) {
|
|
9292
|
+
let escaped = wordChars.replace(/[\\[.+*?(){|^$]/g, "\\$&");
|
|
9293
|
+
try {
|
|
9294
|
+
return new RegExp(`[\\p{Alphabetic}\\p{Number}_${escaped}]+`, "ug");
|
|
9295
|
+
}
|
|
9296
|
+
catch (_a) {
|
|
9297
|
+
return new RegExp(`[\w${escaped}]`, "g");
|
|
9298
|
+
}
|
|
9299
|
+
}
|
|
9300
|
+
function mapRE(re, f) {
|
|
9301
|
+
return new RegExp(f(re.source), re.unicode ? "u" : "");
|
|
9302
|
+
}
|
|
9303
|
+
const wordCaches = /*@__PURE__*/(/* unused pure expression or super */ null && (Object.create(null)));
|
|
9304
|
+
function wordCache(wordChars) {
|
|
9305
|
+
return wordCaches[wordChars] || (wordCaches[wordChars] = new WeakMap);
|
|
9306
|
+
}
|
|
9307
|
+
function storeWords(doc, wordRE, result, seen, ignoreAt) {
|
|
9308
|
+
for (let lines = doc.iterLines(), pos = 0; !lines.next().done;) {
|
|
9309
|
+
let { value } = lines, m;
|
|
9310
|
+
wordRE.lastIndex = 0;
|
|
9311
|
+
while (m = wordRE.exec(value)) {
|
|
9312
|
+
if (!seen[m[0]] && pos + m.index != ignoreAt) {
|
|
9313
|
+
result.push({ type: "text", label: m[0] });
|
|
9314
|
+
seen[m[0]] = true;
|
|
9315
|
+
if (result.length >= 2000 /* MaxList */)
|
|
9316
|
+
return;
|
|
9317
|
+
}
|
|
9318
|
+
}
|
|
9319
|
+
pos += value.length + 1;
|
|
9320
|
+
}
|
|
9321
|
+
}
|
|
9322
|
+
function collectWords(doc, cache, wordRE, to, ignoreAt) {
|
|
9323
|
+
let big = doc.length >= 1000 /* MinCacheLen */;
|
|
9324
|
+
let cached = big && cache.get(doc);
|
|
9325
|
+
if (cached)
|
|
9326
|
+
return cached;
|
|
9327
|
+
let result = [], seen = Object.create(null);
|
|
9328
|
+
if (doc.children) {
|
|
9329
|
+
let pos = 0;
|
|
9330
|
+
for (let ch of doc.children) {
|
|
9331
|
+
if (ch.length >= 1000 /* MinCacheLen */) {
|
|
9332
|
+
for (let c of collectWords(ch, cache, wordRE, to - pos, ignoreAt - pos)) {
|
|
9333
|
+
if (!seen[c.label]) {
|
|
9334
|
+
seen[c.label] = true;
|
|
9335
|
+
result.push(c);
|
|
9336
|
+
}
|
|
9337
|
+
}
|
|
9338
|
+
}
|
|
9339
|
+
else {
|
|
9340
|
+
storeWords(ch, wordRE, result, seen, ignoreAt - pos);
|
|
9341
|
+
}
|
|
9342
|
+
pos += ch.length + 1;
|
|
9343
|
+
}
|
|
9344
|
+
}
|
|
9345
|
+
else {
|
|
9346
|
+
storeWords(doc, wordRE, result, seen, ignoreAt);
|
|
9347
|
+
}
|
|
9348
|
+
if (big && result.length < 2000 /* MaxList */)
|
|
9349
|
+
cache.set(doc, result);
|
|
9350
|
+
return result;
|
|
9351
|
+
}
|
|
9352
|
+
/**
|
|
9353
|
+
A completion source that will scan the document for words (using a
|
|
9354
|
+
[character categorizer](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer)), and
|
|
9355
|
+
return those as completions.
|
|
9356
|
+
*/
|
|
9357
|
+
const completeAnyWord = context => {
|
|
9358
|
+
let wordChars = context.state.languageDataAt("wordChars", context.pos).join("");
|
|
9359
|
+
let re = wordRE(wordChars);
|
|
9360
|
+
let token = context.matchBefore(mapRE(re, s => s + "$"));
|
|
9361
|
+
if (!token && !context.explicit)
|
|
9362
|
+
return null;
|
|
9363
|
+
let from = token ? token.from : context.pos;
|
|
9364
|
+
let options = collectWords(context.state.doc, wordCache(wordChars), re, 50000 /* Range */, from);
|
|
9365
|
+
return { from, options, validFor: mapRE(re, s => "^" + s) };
|
|
9366
|
+
};
|
|
6621
9367
|
|
|
6622
|
-
|
|
9368
|
+
const defaults = {
|
|
9369
|
+
brackets: ["(", "[", "{", "'", '"'],
|
|
9370
|
+
before: ")]}:;>"
|
|
9371
|
+
};
|
|
9372
|
+
const closeBracketEffect = /*@__PURE__*/state_.StateEffect.define({
|
|
9373
|
+
map(value, mapping) {
|
|
9374
|
+
let mapped = mapping.mapPos(value, -1, state_.MapMode.TrackAfter);
|
|
9375
|
+
return mapped == null ? undefined : mapped;
|
|
9376
|
+
}
|
|
9377
|
+
});
|
|
9378
|
+
const skipBracketEffect = /*@__PURE__*/state_.StateEffect.define({
|
|
9379
|
+
map(value, mapping) { return mapping.mapPos(value); }
|
|
9380
|
+
});
|
|
9381
|
+
const closedBracket = /*@__PURE__*/new class extends state_.RangeValue {
|
|
9382
|
+
};
|
|
9383
|
+
closedBracket.startSide = 1;
|
|
9384
|
+
closedBracket.endSide = -1;
|
|
9385
|
+
const bracketState = /*@__PURE__*/state_.StateField.define({
|
|
9386
|
+
create() { return state_.RangeSet.empty; },
|
|
9387
|
+
update(value, tr) {
|
|
9388
|
+
if (tr.selection) {
|
|
9389
|
+
let lineStart = tr.state.doc.lineAt(tr.selection.main.head).from;
|
|
9390
|
+
let prevLineStart = tr.startState.doc.lineAt(tr.startState.selection.main.head).from;
|
|
9391
|
+
if (lineStart != tr.changes.mapPos(prevLineStart, -1))
|
|
9392
|
+
value = state_.RangeSet.empty;
|
|
9393
|
+
}
|
|
9394
|
+
value = value.map(tr.changes);
|
|
9395
|
+
for (let effect of tr.effects) {
|
|
9396
|
+
if (effect.is(closeBracketEffect))
|
|
9397
|
+
value = value.update({ add: [closedBracket.range(effect.value, effect.value + 1)] });
|
|
9398
|
+
else if (effect.is(skipBracketEffect))
|
|
9399
|
+
value = value.update({ filter: from => from != effect.value });
|
|
9400
|
+
}
|
|
9401
|
+
return value;
|
|
9402
|
+
}
|
|
9403
|
+
});
|
|
9404
|
+
/**
|
|
9405
|
+
Extension to enable bracket-closing behavior. When a closeable
|
|
9406
|
+
bracket is typed, its closing bracket is immediately inserted
|
|
9407
|
+
after the cursor. When closing a bracket directly in front of a
|
|
9408
|
+
closing bracket inserted by the extension, the cursor moves over
|
|
9409
|
+
that bracket.
|
|
9410
|
+
*/
|
|
9411
|
+
function closeBrackets() {
|
|
9412
|
+
return [inputHandler, bracketState];
|
|
9413
|
+
}
|
|
9414
|
+
const definedClosing = "()[]{}<>";
|
|
9415
|
+
function closing(ch) {
|
|
9416
|
+
for (let i = 0; i < definedClosing.length; i += 2)
|
|
9417
|
+
if (definedClosing.charCodeAt(i) == ch)
|
|
9418
|
+
return definedClosing.charAt(i + 1);
|
|
9419
|
+
return (0,state_.fromCodePoint)(ch < 128 ? ch : ch + 1);
|
|
9420
|
+
}
|
|
9421
|
+
function config(state, pos) {
|
|
9422
|
+
return state.languageDataAt("closeBrackets", pos)[0] || defaults;
|
|
9423
|
+
}
|
|
9424
|
+
const android = typeof navigator == "object" && /*@__PURE__*//Android\b/.test(navigator.userAgent);
|
|
9425
|
+
const inputHandler = /*@__PURE__*/view_.EditorView.inputHandler.of((view, from, to, insert) => {
|
|
9426
|
+
if ((android ? view.composing : view.compositionStarted) || view.state.readOnly)
|
|
9427
|
+
return false;
|
|
9428
|
+
let sel = view.state.selection.main;
|
|
9429
|
+
if (insert.length > 2 || insert.length == 2 && (0,state_.codePointSize)((0,state_.codePointAt)(insert, 0)) == 1 ||
|
|
9430
|
+
from != sel.from || to != sel.to)
|
|
9431
|
+
return false;
|
|
9432
|
+
let tr = insertBracket(view.state, insert);
|
|
9433
|
+
if (!tr)
|
|
9434
|
+
return false;
|
|
9435
|
+
view.dispatch(tr);
|
|
9436
|
+
return true;
|
|
9437
|
+
});
|
|
9438
|
+
/**
|
|
9439
|
+
Command that implements deleting a pair of matching brackets when
|
|
9440
|
+
the cursor is between them.
|
|
9441
|
+
*/
|
|
9442
|
+
const deleteBracketPair = ({ state, dispatch }) => {
|
|
9443
|
+
if (state.readOnly)
|
|
9444
|
+
return false;
|
|
9445
|
+
let conf = config(state, state.selection.main.head);
|
|
9446
|
+
let tokens = conf.brackets || defaults.brackets;
|
|
9447
|
+
let dont = null, changes = state.changeByRange(range => {
|
|
9448
|
+
if (range.empty) {
|
|
9449
|
+
let before = prevChar(state.doc, range.head);
|
|
9450
|
+
for (let token of tokens) {
|
|
9451
|
+
if (token == before && nextChar(state.doc, range.head) == closing((0,state_.codePointAt)(token, 0)))
|
|
9452
|
+
return { changes: { from: range.head - token.length, to: range.head + token.length },
|
|
9453
|
+
range: state_.EditorSelection.cursor(range.head - token.length),
|
|
9454
|
+
userEvent: "delete.backward" };
|
|
9455
|
+
}
|
|
9456
|
+
}
|
|
9457
|
+
return { range: dont = range };
|
|
9458
|
+
});
|
|
9459
|
+
if (!dont)
|
|
9460
|
+
dispatch(state.update(changes, { scrollIntoView: true }));
|
|
9461
|
+
return !dont;
|
|
9462
|
+
};
|
|
9463
|
+
/**
|
|
9464
|
+
Close-brackets related key bindings. Binds Backspace to
|
|
9465
|
+
[`deleteBracketPair`](https://codemirror.net/6/docs/ref/#autocomplete.deleteBracketPair).
|
|
9466
|
+
*/
|
|
9467
|
+
const closeBracketsKeymap = [
|
|
9468
|
+
{ key: "Backspace", run: deleteBracketPair }
|
|
9469
|
+
];
|
|
9470
|
+
/**
|
|
9471
|
+
Implements the extension's behavior on text insertion. If the
|
|
9472
|
+
given string counts as a bracket in the language around the
|
|
9473
|
+
selection, and replacing the selection with it requires custom
|
|
9474
|
+
behavior (inserting a closing version or skipping past a
|
|
9475
|
+
previously-closed bracket), this function returns a transaction
|
|
9476
|
+
representing that custom behavior. (You only need this if you want
|
|
9477
|
+
to programmatically insert brackets—the
|
|
9478
|
+
[`closeBrackets`](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets) extension will
|
|
9479
|
+
take care of running this for user input.)
|
|
9480
|
+
*/
|
|
9481
|
+
function insertBracket(state, bracket) {
|
|
9482
|
+
let conf = config(state, state.selection.main.head);
|
|
9483
|
+
let tokens = conf.brackets || defaults.brackets;
|
|
9484
|
+
for (let tok of tokens) {
|
|
9485
|
+
let closed = closing((0,state_.codePointAt)(tok, 0));
|
|
9486
|
+
if (bracket == tok)
|
|
9487
|
+
return closed == tok ? handleSame(state, tok, tokens.indexOf(tok + tok + tok) > -1)
|
|
9488
|
+
: handleOpen(state, tok, closed, conf.before || defaults.before);
|
|
9489
|
+
if (bracket == closed && closedBracketAt(state, state.selection.main.from))
|
|
9490
|
+
return handleClose(state, tok, closed);
|
|
9491
|
+
}
|
|
9492
|
+
return null;
|
|
9493
|
+
}
|
|
9494
|
+
function closedBracketAt(state, pos) {
|
|
9495
|
+
let found = false;
|
|
9496
|
+
state.field(bracketState).between(0, state.doc.length, from => {
|
|
9497
|
+
if (from == pos)
|
|
9498
|
+
found = true;
|
|
9499
|
+
});
|
|
9500
|
+
return found;
|
|
9501
|
+
}
|
|
9502
|
+
function nextChar(doc, pos) {
|
|
9503
|
+
let next = doc.sliceString(pos, pos + 2);
|
|
9504
|
+
return next.slice(0, (0,state_.codePointSize)((0,state_.codePointAt)(next, 0)));
|
|
9505
|
+
}
|
|
9506
|
+
function prevChar(doc, pos) {
|
|
9507
|
+
let prev = doc.sliceString(pos - 2, pos);
|
|
9508
|
+
return (0,state_.codePointSize)((0,state_.codePointAt)(prev, 0)) == prev.length ? prev : prev.slice(1);
|
|
9509
|
+
}
|
|
9510
|
+
function handleOpen(state, open, close, closeBefore) {
|
|
9511
|
+
let dont = null, changes = state.changeByRange(range => {
|
|
9512
|
+
if (!range.empty)
|
|
9513
|
+
return { changes: [{ insert: open, from: range.from }, { insert: close, from: range.to }],
|
|
9514
|
+
effects: closeBracketEffect.of(range.to + open.length),
|
|
9515
|
+
range: state_.EditorSelection.range(range.anchor + open.length, range.head + open.length) };
|
|
9516
|
+
let next = nextChar(state.doc, range.head);
|
|
9517
|
+
if (!next || /\s/.test(next) || closeBefore.indexOf(next) > -1)
|
|
9518
|
+
return { changes: { insert: open + close, from: range.head },
|
|
9519
|
+
effects: closeBracketEffect.of(range.head + open.length),
|
|
9520
|
+
range: state_.EditorSelection.cursor(range.head + open.length) };
|
|
9521
|
+
return { range: dont = range };
|
|
9522
|
+
});
|
|
9523
|
+
return dont ? null : state.update(changes, {
|
|
9524
|
+
scrollIntoView: true,
|
|
9525
|
+
userEvent: "input.type"
|
|
9526
|
+
});
|
|
9527
|
+
}
|
|
9528
|
+
function handleClose(state, _open, close) {
|
|
9529
|
+
let dont = null, moved = state.selection.ranges.map(range => {
|
|
9530
|
+
if (range.empty && nextChar(state.doc, range.head) == close)
|
|
9531
|
+
return state_.EditorSelection.cursor(range.head + close.length);
|
|
9532
|
+
return dont = range;
|
|
9533
|
+
});
|
|
9534
|
+
return dont ? null : state.update({
|
|
9535
|
+
selection: state_.EditorSelection.create(moved, state.selection.mainIndex),
|
|
9536
|
+
scrollIntoView: true,
|
|
9537
|
+
effects: state.selection.ranges.map(({ from }) => skipBracketEffect.of(from))
|
|
9538
|
+
});
|
|
9539
|
+
}
|
|
9540
|
+
// Handles cases where the open and close token are the same, and
|
|
9541
|
+
// possibly triple quotes (as in `"""abc"""`-style quoting).
|
|
9542
|
+
function handleSame(state, token, allowTriple) {
|
|
9543
|
+
let dont = null, changes = state.changeByRange(range => {
|
|
9544
|
+
if (!range.empty)
|
|
9545
|
+
return { changes: [{ insert: token, from: range.from }, { insert: token, from: range.to }],
|
|
9546
|
+
effects: closeBracketEffect.of(range.to + token.length),
|
|
9547
|
+
range: state_.EditorSelection.range(range.anchor + token.length, range.head + token.length) };
|
|
9548
|
+
let pos = range.head, next = nextChar(state.doc, pos);
|
|
9549
|
+
if (next == token) {
|
|
9550
|
+
if (nodeStart(state, pos)) {
|
|
9551
|
+
return { changes: { insert: token + token, from: pos },
|
|
9552
|
+
effects: closeBracketEffect.of(pos + token.length),
|
|
9553
|
+
range: state_.EditorSelection.cursor(pos + token.length) };
|
|
9554
|
+
}
|
|
9555
|
+
else if (closedBracketAt(state, pos)) {
|
|
9556
|
+
let isTriple = allowTriple && state.sliceDoc(pos, pos + token.length * 3) == token + token + token;
|
|
9557
|
+
return { range: state_.EditorSelection.cursor(pos + token.length * (isTriple ? 3 : 1)),
|
|
9558
|
+
effects: skipBracketEffect.of(pos) };
|
|
9559
|
+
}
|
|
9560
|
+
}
|
|
9561
|
+
else if (allowTriple && state.sliceDoc(pos - 2 * token.length, pos) == token + token &&
|
|
9562
|
+
nodeStart(state, pos - 2 * token.length)) {
|
|
9563
|
+
return { changes: { insert: token + token + token + token, from: pos },
|
|
9564
|
+
effects: closeBracketEffect.of(pos + token.length),
|
|
9565
|
+
range: state_.EditorSelection.cursor(pos + token.length) };
|
|
9566
|
+
}
|
|
9567
|
+
else if (state.charCategorizer(pos)(next) != state_.CharCategory.Word) {
|
|
9568
|
+
let prev = state.sliceDoc(pos - 1, pos);
|
|
9569
|
+
if (prev != token && state.charCategorizer(pos)(prev) != state_.CharCategory.Word && !probablyInString(state, pos, token))
|
|
9570
|
+
return { changes: { insert: token + token, from: pos },
|
|
9571
|
+
effects: closeBracketEffect.of(pos + token.length),
|
|
9572
|
+
range: state_.EditorSelection.cursor(pos + token.length) };
|
|
9573
|
+
}
|
|
9574
|
+
return { range: dont = range };
|
|
9575
|
+
});
|
|
9576
|
+
return dont ? null : state.update(changes, {
|
|
9577
|
+
scrollIntoView: true,
|
|
9578
|
+
userEvent: "input.type"
|
|
9579
|
+
});
|
|
9580
|
+
}
|
|
9581
|
+
function nodeStart(state, pos) {
|
|
9582
|
+
let tree = dist_syntaxTree(state).resolveInner(pos + 1);
|
|
9583
|
+
return tree.parent && tree.from == pos;
|
|
9584
|
+
}
|
|
9585
|
+
function probablyInString(state, pos, quoteToken) {
|
|
9586
|
+
let node = dist_syntaxTree(state).resolveInner(pos, -1);
|
|
9587
|
+
for (let i = 0; i < 5; i++) {
|
|
9588
|
+
if (state.sliceDoc(node.from, node.from + quoteToken.length) == quoteToken)
|
|
9589
|
+
return true;
|
|
9590
|
+
let parent = node.to == pos && node.parent;
|
|
9591
|
+
if (!parent)
|
|
9592
|
+
break;
|
|
9593
|
+
node = parent;
|
|
9594
|
+
}
|
|
9595
|
+
return false;
|
|
9596
|
+
}
|
|
6623
9597
|
|
|
6624
|
-
|
|
9598
|
+
/**
|
|
9599
|
+
Returns an extension that enables autocompletion.
|
|
9600
|
+
*/
|
|
9601
|
+
function autocompletion(config = {}) {
|
|
9602
|
+
return [
|
|
9603
|
+
completionState,
|
|
9604
|
+
completionConfig.of(config),
|
|
9605
|
+
completionPlugin,
|
|
9606
|
+
completionKeymapExt,
|
|
9607
|
+
autocomplete_dist_baseTheme
|
|
9608
|
+
];
|
|
9609
|
+
}
|
|
9610
|
+
/**
|
|
9611
|
+
Basic keybindings for autocompletion.
|
|
6625
9612
|
|
|
6626
|
-
|
|
6627
|
-
|
|
9613
|
+
- Ctrl-Space: [`startCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.startCompletion)
|
|
9614
|
+
- Escape: [`closeCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.closeCompletion)
|
|
9615
|
+
- ArrowDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true)`
|
|
9616
|
+
- ArrowUp: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(false)`
|
|
9617
|
+
- PageDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true, "page")`
|
|
9618
|
+
- PageDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true, "page")`
|
|
9619
|
+
- Enter: [`acceptCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.acceptCompletion)
|
|
9620
|
+
*/
|
|
9621
|
+
const completionKeymap = [
|
|
9622
|
+
{ key: "Ctrl-Space", run: startCompletion },
|
|
9623
|
+
{ key: "Escape", run: closeCompletion },
|
|
9624
|
+
{ key: "ArrowDown", run: /*@__PURE__*/moveCompletionSelection(true) },
|
|
9625
|
+
{ key: "ArrowUp", run: /*@__PURE__*/moveCompletionSelection(false) },
|
|
9626
|
+
{ key: "PageDown", run: /*@__PURE__*/moveCompletionSelection(true, "page") },
|
|
9627
|
+
{ key: "PageUp", run: /*@__PURE__*/moveCompletionSelection(false, "page") },
|
|
9628
|
+
{ key: "Enter", run: acceptCompletion }
|
|
9629
|
+
];
|
|
9630
|
+
const completionKeymapExt = /*@__PURE__*/state_.Prec.highest(/*@__PURE__*/view_.keymap.computeN([completionConfig], state => state.facet(completionConfig).defaultKeymap ? [completionKeymap] : []));
|
|
9631
|
+
/**
|
|
9632
|
+
Get the current completion status. When completions are available,
|
|
9633
|
+
this will return `"active"`. When completions are pending (in the
|
|
9634
|
+
process of being queried), this returns `"pending"`. Otherwise, it
|
|
9635
|
+
returns `null`.
|
|
9636
|
+
*/
|
|
9637
|
+
function completionStatus(state) {
|
|
9638
|
+
let cState = state.field(completionState, false);
|
|
9639
|
+
return cState && cState.active.some(a => a.state == 1 /* Pending */) ? "pending"
|
|
9640
|
+
: cState && cState.active.some(a => a.state != 0 /* Inactive */) ? "active" : null;
|
|
9641
|
+
}
|
|
9642
|
+
const completionArrayCache = /*@__PURE__*/new WeakMap;
|
|
9643
|
+
/**
|
|
9644
|
+
Returns the available completions as an array.
|
|
9645
|
+
*/
|
|
9646
|
+
function currentCompletions(state) {
|
|
9647
|
+
var _a;
|
|
9648
|
+
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
|
9649
|
+
if (!open)
|
|
9650
|
+
return [];
|
|
9651
|
+
let completions = completionArrayCache.get(open.options);
|
|
9652
|
+
if (!completions)
|
|
9653
|
+
completionArrayCache.set(open.options, completions = open.options.map(o => o.completion));
|
|
9654
|
+
return completions;
|
|
9655
|
+
}
|
|
9656
|
+
/**
|
|
9657
|
+
Return the currently selected completion, if any.
|
|
9658
|
+
*/
|
|
9659
|
+
function selectedCompletion(state) {
|
|
9660
|
+
var _a;
|
|
9661
|
+
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
|
9662
|
+
return open ? open.options[open.selected].completion : null;
|
|
9663
|
+
}
|
|
9664
|
+
/**
|
|
9665
|
+
Returns the currently selected position in the active completion
|
|
9666
|
+
list, or null if no completions are active.
|
|
9667
|
+
*/
|
|
9668
|
+
function selectedCompletionIndex(state) {
|
|
9669
|
+
var _a;
|
|
9670
|
+
let open = (_a = state.field(completionState, false)) === null || _a === void 0 ? void 0 : _a.open;
|
|
9671
|
+
return open ? open.selected : null;
|
|
9672
|
+
}
|
|
9673
|
+
/**
|
|
9674
|
+
Create an effect that can be attached to a transaction to change
|
|
9675
|
+
the currently selected completion.
|
|
9676
|
+
*/
|
|
9677
|
+
function setSelectedCompletion(index) {
|
|
9678
|
+
return setSelectedEffect.of(index);
|
|
9679
|
+
}
|
|
6628
9680
|
|
|
6629
|
-
module.exports = __WEBPACK_EXTERNAL_MODULE__362__;
|
|
6630
9681
|
|
|
6631
|
-
/***/ }),
|
|
6632
9682
|
|
|
6633
|
-
|
|
6634
|
-
/***/ ((module) => {
|
|
9683
|
+
;// CONCATENATED MODULE: ./node_modules/@codemirror/lint/dist/index.js
|
|
6635
9684
|
|
|
6636
|
-
module.exports = __WEBPACK_EXTERNAL_MODULE__105__;
|
|
6637
9685
|
|
|
6638
|
-
/***/ }),
|
|
6639
9686
|
|
|
6640
|
-
/***/ 683:
|
|
6641
|
-
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
6642
9687
|
|
|
9688
|
+
class SelectedDiagnostic {
|
|
9689
|
+
constructor(from, to, diagnostic) {
|
|
9690
|
+
this.from = from;
|
|
9691
|
+
this.to = to;
|
|
9692
|
+
this.diagnostic = diagnostic;
|
|
9693
|
+
}
|
|
9694
|
+
}
|
|
9695
|
+
class LintState {
|
|
9696
|
+
constructor(diagnostics, panel, selected) {
|
|
9697
|
+
this.diagnostics = diagnostics;
|
|
9698
|
+
this.panel = panel;
|
|
9699
|
+
this.selected = selected;
|
|
9700
|
+
}
|
|
9701
|
+
static init(diagnostics, panel, state) {
|
|
9702
|
+
// Filter the list of diagnostics for which to create markers
|
|
9703
|
+
let markedDiagnostics = diagnostics;
|
|
9704
|
+
let diagnosticFilter = state.facet(lintConfig).markerFilter;
|
|
9705
|
+
if (diagnosticFilter)
|
|
9706
|
+
markedDiagnostics = diagnosticFilter(markedDiagnostics);
|
|
9707
|
+
let ranges = view_.Decoration.set(markedDiagnostics.map((d) => {
|
|
9708
|
+
// For zero-length ranges or ranges covering only a line break, create a widget
|
|
9709
|
+
return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from)
|
|
9710
|
+
? view_.Decoration.widget({
|
|
9711
|
+
widget: new DiagnosticWidget(d),
|
|
9712
|
+
diagnostic: d
|
|
9713
|
+
}).range(d.from)
|
|
9714
|
+
: view_.Decoration.mark({
|
|
9715
|
+
attributes: { class: "cm-lintRange cm-lintRange-" + d.severity },
|
|
9716
|
+
diagnostic: d
|
|
9717
|
+
}).range(d.from, d.to);
|
|
9718
|
+
}), true);
|
|
9719
|
+
return new LintState(ranges, panel, findDiagnostic(ranges));
|
|
9720
|
+
}
|
|
9721
|
+
}
|
|
9722
|
+
function findDiagnostic(diagnostics, diagnostic = null, after = 0) {
|
|
9723
|
+
let found = null;
|
|
9724
|
+
diagnostics.between(after, 1e9, (from, to, { spec }) => {
|
|
9725
|
+
if (diagnostic && spec.diagnostic != diagnostic)
|
|
9726
|
+
return;
|
|
9727
|
+
found = new SelectedDiagnostic(from, to, spec.diagnostic);
|
|
9728
|
+
return false;
|
|
9729
|
+
});
|
|
9730
|
+
return found;
|
|
9731
|
+
}
|
|
9732
|
+
function hideTooltip(tr, tooltip) {
|
|
9733
|
+
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(tooltip.pos));
|
|
9734
|
+
}
|
|
9735
|
+
function maybeEnableLint(state, effects) {
|
|
9736
|
+
return state.field(lintState, false) ? effects : effects.concat(state_.StateEffect.appendConfig.of([
|
|
9737
|
+
lintState,
|
|
9738
|
+
view_.EditorView.decorations.compute([lintState], state => {
|
|
9739
|
+
let { selected, panel } = state.field(lintState);
|
|
9740
|
+
return !selected || !panel || selected.from == selected.to ? view_.Decoration.none : view_.Decoration.set([
|
|
9741
|
+
activeMark.range(selected.from, selected.to)
|
|
9742
|
+
]);
|
|
9743
|
+
}),
|
|
9744
|
+
(0,view_.hoverTooltip)(lintTooltip, { hideOn: hideTooltip }),
|
|
9745
|
+
lint_dist_baseTheme
|
|
9746
|
+
]));
|
|
9747
|
+
}
|
|
9748
|
+
/**
|
|
9749
|
+
Returns a transaction spec which updates the current set of
|
|
9750
|
+
diagnostics, and enables the lint extension if if wasn't already
|
|
9751
|
+
active.
|
|
9752
|
+
*/
|
|
9753
|
+
function setDiagnostics(state, diagnostics) {
|
|
9754
|
+
return {
|
|
9755
|
+
effects: maybeEnableLint(state, [setDiagnosticsEffect.of(diagnostics)])
|
|
9756
|
+
};
|
|
9757
|
+
}
|
|
9758
|
+
/**
|
|
9759
|
+
The state effect that updates the set of active diagnostics. Can
|
|
9760
|
+
be useful when writing an extension that needs to track these.
|
|
9761
|
+
*/
|
|
9762
|
+
const setDiagnosticsEffect = /*@__PURE__*/state_.StateEffect.define();
|
|
9763
|
+
const dist_togglePanel = /*@__PURE__*/state_.StateEffect.define();
|
|
9764
|
+
const movePanelSelection = /*@__PURE__*/state_.StateEffect.define();
|
|
9765
|
+
const lintState = /*@__PURE__*/state_.StateField.define({
|
|
9766
|
+
create() {
|
|
9767
|
+
return new LintState(view_.Decoration.none, null, null);
|
|
9768
|
+
},
|
|
9769
|
+
update(value, tr) {
|
|
9770
|
+
if (tr.docChanged) {
|
|
9771
|
+
let mapped = value.diagnostics.map(tr.changes), selected = null;
|
|
9772
|
+
if (value.selected) {
|
|
9773
|
+
let selPos = tr.changes.mapPos(value.selected.from, 1);
|
|
9774
|
+
selected = findDiagnostic(mapped, value.selected.diagnostic, selPos) || findDiagnostic(mapped, null, selPos);
|
|
9775
|
+
}
|
|
9776
|
+
value = new LintState(mapped, value.panel, selected);
|
|
9777
|
+
}
|
|
9778
|
+
for (let effect of tr.effects) {
|
|
9779
|
+
if (effect.is(setDiagnosticsEffect)) {
|
|
9780
|
+
value = LintState.init(effect.value, value.panel, tr.state);
|
|
9781
|
+
}
|
|
9782
|
+
else if (effect.is(dist_togglePanel)) {
|
|
9783
|
+
value = new LintState(value.diagnostics, effect.value ? LintPanel.open : null, value.selected);
|
|
9784
|
+
}
|
|
9785
|
+
else if (effect.is(movePanelSelection)) {
|
|
9786
|
+
value = new LintState(value.diagnostics, value.panel, effect.value);
|
|
9787
|
+
}
|
|
9788
|
+
}
|
|
9789
|
+
return value;
|
|
9790
|
+
},
|
|
9791
|
+
provide: f => [view_.showPanel.from(f, val => val.panel),
|
|
9792
|
+
view_.EditorView.decorations.from(f, s => s.diagnostics)]
|
|
9793
|
+
});
|
|
9794
|
+
/**
|
|
9795
|
+
Returns the number of active lint diagnostics in the given state.
|
|
9796
|
+
*/
|
|
9797
|
+
function diagnosticCount(state) {
|
|
9798
|
+
let lint = state.field(lintState, false);
|
|
9799
|
+
return lint ? lint.diagnostics.size : 0;
|
|
9800
|
+
}
|
|
9801
|
+
const activeMark = /*@__PURE__*/view_.Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
|
|
9802
|
+
function lintTooltip(view, pos, side) {
|
|
9803
|
+
let { diagnostics } = view.state.field(lintState);
|
|
9804
|
+
let found = [], stackStart = 2e8, stackEnd = 0;
|
|
9805
|
+
diagnostics.between(pos - (side < 0 ? 1 : 0), pos + (side > 0 ? 1 : 0), (from, to, { spec }) => {
|
|
9806
|
+
if (pos >= from && pos <= to &&
|
|
9807
|
+
(from == to || ((pos > from || side > 0) && (pos < to || side < 0)))) {
|
|
9808
|
+
found.push(spec.diagnostic);
|
|
9809
|
+
stackStart = Math.min(from, stackStart);
|
|
9810
|
+
stackEnd = Math.max(to, stackEnd);
|
|
9811
|
+
}
|
|
9812
|
+
});
|
|
9813
|
+
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
|
9814
|
+
if (diagnosticFilter)
|
|
9815
|
+
found = diagnosticFilter(found);
|
|
9816
|
+
if (!found.length)
|
|
9817
|
+
return null;
|
|
9818
|
+
return {
|
|
9819
|
+
pos: stackStart,
|
|
9820
|
+
end: stackEnd,
|
|
9821
|
+
above: view.state.doc.lineAt(stackStart).to < stackEnd,
|
|
9822
|
+
create() {
|
|
9823
|
+
return { dom: diagnosticsTooltip(view, found) };
|
|
9824
|
+
}
|
|
9825
|
+
};
|
|
9826
|
+
}
|
|
9827
|
+
function diagnosticsTooltip(view, diagnostics) {
|
|
9828
|
+
return crelt("ul", { class: "cm-tooltip-lint" }, diagnostics.map(d => renderDiagnostic(view, d, false)));
|
|
9829
|
+
}
|
|
9830
|
+
/**
|
|
9831
|
+
Command to open and focus the lint panel.
|
|
9832
|
+
*/
|
|
9833
|
+
const openLintPanel = (view) => {
|
|
9834
|
+
let field = view.state.field(lintState, false);
|
|
9835
|
+
if (!field || !field.panel)
|
|
9836
|
+
view.dispatch({ effects: maybeEnableLint(view.state, [dist_togglePanel.of(true)]) });
|
|
9837
|
+
let panel = (0,view_.getPanel)(view, LintPanel.open);
|
|
9838
|
+
if (panel)
|
|
9839
|
+
panel.dom.querySelector(".cm-panel-lint ul").focus();
|
|
9840
|
+
return true;
|
|
9841
|
+
};
|
|
9842
|
+
/**
|
|
9843
|
+
Command to close the lint panel, when open.
|
|
9844
|
+
*/
|
|
9845
|
+
const closeLintPanel = (view) => {
|
|
9846
|
+
let field = view.state.field(lintState, false);
|
|
9847
|
+
if (!field || !field.panel)
|
|
9848
|
+
return false;
|
|
9849
|
+
view.dispatch({ effects: dist_togglePanel.of(false) });
|
|
9850
|
+
return true;
|
|
9851
|
+
};
|
|
9852
|
+
/**
|
|
9853
|
+
Move the selection to the next diagnostic.
|
|
9854
|
+
*/
|
|
9855
|
+
const nextDiagnostic = (view) => {
|
|
9856
|
+
let field = view.state.field(lintState, false);
|
|
9857
|
+
if (!field)
|
|
9858
|
+
return false;
|
|
9859
|
+
let sel = view.state.selection.main, next = field.diagnostics.iter(sel.to + 1);
|
|
9860
|
+
if (!next.value) {
|
|
9861
|
+
next = field.diagnostics.iter(0);
|
|
9862
|
+
if (!next.value || next.from == sel.from && next.to == sel.to)
|
|
9863
|
+
return false;
|
|
9864
|
+
}
|
|
9865
|
+
view.dispatch({ selection: { anchor: next.from, head: next.to }, scrollIntoView: true });
|
|
9866
|
+
return true;
|
|
9867
|
+
};
|
|
9868
|
+
/**
|
|
9869
|
+
A set of default key bindings for the lint functionality.
|
|
6643
9870
|
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
9871
|
+
- Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](https://codemirror.net/6/docs/ref/#lint.openLintPanel)
|
|
9872
|
+
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
|
9873
|
+
*/
|
|
9874
|
+
const lintKeymap = [
|
|
9875
|
+
{ key: "Mod-Shift-m", run: openLintPanel },
|
|
9876
|
+
{ key: "F8", run: nextDiagnostic }
|
|
9877
|
+
];
|
|
9878
|
+
const lintPlugin = /*@__PURE__*/view_.ViewPlugin.fromClass(class {
|
|
9879
|
+
constructor(view) {
|
|
9880
|
+
this.view = view;
|
|
9881
|
+
this.timeout = -1;
|
|
9882
|
+
this.set = true;
|
|
9883
|
+
let { delay } = view.state.facet(lintConfig);
|
|
9884
|
+
this.lintTime = Date.now() + delay;
|
|
9885
|
+
this.run = this.run.bind(this);
|
|
9886
|
+
this.timeout = setTimeout(this.run, delay);
|
|
9887
|
+
}
|
|
9888
|
+
run() {
|
|
9889
|
+
let now = Date.now();
|
|
9890
|
+
if (now < this.lintTime - 10) {
|
|
9891
|
+
setTimeout(this.run, this.lintTime - now);
|
|
9892
|
+
}
|
|
9893
|
+
else {
|
|
9894
|
+
this.set = false;
|
|
9895
|
+
let { state } = this.view, { sources } = state.facet(lintConfig);
|
|
9896
|
+
Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
|
|
9897
|
+
let all = annotations.reduce((a, b) => a.concat(b));
|
|
9898
|
+
if (this.view.state.doc == state.doc)
|
|
9899
|
+
this.view.dispatch(setDiagnostics(this.view.state, all));
|
|
9900
|
+
}, error => { (0,view_.logException)(this.view.state, error); });
|
|
9901
|
+
}
|
|
9902
|
+
}
|
|
9903
|
+
update(update) {
|
|
9904
|
+
let config = update.state.facet(lintConfig);
|
|
9905
|
+
if (update.docChanged || config != update.startState.facet(lintConfig)) {
|
|
9906
|
+
this.lintTime = Date.now() + config.delay;
|
|
9907
|
+
if (!this.set) {
|
|
9908
|
+
this.set = true;
|
|
9909
|
+
this.timeout = setTimeout(this.run, config.delay);
|
|
9910
|
+
}
|
|
9911
|
+
}
|
|
9912
|
+
}
|
|
9913
|
+
force() {
|
|
9914
|
+
if (this.set) {
|
|
9915
|
+
this.lintTime = Date.now();
|
|
9916
|
+
this.run();
|
|
9917
|
+
}
|
|
9918
|
+
}
|
|
9919
|
+
destroy() {
|
|
9920
|
+
clearTimeout(this.timeout);
|
|
9921
|
+
}
|
|
9922
|
+
});
|
|
9923
|
+
const lintConfig = /*@__PURE__*/state_.Facet.define({
|
|
9924
|
+
combine(input) {
|
|
9925
|
+
return Object.assign({ sources: input.map(i => i.source) }, (0,state_.combineConfig)(input.map(i => i.config), {
|
|
9926
|
+
delay: 750,
|
|
9927
|
+
markerFilter: null,
|
|
9928
|
+
tooltipFilter: null
|
|
9929
|
+
}));
|
|
9930
|
+
},
|
|
9931
|
+
enables: lintPlugin
|
|
9932
|
+
});
|
|
9933
|
+
/**
|
|
9934
|
+
Given a diagnostic source, this function returns an extension that
|
|
9935
|
+
enables linting with that source. It will be called whenever the
|
|
9936
|
+
editor is idle (after its content changed).
|
|
9937
|
+
*/
|
|
9938
|
+
function linter(source, config = {}) {
|
|
9939
|
+
return lintConfig.of({ source, config });
|
|
9940
|
+
}
|
|
9941
|
+
/**
|
|
9942
|
+
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
|
9943
|
+
editor is idle to run right away.
|
|
9944
|
+
*/
|
|
9945
|
+
function forceLinting(view) {
|
|
9946
|
+
let plugin = view.plugin(lintPlugin);
|
|
9947
|
+
if (plugin)
|
|
9948
|
+
plugin.force();
|
|
9949
|
+
}
|
|
9950
|
+
function assignKeys(actions) {
|
|
9951
|
+
let assigned = [];
|
|
9952
|
+
if (actions)
|
|
9953
|
+
actions: for (let { name } of actions) {
|
|
9954
|
+
for (let i = 0; i < name.length; i++) {
|
|
9955
|
+
let ch = name[i];
|
|
9956
|
+
if (/[a-zA-Z]/.test(ch) && !assigned.some(c => c.toLowerCase() == ch.toLowerCase())) {
|
|
9957
|
+
assigned.push(ch);
|
|
9958
|
+
continue actions;
|
|
9959
|
+
}
|
|
9960
|
+
}
|
|
9961
|
+
assigned.push("");
|
|
9962
|
+
}
|
|
9963
|
+
return assigned;
|
|
9964
|
+
}
|
|
9965
|
+
function renderDiagnostic(view, diagnostic, inPanel) {
|
|
9966
|
+
var _a;
|
|
9967
|
+
let keys = inPanel ? assignKeys(diagnostic.actions) : [];
|
|
9968
|
+
return crelt("li", { class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity }, crelt("span", { class: "cm-diagnosticText" }, diagnostic.renderMessage ? diagnostic.renderMessage() : diagnostic.message), (_a = diagnostic.actions) === null || _a === void 0 ? void 0 : _a.map((action, i) => {
|
|
9969
|
+
let click = (e) => {
|
|
9970
|
+
e.preventDefault();
|
|
9971
|
+
let found = findDiagnostic(view.state.field(lintState).diagnostics, diagnostic);
|
|
9972
|
+
if (found)
|
|
9973
|
+
action.apply(view, found.from, found.to);
|
|
9974
|
+
};
|
|
9975
|
+
let { name } = action, keyIndex = keys[i] ? name.indexOf(keys[i]) : -1;
|
|
9976
|
+
let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),
|
|
9977
|
+
crelt("u", name.slice(keyIndex, keyIndex + 1)),
|
|
9978
|
+
name.slice(keyIndex + 1)];
|
|
9979
|
+
return crelt("button", {
|
|
9980
|
+
type: "button",
|
|
9981
|
+
class: "cm-diagnosticAction",
|
|
9982
|
+
onclick: click,
|
|
9983
|
+
onmousedown: click,
|
|
9984
|
+
"aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`
|
|
9985
|
+
}, nameElt);
|
|
9986
|
+
}), diagnostic.source && crelt("div", { class: "cm-diagnosticSource" }, diagnostic.source));
|
|
9987
|
+
}
|
|
9988
|
+
class DiagnosticWidget extends view_.WidgetType {
|
|
9989
|
+
constructor(diagnostic) {
|
|
9990
|
+
super();
|
|
9991
|
+
this.diagnostic = diagnostic;
|
|
9992
|
+
}
|
|
9993
|
+
eq(other) { return other.diagnostic == this.diagnostic; }
|
|
9994
|
+
toDOM() {
|
|
9995
|
+
return crelt("span", { class: "cm-lintPoint cm-lintPoint-" + this.diagnostic.severity });
|
|
9996
|
+
}
|
|
9997
|
+
}
|
|
9998
|
+
class PanelItem {
|
|
9999
|
+
constructor(view, diagnostic) {
|
|
10000
|
+
this.diagnostic = diagnostic;
|
|
10001
|
+
this.id = "item_" + Math.floor(Math.random() * 0xffffffff).toString(16);
|
|
10002
|
+
this.dom = renderDiagnostic(view, diagnostic, true);
|
|
10003
|
+
this.dom.id = this.id;
|
|
10004
|
+
this.dom.setAttribute("role", "option");
|
|
10005
|
+
}
|
|
10006
|
+
}
|
|
10007
|
+
class LintPanel {
|
|
10008
|
+
constructor(view) {
|
|
10009
|
+
this.view = view;
|
|
10010
|
+
this.items = [];
|
|
10011
|
+
let onkeydown = (event) => {
|
|
10012
|
+
if (event.keyCode == 27) { // Escape
|
|
10013
|
+
closeLintPanel(this.view);
|
|
10014
|
+
this.view.focus();
|
|
10015
|
+
}
|
|
10016
|
+
else if (event.keyCode == 38 || event.keyCode == 33) { // ArrowUp, PageUp
|
|
10017
|
+
this.moveSelection((this.selectedIndex - 1 + this.items.length) % this.items.length);
|
|
10018
|
+
}
|
|
10019
|
+
else if (event.keyCode == 40 || event.keyCode == 34) { // ArrowDown, PageDown
|
|
10020
|
+
this.moveSelection((this.selectedIndex + 1) % this.items.length);
|
|
10021
|
+
}
|
|
10022
|
+
else if (event.keyCode == 36) { // Home
|
|
10023
|
+
this.moveSelection(0);
|
|
10024
|
+
}
|
|
10025
|
+
else if (event.keyCode == 35) { // End
|
|
10026
|
+
this.moveSelection(this.items.length - 1);
|
|
10027
|
+
}
|
|
10028
|
+
else if (event.keyCode == 13) { // Enter
|
|
10029
|
+
this.view.focus();
|
|
10030
|
+
}
|
|
10031
|
+
else if (event.keyCode >= 65 && event.keyCode <= 90 && this.selectedIndex >= 0) { // A-Z
|
|
10032
|
+
let { diagnostic } = this.items[this.selectedIndex], keys = assignKeys(diagnostic.actions);
|
|
10033
|
+
for (let i = 0; i < keys.length; i++)
|
|
10034
|
+
if (keys[i].toUpperCase().charCodeAt(0) == event.keyCode) {
|
|
10035
|
+
let found = findDiagnostic(this.view.state.field(lintState).diagnostics, diagnostic);
|
|
10036
|
+
if (found)
|
|
10037
|
+
diagnostic.actions[i].apply(view, found.from, found.to);
|
|
10038
|
+
}
|
|
10039
|
+
}
|
|
10040
|
+
else {
|
|
10041
|
+
return;
|
|
10042
|
+
}
|
|
10043
|
+
event.preventDefault();
|
|
10044
|
+
};
|
|
10045
|
+
let onclick = (event) => {
|
|
10046
|
+
for (let i = 0; i < this.items.length; i++) {
|
|
10047
|
+
if (this.items[i].dom.contains(event.target))
|
|
10048
|
+
this.moveSelection(i);
|
|
10049
|
+
}
|
|
10050
|
+
};
|
|
10051
|
+
this.list = crelt("ul", {
|
|
10052
|
+
tabIndex: 0,
|
|
10053
|
+
role: "listbox",
|
|
10054
|
+
"aria-label": this.view.state.phrase("Diagnostics"),
|
|
10055
|
+
onkeydown,
|
|
10056
|
+
onclick
|
|
10057
|
+
});
|
|
10058
|
+
this.dom = crelt("div", { class: "cm-panel-lint" }, this.list, crelt("button", {
|
|
10059
|
+
type: "button",
|
|
10060
|
+
name: "close",
|
|
10061
|
+
"aria-label": this.view.state.phrase("close"),
|
|
10062
|
+
onclick: () => closeLintPanel(this.view)
|
|
10063
|
+
}, "×"));
|
|
10064
|
+
this.update();
|
|
10065
|
+
}
|
|
10066
|
+
get selectedIndex() {
|
|
10067
|
+
let selected = this.view.state.field(lintState).selected;
|
|
10068
|
+
if (!selected)
|
|
10069
|
+
return -1;
|
|
10070
|
+
for (let i = 0; i < this.items.length; i++)
|
|
10071
|
+
if (this.items[i].diagnostic == selected.diagnostic)
|
|
10072
|
+
return i;
|
|
10073
|
+
return -1;
|
|
10074
|
+
}
|
|
10075
|
+
update() {
|
|
10076
|
+
let { diagnostics, selected } = this.view.state.field(lintState);
|
|
10077
|
+
let i = 0, needsSync = false, newSelectedItem = null;
|
|
10078
|
+
diagnostics.between(0, this.view.state.doc.length, (_start, _end, { spec }) => {
|
|
10079
|
+
let found = -1, item;
|
|
10080
|
+
for (let j = i; j < this.items.length; j++)
|
|
10081
|
+
if (this.items[j].diagnostic == spec.diagnostic) {
|
|
10082
|
+
found = j;
|
|
10083
|
+
break;
|
|
10084
|
+
}
|
|
10085
|
+
if (found < 0) {
|
|
10086
|
+
item = new PanelItem(this.view, spec.diagnostic);
|
|
10087
|
+
this.items.splice(i, 0, item);
|
|
10088
|
+
needsSync = true;
|
|
10089
|
+
}
|
|
10090
|
+
else {
|
|
10091
|
+
item = this.items[found];
|
|
10092
|
+
if (found > i) {
|
|
10093
|
+
this.items.splice(i, found - i);
|
|
10094
|
+
needsSync = true;
|
|
10095
|
+
}
|
|
10096
|
+
}
|
|
10097
|
+
if (selected && item.diagnostic == selected.diagnostic) {
|
|
10098
|
+
if (!item.dom.hasAttribute("aria-selected")) {
|
|
10099
|
+
item.dom.setAttribute("aria-selected", "true");
|
|
10100
|
+
newSelectedItem = item;
|
|
10101
|
+
}
|
|
10102
|
+
}
|
|
10103
|
+
else if (item.dom.hasAttribute("aria-selected")) {
|
|
10104
|
+
item.dom.removeAttribute("aria-selected");
|
|
10105
|
+
}
|
|
10106
|
+
i++;
|
|
10107
|
+
});
|
|
10108
|
+
while (i < this.items.length && !(this.items.length == 1 && this.items[0].diagnostic.from < 0)) {
|
|
10109
|
+
needsSync = true;
|
|
10110
|
+
this.items.pop();
|
|
10111
|
+
}
|
|
10112
|
+
if (this.items.length == 0) {
|
|
10113
|
+
this.items.push(new PanelItem(this.view, {
|
|
10114
|
+
from: -1, to: -1,
|
|
10115
|
+
severity: "info",
|
|
10116
|
+
message: this.view.state.phrase("No diagnostics")
|
|
10117
|
+
}));
|
|
10118
|
+
needsSync = true;
|
|
10119
|
+
}
|
|
10120
|
+
if (newSelectedItem) {
|
|
10121
|
+
this.list.setAttribute("aria-activedescendant", newSelectedItem.id);
|
|
10122
|
+
this.view.requestMeasure({
|
|
10123
|
+
key: this,
|
|
10124
|
+
read: () => ({ sel: newSelectedItem.dom.getBoundingClientRect(), panel: this.list.getBoundingClientRect() }),
|
|
10125
|
+
write: ({ sel, panel }) => {
|
|
10126
|
+
if (sel.top < panel.top)
|
|
10127
|
+
this.list.scrollTop -= panel.top - sel.top;
|
|
10128
|
+
else if (sel.bottom > panel.bottom)
|
|
10129
|
+
this.list.scrollTop += sel.bottom - panel.bottom;
|
|
10130
|
+
}
|
|
10131
|
+
});
|
|
10132
|
+
}
|
|
10133
|
+
else if (this.selectedIndex < 0) {
|
|
10134
|
+
this.list.removeAttribute("aria-activedescendant");
|
|
10135
|
+
}
|
|
10136
|
+
if (needsSync)
|
|
10137
|
+
this.sync();
|
|
10138
|
+
}
|
|
10139
|
+
sync() {
|
|
10140
|
+
let domPos = this.list.firstChild;
|
|
10141
|
+
function rm() {
|
|
10142
|
+
let prev = domPos;
|
|
10143
|
+
domPos = prev.nextSibling;
|
|
10144
|
+
prev.remove();
|
|
10145
|
+
}
|
|
10146
|
+
for (let item of this.items) {
|
|
10147
|
+
if (item.dom.parentNode == this.list) {
|
|
10148
|
+
while (domPos != item.dom)
|
|
10149
|
+
rm();
|
|
10150
|
+
domPos = item.dom.nextSibling;
|
|
10151
|
+
}
|
|
10152
|
+
else {
|
|
10153
|
+
this.list.insertBefore(item.dom, domPos);
|
|
10154
|
+
}
|
|
10155
|
+
}
|
|
10156
|
+
while (domPos)
|
|
10157
|
+
rm();
|
|
10158
|
+
}
|
|
10159
|
+
moveSelection(selectedIndex) {
|
|
10160
|
+
if (this.selectedIndex < 0)
|
|
10161
|
+
return;
|
|
10162
|
+
let field = this.view.state.field(lintState);
|
|
10163
|
+
let selection = findDiagnostic(field.diagnostics, this.items[selectedIndex].diagnostic);
|
|
10164
|
+
if (!selection)
|
|
10165
|
+
return;
|
|
10166
|
+
this.view.dispatch({
|
|
10167
|
+
selection: { anchor: selection.from, head: selection.to },
|
|
10168
|
+
scrollIntoView: true,
|
|
10169
|
+
effects: movePanelSelection.of(selection)
|
|
10170
|
+
});
|
|
10171
|
+
}
|
|
10172
|
+
static open(view) { return new LintPanel(view); }
|
|
10173
|
+
}
|
|
10174
|
+
function svg(content, attrs = `viewBox="0 0 40 40"`) {
|
|
10175
|
+
return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;
|
|
10176
|
+
}
|
|
10177
|
+
function underline(color) {
|
|
10178
|
+
return svg(`<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`, `width="6" height="3"`);
|
|
10179
|
+
}
|
|
10180
|
+
const lint_dist_baseTheme = /*@__PURE__*/view_.EditorView.baseTheme({
|
|
10181
|
+
".cm-diagnostic": {
|
|
10182
|
+
padding: "3px 6px 3px 8px",
|
|
10183
|
+
marginLeft: "-1px",
|
|
10184
|
+
display: "block",
|
|
10185
|
+
whiteSpace: "pre-wrap"
|
|
10186
|
+
},
|
|
10187
|
+
".cm-diagnostic-error": { borderLeft: "5px solid #d11" },
|
|
10188
|
+
".cm-diagnostic-warning": { borderLeft: "5px solid orange" },
|
|
10189
|
+
".cm-diagnostic-info": { borderLeft: "5px solid #999" },
|
|
10190
|
+
".cm-diagnosticAction": {
|
|
10191
|
+
font: "inherit",
|
|
10192
|
+
border: "none",
|
|
10193
|
+
padding: "2px 4px",
|
|
10194
|
+
backgroundColor: "#444",
|
|
10195
|
+
color: "white",
|
|
10196
|
+
borderRadius: "3px",
|
|
10197
|
+
marginLeft: "8px"
|
|
10198
|
+
},
|
|
10199
|
+
".cm-diagnosticSource": {
|
|
10200
|
+
fontSize: "70%",
|
|
10201
|
+
opacity: .7
|
|
10202
|
+
},
|
|
10203
|
+
".cm-lintRange": {
|
|
10204
|
+
backgroundPosition: "left bottom",
|
|
10205
|
+
backgroundRepeat: "repeat-x",
|
|
10206
|
+
paddingBottom: "0.7px",
|
|
10207
|
+
},
|
|
10208
|
+
".cm-lintRange-error": { backgroundImage: /*@__PURE__*/underline("#d11") },
|
|
10209
|
+
".cm-lintRange-warning": { backgroundImage: /*@__PURE__*/underline("orange") },
|
|
10210
|
+
".cm-lintRange-info": { backgroundImage: /*@__PURE__*/underline("#999") },
|
|
10211
|
+
".cm-lintRange-active": { backgroundColor: "#ffdd9980" },
|
|
10212
|
+
".cm-tooltip-lint": {
|
|
10213
|
+
padding: 0,
|
|
10214
|
+
margin: 0
|
|
10215
|
+
},
|
|
10216
|
+
".cm-lintPoint": {
|
|
10217
|
+
position: "relative",
|
|
10218
|
+
"&:after": {
|
|
10219
|
+
content: '""',
|
|
10220
|
+
position: "absolute",
|
|
10221
|
+
bottom: 0,
|
|
10222
|
+
left: "-2px",
|
|
10223
|
+
borderLeft: "3px solid transparent",
|
|
10224
|
+
borderRight: "3px solid transparent",
|
|
10225
|
+
borderBottom: "4px solid #d11"
|
|
10226
|
+
}
|
|
10227
|
+
},
|
|
10228
|
+
".cm-lintPoint-warning": {
|
|
10229
|
+
"&:after": { borderBottomColor: "orange" }
|
|
10230
|
+
},
|
|
10231
|
+
".cm-lintPoint-info": {
|
|
10232
|
+
"&:after": { borderBottomColor: "#999" }
|
|
10233
|
+
},
|
|
10234
|
+
".cm-panel.cm-panel-lint": {
|
|
10235
|
+
position: "relative",
|
|
10236
|
+
"& ul": {
|
|
10237
|
+
maxHeight: "100px",
|
|
10238
|
+
overflowY: "auto",
|
|
10239
|
+
"& [aria-selected]": {
|
|
10240
|
+
backgroundColor: "#ddd",
|
|
10241
|
+
"& u": { textDecoration: "underline" }
|
|
10242
|
+
},
|
|
10243
|
+
"&:focus [aria-selected]": {
|
|
10244
|
+
background_fallback: "#bdf",
|
|
10245
|
+
backgroundColor: "Highlight",
|
|
10246
|
+
color_fallback: "white",
|
|
10247
|
+
color: "HighlightText"
|
|
10248
|
+
},
|
|
10249
|
+
"& u": { textDecoration: "none" },
|
|
10250
|
+
padding: 0,
|
|
10251
|
+
margin: 0
|
|
10252
|
+
},
|
|
10253
|
+
"& [name=close]": {
|
|
10254
|
+
position: "absolute",
|
|
10255
|
+
top: "0",
|
|
10256
|
+
right: "2px",
|
|
10257
|
+
background: "inherit",
|
|
10258
|
+
border: "none",
|
|
10259
|
+
font: "inherit",
|
|
10260
|
+
padding: 0,
|
|
10261
|
+
margin: 0
|
|
10262
|
+
}
|
|
10263
|
+
}
|
|
6647
10264
|
});
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
10265
|
+
class LintGutterMarker extends view_.GutterMarker {
|
|
10266
|
+
constructor(diagnostics) {
|
|
10267
|
+
super();
|
|
10268
|
+
this.diagnostics = diagnostics;
|
|
10269
|
+
this.severity = diagnostics.reduce((max, d) => {
|
|
10270
|
+
let s = d.severity;
|
|
10271
|
+
return s == "error" || s == "warning" && max == "info" ? s : max;
|
|
10272
|
+
}, "info");
|
|
10273
|
+
}
|
|
10274
|
+
toDOM(view) {
|
|
10275
|
+
let elt = document.createElement("div");
|
|
10276
|
+
elt.className = "cm-lint-marker cm-lint-marker-" + this.severity;
|
|
10277
|
+
let diagnostics = this.diagnostics;
|
|
10278
|
+
let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
|
|
10279
|
+
if (diagnosticsFilter)
|
|
10280
|
+
diagnostics = diagnosticsFilter(diagnostics);
|
|
10281
|
+
if (diagnostics.length)
|
|
10282
|
+
elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
|
|
10283
|
+
return elt;
|
|
10284
|
+
}
|
|
10285
|
+
}
|
|
10286
|
+
function trackHoverOn(view, marker) {
|
|
10287
|
+
let mousemove = (event) => {
|
|
10288
|
+
let rect = marker.getBoundingClientRect();
|
|
10289
|
+
if (event.clientX > rect.left - 10 /* Margin */ && event.clientX < rect.right + 10 /* Margin */ &&
|
|
10290
|
+
event.clientY > rect.top - 10 /* Margin */ && event.clientY < rect.bottom + 10 /* Margin */)
|
|
10291
|
+
return;
|
|
10292
|
+
for (let target = event.target; target; target = target.parentNode) {
|
|
10293
|
+
if (target.nodeType == 1 && target.classList.contains("cm-tooltip-lint"))
|
|
10294
|
+
return;
|
|
10295
|
+
}
|
|
10296
|
+
window.removeEventListener("mousemove", mousemove);
|
|
10297
|
+
if (view.state.field(lintGutterTooltip))
|
|
10298
|
+
view.dispatch({ effects: setLintGutterTooltip.of(null) });
|
|
10299
|
+
};
|
|
10300
|
+
window.addEventListener("mousemove", mousemove);
|
|
10301
|
+
}
|
|
10302
|
+
function gutterMarkerMouseOver(view, marker, diagnostics) {
|
|
10303
|
+
function hovered() {
|
|
10304
|
+
let line = view.elementAtHeight(marker.getBoundingClientRect().top + 5 - view.documentTop);
|
|
10305
|
+
const linePos = view.coordsAtPos(line.from);
|
|
10306
|
+
if (linePos) {
|
|
10307
|
+
view.dispatch({ effects: setLintGutterTooltip.of({
|
|
10308
|
+
pos: line.from,
|
|
10309
|
+
above: false,
|
|
10310
|
+
create() {
|
|
10311
|
+
return {
|
|
10312
|
+
dom: diagnosticsTooltip(view, diagnostics),
|
|
10313
|
+
getCoords: () => marker.getBoundingClientRect()
|
|
10314
|
+
};
|
|
10315
|
+
}
|
|
10316
|
+
}) });
|
|
10317
|
+
}
|
|
10318
|
+
marker.onmouseout = marker.onmousemove = null;
|
|
10319
|
+
trackHoverOn(view, marker);
|
|
10320
|
+
}
|
|
10321
|
+
let { hoverTime } = view.state.facet(lintGutterConfig);
|
|
10322
|
+
let hoverTimeout = setTimeout(hovered, hoverTime);
|
|
10323
|
+
marker.onmouseout = () => {
|
|
10324
|
+
clearTimeout(hoverTimeout);
|
|
10325
|
+
marker.onmouseout = marker.onmousemove = null;
|
|
10326
|
+
};
|
|
10327
|
+
marker.onmousemove = () => {
|
|
10328
|
+
clearTimeout(hoverTimeout);
|
|
10329
|
+
hoverTimeout = setTimeout(hovered, hoverTime);
|
|
10330
|
+
};
|
|
10331
|
+
}
|
|
10332
|
+
function markersForDiagnostics(doc, diagnostics) {
|
|
10333
|
+
let byLine = Object.create(null);
|
|
10334
|
+
for (let diagnostic of diagnostics) {
|
|
10335
|
+
let line = doc.lineAt(diagnostic.from);
|
|
10336
|
+
(byLine[line.from] || (byLine[line.from] = [])).push(diagnostic);
|
|
10337
|
+
}
|
|
10338
|
+
let markers = [];
|
|
10339
|
+
for (let line in byLine) {
|
|
10340
|
+
markers.push(new LintGutterMarker(byLine[line]).range(+line));
|
|
10341
|
+
}
|
|
10342
|
+
return state_.RangeSet.of(markers, true);
|
|
10343
|
+
}
|
|
10344
|
+
const lintGutterExtension = /*@__PURE__*/(0,view_.gutter)({
|
|
10345
|
+
class: "cm-gutter-lint",
|
|
10346
|
+
markers: view => view.state.field(lintGutterMarkers),
|
|
10347
|
+
});
|
|
10348
|
+
const lintGutterMarkers = /*@__PURE__*/state_.StateField.define({
|
|
10349
|
+
create() {
|
|
10350
|
+
return state_.RangeSet.empty;
|
|
10351
|
+
},
|
|
10352
|
+
update(markers, tr) {
|
|
10353
|
+
markers = markers.map(tr.changes);
|
|
10354
|
+
let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter;
|
|
10355
|
+
for (let effect of tr.effects) {
|
|
10356
|
+
if (effect.is(setDiagnosticsEffect)) {
|
|
10357
|
+
let diagnostics = effect.value;
|
|
10358
|
+
if (diagnosticFilter)
|
|
10359
|
+
diagnostics = diagnosticFilter(diagnostics || []);
|
|
10360
|
+
markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
|
|
10361
|
+
}
|
|
10362
|
+
}
|
|
10363
|
+
return markers;
|
|
10364
|
+
}
|
|
10365
|
+
});
|
|
10366
|
+
const setLintGutterTooltip = /*@__PURE__*/state_.StateEffect.define();
|
|
10367
|
+
const lintGutterTooltip = /*@__PURE__*/state_.StateField.define({
|
|
10368
|
+
create() { return null; },
|
|
10369
|
+
update(tooltip, tr) {
|
|
10370
|
+
if (tooltip && tr.docChanged)
|
|
10371
|
+
tooltip = hideTooltip(tr, tooltip) ? null : Object.assign(Object.assign({}, tooltip), { pos: tr.changes.mapPos(tooltip.pos) });
|
|
10372
|
+
return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip);
|
|
10373
|
+
},
|
|
10374
|
+
provide: field => view_.showTooltip.from(field)
|
|
10375
|
+
});
|
|
10376
|
+
const lintGutterTheme = /*@__PURE__*/view_.EditorView.baseTheme({
|
|
10377
|
+
".cm-gutter-lint": {
|
|
10378
|
+
width: "1.4em",
|
|
10379
|
+
"& .cm-gutterElement": {
|
|
10380
|
+
padding: ".2em"
|
|
10381
|
+
}
|
|
10382
|
+
},
|
|
10383
|
+
".cm-lint-marker": {
|
|
10384
|
+
width: "1em",
|
|
10385
|
+
height: "1em"
|
|
10386
|
+
},
|
|
10387
|
+
".cm-lint-marker-info": {
|
|
10388
|
+
content: /*@__PURE__*/svg(`<path fill="#aaf" stroke="#77e" stroke-width="6" stroke-linejoin="round" d="M5 5L35 5L35 35L5 35Z"/>`)
|
|
10389
|
+
},
|
|
10390
|
+
".cm-lint-marker-warning": {
|
|
10391
|
+
content: /*@__PURE__*/svg(`<path fill="#fe8" stroke="#fd7" stroke-width="6" stroke-linejoin="round" d="M20 6L37 35L3 35Z"/>`),
|
|
10392
|
+
},
|
|
10393
|
+
".cm-lint-marker-error:before": {
|
|
10394
|
+
content: /*@__PURE__*/svg(`<circle cx="20" cy="20" r="15" fill="#f87" stroke="#f43" stroke-width="6"/>`)
|
|
10395
|
+
},
|
|
10396
|
+
});
|
|
10397
|
+
const lintGutterConfig = /*@__PURE__*/state_.Facet.define({
|
|
10398
|
+
combine(configs) {
|
|
10399
|
+
return (0,state_.combineConfig)(configs, {
|
|
10400
|
+
hoverTime: 300 /* Time */,
|
|
10401
|
+
markerFilter: null,
|
|
10402
|
+
tooltipFilter: null
|
|
10403
|
+
});
|
|
10404
|
+
}
|
|
10405
|
+
});
|
|
10406
|
+
/**
|
|
10407
|
+
Returns an extension that installs a gutter showing markers for
|
|
10408
|
+
each line that has diagnostics, which can be hovered over to see
|
|
10409
|
+
the diagnostics.
|
|
10410
|
+
*/
|
|
10411
|
+
function lintGutter(config = {}) {
|
|
10412
|
+
return [lintGutterConfig.of(config), lintGutterMarkers, lintGutterExtension, lintGutterTheme, lintGutterTooltip];
|
|
6663
10413
|
}
|
|
6664
|
-
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/objectSpread2.js
|
|
6665
10414
|
|
|
6666
10415
|
|
|
6667
|
-
function ownKeys(object, enumerableOnly) {
|
|
6668
|
-
var keys = Object.keys(object);
|
|
6669
10416
|
|
|
6670
|
-
|
|
6671
|
-
var symbols = Object.getOwnPropertySymbols(object);
|
|
6672
|
-
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
|
6673
|
-
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
6674
|
-
})), keys.push.apply(keys, symbols);
|
|
6675
|
-
}
|
|
10417
|
+
;// CONCATENATED MODULE: ./node_modules/codemirror/dist/index.js
|
|
6676
10418
|
|
|
6677
|
-
return keys;
|
|
6678
|
-
}
|
|
6679
10419
|
|
|
6680
|
-
function _objectSpread2(target) {
|
|
6681
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
6682
|
-
var source = null != arguments[i] ? arguments[i] : {};
|
|
6683
|
-
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
|
|
6684
|
-
_defineProperty(target, key, source[key]);
|
|
6685
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
|
|
6686
|
-
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
6687
|
-
});
|
|
6688
|
-
}
|
|
6689
10420
|
|
|
6690
|
-
return target;
|
|
6691
|
-
}
|
|
6692
10421
|
|
|
6693
|
-
/***/ }),
|
|
6694
10422
|
|
|
6695
|
-
/***/ 925:
|
|
6696
|
-
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
6697
10423
|
|
|
6698
10424
|
|
|
6699
|
-
// EXPORTS
|
|
6700
|
-
__webpack_require__.d(__webpack_exports__, {
|
|
6701
|
-
"Z": () => (/* binding */ _objectWithoutProperties)
|
|
6702
|
-
});
|
|
6703
10425
|
|
|
6704
|
-
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js
|
|
6705
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
6706
|
-
if (source == null) return {};
|
|
6707
|
-
var target = {};
|
|
6708
|
-
var sourceKeys = Object.keys(source);
|
|
6709
|
-
var key, i;
|
|
6710
10426
|
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
10427
|
+
/**
|
|
10428
|
+
This is an extension value that just pulls together a number of
|
|
10429
|
+
extensions that you might want in a basic editor. It is meant as a
|
|
10430
|
+
convenient helper to quickly set up CodeMirror without installing
|
|
10431
|
+
and importing a lot of separate packages.
|
|
6716
10432
|
|
|
6717
|
-
|
|
6718
|
-
}
|
|
6719
|
-
;// CONCATENATED MODULE: ./node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js
|
|
10433
|
+
Specifically, it includes...
|
|
6720
10434
|
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
10435
|
+
- [the default command bindings](https://codemirror.net/6/docs/ref/#commands.defaultKeymap)
|
|
10436
|
+
- [line numbers](https://codemirror.net/6/docs/ref/#view.lineNumbers)
|
|
10437
|
+
- [special character highlighting](https://codemirror.net/6/docs/ref/#view.highlightSpecialChars)
|
|
10438
|
+
- [the undo history](https://codemirror.net/6/docs/ref/#commands.history)
|
|
10439
|
+
- [a fold gutter](https://codemirror.net/6/docs/ref/#language.foldGutter)
|
|
10440
|
+
- [custom selection drawing](https://codemirror.net/6/docs/ref/#view.drawSelection)
|
|
10441
|
+
- [drop cursor](https://codemirror.net/6/docs/ref/#view.dropCursor)
|
|
10442
|
+
- [multiple selections](https://codemirror.net/6/docs/ref/#state.EditorState^allowMultipleSelections)
|
|
10443
|
+
- [reindentation on input](https://codemirror.net/6/docs/ref/#language.indentOnInput)
|
|
10444
|
+
- [the default highlight style](https://codemirror.net/6/docs/ref/#language.defaultHighlightStyle) (as fallback)
|
|
10445
|
+
- [bracket matching](https://codemirror.net/6/docs/ref/#language.bracketMatching)
|
|
10446
|
+
- [bracket closing](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets)
|
|
10447
|
+
- [autocompletion](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion)
|
|
10448
|
+
- [rectangular selection](https://codemirror.net/6/docs/ref/#view.rectangularSelection) and [crosshair cursor](https://codemirror.net/6/docs/ref/#view.crosshairCursor)
|
|
10449
|
+
- [active line highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLine)
|
|
10450
|
+
- [active line gutter highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLineGutter)
|
|
10451
|
+
- [selection match highlighting](https://codemirror.net/6/docs/ref/#search.highlightSelectionMatches)
|
|
10452
|
+
- [search](https://codemirror.net/6/docs/ref/#search.searchKeymap)
|
|
10453
|
+
- [linting](https://codemirror.net/6/docs/ref/#lint.lintKeymap)
|
|
6725
10454
|
|
|
6726
|
-
|
|
6727
|
-
|
|
10455
|
+
(You'll probably want to add some language package to your setup
|
|
10456
|
+
too.)
|
|
6728
10457
|
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
10458
|
+
This extension does not allow customization. The idea is that,
|
|
10459
|
+
once you decide you want to configure your editor more precisely,
|
|
10460
|
+
you take this package's source (which is just a bunch of imports
|
|
10461
|
+
and an array literal), copy it into your own code, and adjust it
|
|
10462
|
+
as desired.
|
|
10463
|
+
*/
|
|
10464
|
+
const basicSetup = [
|
|
10465
|
+
/*@__PURE__*/(0,view_.lineNumbers)(),
|
|
10466
|
+
/*@__PURE__*/(0,view_.highlightActiveLineGutter)(),
|
|
10467
|
+
/*@__PURE__*/(0,view_.highlightSpecialChars)(),
|
|
10468
|
+
/*@__PURE__*/dist_history(),
|
|
10469
|
+
/*@__PURE__*/foldGutter(),
|
|
10470
|
+
/*@__PURE__*/(0,view_.drawSelection)(),
|
|
10471
|
+
/*@__PURE__*/(0,view_.dropCursor)(),
|
|
10472
|
+
/*@__PURE__*/state_.EditorState.allowMultipleSelections.of(true),
|
|
10473
|
+
/*@__PURE__*/indentOnInput(),
|
|
10474
|
+
/*@__PURE__*/syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
|
10475
|
+
/*@__PURE__*/bracketMatching(),
|
|
10476
|
+
/*@__PURE__*/closeBrackets(),
|
|
10477
|
+
/*@__PURE__*/autocompletion(),
|
|
10478
|
+
/*@__PURE__*/(0,view_.rectangularSelection)(),
|
|
10479
|
+
/*@__PURE__*/(0,view_.crosshairCursor)(),
|
|
10480
|
+
/*@__PURE__*/(0,view_.highlightActiveLine)(),
|
|
10481
|
+
/*@__PURE__*/highlightSelectionMatches(),
|
|
10482
|
+
/*@__PURE__*/view_.keymap.of([
|
|
10483
|
+
...closeBracketsKeymap,
|
|
10484
|
+
...defaultKeymap,
|
|
10485
|
+
...searchKeymap,
|
|
10486
|
+
...historyKeymap,
|
|
10487
|
+
...foldKeymap,
|
|
10488
|
+
...completionKeymap,
|
|
10489
|
+
...lintKeymap
|
|
10490
|
+
])
|
|
10491
|
+
];
|
|
10492
|
+
/**
|
|
10493
|
+
A minimal set of extensions to create a functional editor. Only
|
|
10494
|
+
includes [the default keymap](https://codemirror.net/6/docs/ref/#commands.defaultKeymap), [undo
|
|
10495
|
+
history](https://codemirror.net/6/docs/ref/#commands.history), [special character
|
|
10496
|
+
highlighting](https://codemirror.net/6/docs/ref/#view.highlightSpecialChars), [custom selection
|
|
10497
|
+
drawing](https://codemirror.net/6/docs/ref/#view.drawSelection), and [default highlight
|
|
10498
|
+
style](https://codemirror.net/6/docs/ref/#language.defaultHighlightStyle).
|
|
10499
|
+
*/
|
|
10500
|
+
const minimalSetup = [
|
|
10501
|
+
/*@__PURE__*/(0,view_.highlightSpecialChars)(),
|
|
10502
|
+
/*@__PURE__*/dist_history(),
|
|
10503
|
+
/*@__PURE__*/(0,view_.drawSelection)(),
|
|
10504
|
+
/*@__PURE__*/syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
|
10505
|
+
/*@__PURE__*/view_.keymap.of([
|
|
10506
|
+
...defaultKeymap,
|
|
10507
|
+
...historyKeymap,
|
|
10508
|
+
])
|
|
10509
|
+
];
|
|
6736
10510
|
|
|
6737
|
-
return target;
|
|
6738
|
-
}
|
|
6739
10511
|
|
|
6740
|
-
/***/ })
|
|
6741
10512
|
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
/******/ // Create a new module (and put it into the cache)
|
|
6755
|
-
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
6756
|
-
/******/ // no module.id needed
|
|
6757
|
-
/******/ // no module.loaded needed
|
|
6758
|
-
/******/ exports: {}
|
|
6759
|
-
/******/ };
|
|
6760
|
-
/******/
|
|
6761
|
-
/******/ // Execute the module function
|
|
6762
|
-
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
6763
|
-
/******/
|
|
6764
|
-
/******/ // Return the exports of the module
|
|
6765
|
-
/******/ return module.exports;
|
|
6766
|
-
/******/ }
|
|
6767
|
-
/******/
|
|
6768
|
-
/************************************************************************/
|
|
6769
|
-
/******/ /* webpack/runtime/compat get default export */
|
|
6770
|
-
/******/ (() => {
|
|
6771
|
-
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
6772
|
-
/******/ __webpack_require__.n = (module) => {
|
|
6773
|
-
/******/ var getter = module && module.__esModule ?
|
|
6774
|
-
/******/ () => (module['default']) :
|
|
6775
|
-
/******/ () => (module);
|
|
6776
|
-
/******/ __webpack_require__.d(getter, { a: getter });
|
|
6777
|
-
/******/ return getter;
|
|
6778
|
-
/******/ };
|
|
6779
|
-
/******/ })();
|
|
6780
|
-
/******/
|
|
6781
|
-
/******/ /* webpack/runtime/define property getters */
|
|
6782
|
-
/******/ (() => {
|
|
6783
|
-
/******/ // define getter functions for harmony exports
|
|
6784
|
-
/******/ __webpack_require__.d = (exports, definition) => {
|
|
6785
|
-
/******/ for(var key in definition) {
|
|
6786
|
-
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
6787
|
-
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
6788
|
-
/******/ }
|
|
6789
|
-
/******/ }
|
|
6790
|
-
/******/ };
|
|
6791
|
-
/******/ })();
|
|
6792
|
-
/******/
|
|
6793
|
-
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
6794
|
-
/******/ (() => {
|
|
6795
|
-
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
6796
|
-
/******/ })();
|
|
6797
|
-
/******/
|
|
6798
|
-
/******/ /* webpack/runtime/make namespace object */
|
|
6799
|
-
/******/ (() => {
|
|
6800
|
-
/******/ // define __esModule on exports
|
|
6801
|
-
/******/ __webpack_require__.r = (exports) => {
|
|
6802
|
-
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
6803
|
-
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
6804
|
-
/******/ }
|
|
6805
|
-
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
6806
|
-
/******/ };
|
|
6807
|
-
/******/ })();
|
|
6808
|
-
/******/
|
|
6809
|
-
/************************************************************************/
|
|
6810
|
-
var __webpack_exports__ = {};
|
|
6811
|
-
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
|
6812
|
-
(() => {
|
|
6813
|
-
__webpack_require__.r(__webpack_exports__);
|
|
6814
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
6815
|
-
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
|
|
6816
|
-
/* harmony export */ "useCodeMirror": () => (/* reexport safe */ _useCodeMirror__WEBPACK_IMPORTED_MODULE_1__.U)
|
|
6817
|
-
/* harmony export */ });
|
|
6818
|
-
/* harmony import */ var _home_runner_work_react_codemirror_react_codemirror_node_modules_babel_runtime_helpers_esm_objectSpread2_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(683);
|
|
6819
|
-
/* harmony import */ var _home_runner_work_react_codemirror_react_codemirror_node_modules_babel_runtime_helpers_esm_objectWithoutProperties_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(925);
|
|
6820
|
-
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(787);
|
|
6821
|
-
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
6822
|
-
/* harmony import */ var _useCodeMirror__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(963);
|
|
6823
|
-
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(724);
|
|
6824
|
-
/* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(105);
|
|
6825
|
-
/* harmony import */ var _codemirror_view__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_codemirror_view__WEBPACK_IMPORTED_MODULE_3__);
|
|
6826
|
-
/* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {};
|
|
6827
|
-
/* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _codemirror_view__WEBPACK_IMPORTED_MODULE_3__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _codemirror_view__WEBPACK_IMPORTED_MODULE_3__[__WEBPACK_IMPORT_KEY__]
|
|
6828
|
-
/* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
|
|
6829
|
-
/* harmony import */ var _codemirror_basic_setup__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(573);
|
|
6830
|
-
/* harmony import */ var _codemirror_basic_setup__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_codemirror_basic_setup__WEBPACK_IMPORTED_MODULE_4__);
|
|
6831
|
-
/* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {};
|
|
6832
|
-
/* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _codemirror_basic_setup__WEBPACK_IMPORTED_MODULE_4__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _codemirror_basic_setup__WEBPACK_IMPORTED_MODULE_4__[__WEBPACK_IMPORT_KEY__]
|
|
6833
|
-
/* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
|
|
6834
|
-
/* harmony import */ var _codemirror_state__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(242);
|
|
6835
|
-
/* harmony import */ var _codemirror_state__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_codemirror_state__WEBPACK_IMPORTED_MODULE_5__);
|
|
6836
|
-
/* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {};
|
|
6837
|
-
/* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in _codemirror_state__WEBPACK_IMPORTED_MODULE_5__) if(__WEBPACK_IMPORT_KEY__ !== "default") __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => _codemirror_state__WEBPACK_IMPORTED_MODULE_5__[__WEBPACK_IMPORT_KEY__]
|
|
6838
|
-
/* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
|
|
6839
|
-
var _excluded=["className","value","selection","extensions","onChange","onUpdate","autoFocus","theme","height","minHeight","maxHeight","width","minWidth","maxWidth","basicSetup","placeholder","indentWithTab","editable","readOnly","root"];var ReactCodeMirror=/*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().forwardRef(function(props,ref){var className=props.className,_props$value=props.value,value=_props$value===void 0?'':_props$value,selection=props.selection,_props$extensions=props.extensions,extensions=_props$extensions===void 0?[]:_props$extensions,onChange=props.onChange,onUpdate=props.onUpdate,autoFocus=props.autoFocus,_props$theme=props.theme,theme=_props$theme===void 0?'light':_props$theme,height=props.height,minHeight=props.minHeight,maxHeight=props.maxHeight,width=props.width,minWidth=props.minWidth,maxWidth=props.maxWidth,basicSetup=props.basicSetup,placeholder=props.placeholder,indentWithTab=props.indentWithTab,editable=props.editable,readOnly=props.readOnly,root=props.root,other=(0,_home_runner_work_react_codemirror_react_codemirror_node_modules_babel_runtime_helpers_esm_objectWithoutProperties_js__WEBPACK_IMPORTED_MODULE_6__/* ["default"] */ .Z)(props,_excluded);var editor=(0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);var _useCodeMirror=(0,_useCodeMirror__WEBPACK_IMPORTED_MODULE_1__/* .useCodeMirror */ .U)({container:editor.current,root:root,value:value,autoFocus:autoFocus,theme:theme,height:height,minHeight:minHeight,maxHeight:maxHeight,width:width,minWidth:minWidth,maxWidth:maxWidth,basicSetup:basicSetup,placeholder:placeholder,indentWithTab:indentWithTab,editable:editable,readOnly:readOnly,selection:selection,onChange:onChange,onUpdate:onUpdate,extensions:extensions}),state=_useCodeMirror.state,view=_useCodeMirror.view,container=_useCodeMirror.container,setContainer=_useCodeMirror.setContainer;(0,react__WEBPACK_IMPORTED_MODULE_0__.useImperativeHandle)(ref,function(){return{editor:container,state:state,view:view};},[container,state,view]);(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function(){setContainer(editor.current);// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
10513
|
+
// EXTERNAL MODULE: external {"root":["CM","@codemirror/theme-one-dark"],"commonjs":"@codemirror/theme-one-dark","commonjs2":"@codemirror/theme-one-dark"}
|
|
10514
|
+
var theme_one_dark_ = __webpack_require__(362);
|
|
10515
|
+
;// CONCATENATED MODULE: ./src/theme/light.ts
|
|
10516
|
+
var defaultLightThemeOption=view_.EditorView.theme({'&':{backgroundColor:'#fff'}},{dark:false});
|
|
10517
|
+
;// CONCATENATED MODULE: ./src/useCodeMirror.ts
|
|
10518
|
+
function useCodeMirror(props){var value=props.value,selection=props.selection,onChange=props.onChange,onUpdate=props.onUpdate,_props$extensions=props.extensions,extensions=_props$extensions===void 0?[]:_props$extensions,autoFocus=props.autoFocus,_props$theme=props.theme,theme=_props$theme===void 0?'light':_props$theme,_props$height=props.height,height=_props$height===void 0?'':_props$height,_props$minHeight=props.minHeight,minHeight=_props$minHeight===void 0?'':_props$minHeight,_props$maxHeight=props.maxHeight,maxHeight=_props$maxHeight===void 0?'':_props$maxHeight,_props$placeholder=props.placeholder,placeholderStr=_props$placeholder===void 0?'':_props$placeholder,_props$width=props.width,width=_props$width===void 0?'':_props$width,_props$minWidth=props.minWidth,minWidth=_props$minWidth===void 0?'':_props$minWidth,_props$maxWidth=props.maxWidth,maxWidth=_props$maxWidth===void 0?'':_props$maxWidth,_props$editable=props.editable,editable=_props$editable===void 0?true:_props$editable,_props$readOnly=props.readOnly,readOnly=_props$readOnly===void 0?false:_props$readOnly,_props$indentWithTab=props.indentWithTab,defaultIndentWithTab=_props$indentWithTab===void 0?true:_props$indentWithTab,_props$basicSetup=props.basicSetup,defaultBasicSetup=_props$basicSetup===void 0?true:_props$basicSetup,root=props.root;var _useState=(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)(props.container),_useState2=_slicedToArray(_useState,2),container=_useState2[0],setContainer=_useState2[1];var _useState3=(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)(),_useState4=_slicedToArray(_useState3,2),view=_useState4[0],setView=_useState4[1];var _useState5=(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useState)(),_useState6=_slicedToArray(_useState5,2),state=_useState6[0],setState=_useState6[1];var defaultThemeOption=view_.EditorView.theme({'&':{height:height,minHeight:minHeight,maxHeight:maxHeight,width:width,minWidth:minWidth,maxWidth:maxWidth}});var updateListener=view_.EditorView.updateListener.of(function(vu){if(vu.docChanged&&typeof onChange==='function'){var doc=vu.state.doc;var _value=doc.toString();onChange(_value,vu);}});var getExtensions=[updateListener,defaultThemeOption];if(defaultIndentWithTab){getExtensions.unshift(view_.keymap.of([indentWithTab]));}if(defaultBasicSetup){getExtensions.unshift(basicSetup);}if(placeholderStr){getExtensions.unshift((0,view_.placeholder)(placeholderStr));}switch(theme){case'light':getExtensions.push(defaultLightThemeOption);break;case'dark':getExtensions.push(theme_one_dark_.oneDark);break;default:getExtensions.push(theme);break;}if(editable===false){getExtensions.push(view_.EditorView.editable.of(false));}if(readOnly){getExtensions.push(state_.EditorState.readOnly.of(true));}if(onUpdate&&typeof onUpdate==='function'){getExtensions.push(view_.EditorView.updateListener.of(onUpdate));}getExtensions=getExtensions.concat(extensions);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){if(container&&!state){var stateCurrent=state_.EditorState.create({doc:value,selection:selection,extensions:getExtensions});setState(stateCurrent);if(!view){var viewCurrent=new view_.EditorView({state:stateCurrent,parent:container,root:root});setView(viewCurrent);}}return function(){if(view){setView(undefined);}};// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
10519
|
+
},[container,state]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){return function(){if(view){view.destroy();setView(undefined);}};},[view]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){if(autoFocus&&view){view.focus();}},[autoFocus,view]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){var currentValue=view?view.state.doc.toString():'';if(view&&value!==currentValue){view.dispatch({changes:{from:0,to:currentValue.length,insert:value||''}});}},[value,view]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){if(view){view.dispatch({effects:state_.StateEffect.reconfigure.of(getExtensions)});}// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
10520
|
+
},[theme,extensions,height,minHeight,maxHeight,width,placeholderStr,minWidth,maxWidth,editable,defaultIndentWithTab,defaultBasicSetup]);return{state:state,setState:setState,view:view,setView:setView,container:container,setContainer:setContainer};}
|
|
10521
|
+
// EXTERNAL MODULE: ./node_modules/react/jsx-runtime.js
|
|
10522
|
+
var jsx_runtime = __webpack_require__(724);
|
|
10523
|
+
;// CONCATENATED MODULE: ./src/index.tsx
|
|
10524
|
+
var _excluded=["className","value","selection","extensions","onChange","onUpdate","autoFocus","theme","height","minHeight","maxHeight","width","minWidth","maxWidth","basicSetup","placeholder","indentWithTab","editable","readOnly","root"];var ReactCodeMirror=/*#__PURE__*/external_root_React_commonjs2_react_commonjs_react_amd_react_default().forwardRef(function(props,ref){var className=props.className,_props$value=props.value,value=_props$value===void 0?'':_props$value,selection=props.selection,_props$extensions=props.extensions,extensions=_props$extensions===void 0?[]:_props$extensions,onChange=props.onChange,onUpdate=props.onUpdate,autoFocus=props.autoFocus,_props$theme=props.theme,theme=_props$theme===void 0?'light':_props$theme,height=props.height,minHeight=props.minHeight,maxHeight=props.maxHeight,width=props.width,minWidth=props.minWidth,maxWidth=props.maxWidth,basicSetup=props.basicSetup,placeholder=props.placeholder,indentWithTab=props.indentWithTab,editable=props.editable,readOnly=props.readOnly,root=props.root,other=_objectWithoutProperties(props,_excluded);var editor=(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useRef)(null);var _useCodeMirror=useCodeMirror({container:editor.current,root:root,value:value,autoFocus:autoFocus,theme:theme,height:height,minHeight:minHeight,maxHeight:maxHeight,width:width,minWidth:minWidth,maxWidth:maxWidth,basicSetup:basicSetup,placeholder:placeholder,indentWithTab:indentWithTab,editable:editable,readOnly:readOnly,selection:selection,onChange:onChange,onUpdate:onUpdate,extensions:extensions}),state=_useCodeMirror.state,view=_useCodeMirror.view,container=_useCodeMirror.container,setContainer=_useCodeMirror.setContainer;(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useImperativeHandle)(ref,function(){return{editor:container,state:state,view:view};},[container,state,view]);(0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useEffect)(function(){setContainer(editor.current);// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
6840
10525
|
},[]);// check type of value
|
|
6841
|
-
if(typeof value!=='string'){throw new Error("value must be typeof string but got ".concat(typeof value));}var defaultClassNames=typeof theme==='string'?"cm-theme-".concat(theme):'cm-theme';return/*#__PURE__*/(0,
|
|
10526
|
+
if(typeof value!=='string'){throw new Error("value must be typeof string but got ".concat(typeof value));}var defaultClassNames=typeof theme==='string'?"cm-theme-".concat(theme):'cm-theme';return/*#__PURE__*/(0,jsx_runtime.jsx)("div",_objectSpread2({ref:editor,className:"".concat(defaultClassNames).concat(className?" ".concat(className):'')},other));});ReactCodeMirror.displayName='CodeMirror';/* harmony default export */ const src = (ReactCodeMirror);
|
|
6842
10527
|
})();
|
|
6843
10528
|
|
|
6844
10529
|
/******/ return __webpack_exports__;
|