janusweb 1.5.33 → 1.5.34

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.
Files changed (46) hide show
  1. package/CHANGELOG +39 -0
  2. package/media/assets/webui/apps/avatar/avatar.js +2 -1
  3. package/media/assets/webui/apps/comms/voip.js +2 -4
  4. package/media/assets/webui/apps/editor/codemirror/addon/hint/javascript-hint.js +162 -0
  5. package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.css +36 -0
  6. package/media/assets/webui/apps/editor/codemirror/addon/hint/show-hint.js +529 -0
  7. package/media/assets/webui/apps/editor/codemirror/addon/hint/xml-hint.js +140 -0
  8. package/media/assets/webui/apps/editor/codemirror/keymap/vim.js +5734 -0
  9. package/media/assets/webui/apps/editor/codemirror/lib/codemirror.css +350 -0
  10. package/media/assets/webui/apps/editor/codemirror/lib/codemirror.js +9800 -0
  11. package/media/assets/webui/apps/editor/codemirror/lib/jmldark.css +33 -0
  12. package/media/assets/webui/apps/editor/codemirror/mode/css/css.js +864 -0
  13. package/media/assets/webui/apps/editor/codemirror/mode/htmlmixed/htmlmixed.js +153 -0
  14. package/media/assets/webui/apps/editor/codemirror/mode/javascript/javascript.js +942 -0
  15. package/media/assets/webui/apps/editor/codemirror/mode/xml/xml.js +413 -0
  16. package/media/assets/webui/apps/editor/editor.css +3 -0
  17. package/media/assets/webui/apps/editor/editor.js +407 -9
  18. package/media/assets/webui/apps/editor/editor.json +6 -3
  19. package/media/assets/webui/apps/inventory/inventory.js +1 -1
  20. package/media/assets/webui/apps/locomotion/teleporter.js +1 -1
  21. package/media/assets/webui/apps/navigation/navigation.js +12 -12
  22. package/media/assets/webui/apps/vfs/browserfs/browserfs.js +8 -0
  23. package/media/assets/webui/apps/vfs/vfs.css +52 -0
  24. package/media/assets/webui/apps/vfs/vfs.js +452 -0
  25. package/media/assets/webui/apps/vfs/vfs.json +10 -0
  26. package/media/assets/webui/default.json +2 -1
  27. package/media/assets/webui/themes/default.css +29 -2
  28. package/package.json +2 -9
  29. package/scripts/client.js +64 -44
  30. package/scripts/elements/linesegments.js +5 -2
  31. package/scripts/janusbase.js +21 -9
  32. package/scripts/janusghost.js +0 -1
  33. package/scripts/janusparagraph.js +5 -3
  34. package/scripts/janusparticle.js +11 -12
  35. package/scripts/janusplayer.js +2 -2
  36. package/scripts/janusweb.js +21 -2
  37. package/scripts/janusxrplayer.js +3 -0
  38. package/scripts/multiplayermanager.js +3 -3
  39. package/scripts/object.js +159 -82
  40. package/scripts/portal.js +2 -3
  41. package/scripts/room.js +86 -44
  42. package/scripts/sound.js +0 -1
  43. package/scripts/text.js +10 -2
  44. package/scripts/translators/janusvfs.js +20 -0
  45. package/scripts/video.js +1 -1
  46. package/scripts/websurface.js +11 -2
@@ -0,0 +1,529 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: https://codemirror.net/LICENSE
3
+
4
+ // declare global: DOMRect
5
+
6
+ (function(mod) {
7
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
8
+ mod(require("../../lib/codemirror"));
9
+ else if (typeof define == "function" && define.amd) // AMD
10
+ define(["../../lib/codemirror"], mod);
11
+ else // Plain browser env
12
+ mod(CodeMirror);
13
+ })(function(CodeMirror) {
14
+ "use strict";
15
+
16
+ var HINT_ELEMENT_CLASS = "CodeMirror-hint";
17
+ var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
18
+
19
+ // This is the old interface, kept around for now to stay
20
+ // backwards-compatible.
21
+ CodeMirror.showHint = function(cm, getHints, options) {
22
+ if (!getHints) return cm.showHint(options);
23
+ if (options && options.async) getHints.async = true;
24
+ var newOpts = {hint: getHints};
25
+ if (options) for (var prop in options) newOpts[prop] = options[prop];
26
+ return cm.showHint(newOpts);
27
+ };
28
+
29
+ CodeMirror.defineExtension("showHint", function(options) {
30
+ options = parseOptions(this, this.getCursor("start"), options);
31
+ var selections = this.listSelections()
32
+ if (selections.length > 1) return;
33
+ // By default, don't allow completion when something is selected.
34
+ // A hint function can have a `supportsSelection` property to
35
+ // indicate that it can handle selections.
36
+ if (this.somethingSelected()) {
37
+ if (!options.hint.supportsSelection) return;
38
+ // Don't try with cross-line selections
39
+ for (var i = 0; i < selections.length; i++)
40
+ if (selections[i].head.line != selections[i].anchor.line) return;
41
+ }
42
+
43
+ if (this.state.completionActive) this.state.completionActive.close();
44
+ var completion = this.state.completionActive = new Completion(this, options);
45
+ if (!completion.options.hint) return;
46
+
47
+ CodeMirror.signal(this, "startCompletion", this);
48
+ completion.update(true);
49
+ });
50
+
51
+ CodeMirror.defineExtension("closeHint", function() {
52
+ if (this.state.completionActive) this.state.completionActive.close()
53
+ })
54
+
55
+ function Completion(cm, options) {
56
+ this.cm = cm;
57
+ this.options = options;
58
+ this.widget = null;
59
+ this.debounce = 0;
60
+ this.tick = 0;
61
+ this.startPos = this.cm.getCursor("start");
62
+ this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
63
+
64
+ if (this.options.updateOnCursorActivity) {
65
+ var self = this;
66
+ cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
67
+ }
68
+ }
69
+
70
+ var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
71
+ return setTimeout(fn, 1000/60);
72
+ };
73
+ var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
74
+
75
+ Completion.prototype = {
76
+ close: function() {
77
+ if (!this.active()) return;
78
+ this.cm.state.completionActive = null;
79
+ this.tick = null;
80
+ if (this.options.updateOnCursorActivity) {
81
+ this.cm.off("cursorActivity", this.activityFunc);
82
+ }
83
+
84
+ if (this.widget && this.data) CodeMirror.signal(this.data, "close");
85
+ if (this.widget) this.widget.close();
86
+ CodeMirror.signal(this.cm, "endCompletion", this.cm);
87
+ },
88
+
89
+ active: function() {
90
+ return this.cm.state.completionActive == this;
91
+ },
92
+
93
+ pick: function(data, i) {
94
+ var completion = data.list[i], self = this;
95
+ this.cm.operation(function() {
96
+ if (completion.hint)
97
+ completion.hint(self.cm, data, completion);
98
+ else
99
+ self.cm.replaceRange(getText(completion), completion.from || data.from,
100
+ completion.to || data.to, "complete");
101
+ CodeMirror.signal(data, "pick", completion);
102
+ self.cm.scrollIntoView();
103
+ });
104
+ if (this.options.closeOnPick) {
105
+ this.close();
106
+ }
107
+ },
108
+
109
+ cursorActivity: function() {
110
+ if (this.debounce) {
111
+ cancelAnimationFrame(this.debounce);
112
+ this.debounce = 0;
113
+ }
114
+
115
+ var identStart = this.startPos;
116
+ if(this.data) {
117
+ identStart = this.data.from;
118
+ }
119
+
120
+ var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
121
+ if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
122
+ pos.ch < identStart.ch || this.cm.somethingSelected() ||
123
+ (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
124
+ this.close();
125
+ } else {
126
+ var self = this;
127
+ this.debounce = requestAnimationFrame(function() {self.update();});
128
+ if (this.widget) this.widget.disable();
129
+ }
130
+ },
131
+
132
+ update: function(first) {
133
+ if (this.tick == null) return
134
+ var self = this, myTick = ++this.tick
135
+ fetchHints(this.options.hint, this.cm, this.options, function(data) {
136
+ if (self.tick == myTick) self.finishUpdate(data, first)
137
+ })
138
+ },
139
+
140
+ finishUpdate: function(data, first) {
141
+ if (this.data) CodeMirror.signal(this.data, "update");
142
+
143
+ var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
144
+ if (this.widget) this.widget.close();
145
+
146
+ this.data = data;
147
+
148
+ if (data && data.list.length) {
149
+ if (picked && data.list.length == 1) {
150
+ this.pick(data, 0);
151
+ } else {
152
+ this.widget = new Widget(this, data);
153
+ CodeMirror.signal(data, "shown");
154
+ }
155
+ }
156
+ }
157
+ };
158
+
159
+ function parseOptions(cm, pos, options) {
160
+ var editor = cm.options.hintOptions;
161
+ var out = {};
162
+ for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
163
+ if (editor) for (var prop in editor)
164
+ if (editor[prop] !== undefined) out[prop] = editor[prop];
165
+ if (options) for (var prop in options)
166
+ if (options[prop] !== undefined) out[prop] = options[prop];
167
+ if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
168
+ return out;
169
+ }
170
+
171
+ function getText(completion) {
172
+ if (typeof completion == "string") return completion;
173
+ else return completion.text;
174
+ }
175
+
176
+ function buildKeyMap(completion, handle) {
177
+ var baseMap = {
178
+ Up: function() {handle.moveFocus(-1);},
179
+ Down: function() {handle.moveFocus(1);},
180
+ PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
181
+ PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
182
+ Home: function() {handle.setFocus(0);},
183
+ End: function() {handle.setFocus(handle.length - 1);},
184
+ Enter: handle.pick,
185
+ Tab: handle.pick,
186
+ Esc: handle.close
187
+ };
188
+
189
+ var mac = /Mac/.test(navigator.platform);
190
+
191
+ if (mac) {
192
+ baseMap["Ctrl-P"] = function() {handle.moveFocus(-1);};
193
+ baseMap["Ctrl-N"] = function() {handle.moveFocus(1);};
194
+ }
195
+
196
+ var custom = completion.options.customKeys;
197
+ var ourMap = custom ? {} : baseMap;
198
+ function addBinding(key, val) {
199
+ var bound;
200
+ if (typeof val != "string")
201
+ bound = function(cm) { return val(cm, handle); };
202
+ // This mechanism is deprecated
203
+ else if (baseMap.hasOwnProperty(val))
204
+ bound = baseMap[val];
205
+ else
206
+ bound = val;
207
+ ourMap[key] = bound;
208
+ }
209
+ if (custom)
210
+ for (var key in custom) if (custom.hasOwnProperty(key))
211
+ addBinding(key, custom[key]);
212
+ var extra = completion.options.extraKeys;
213
+ if (extra)
214
+ for (var key in extra) if (extra.hasOwnProperty(key))
215
+ addBinding(key, extra[key]);
216
+ return ourMap;
217
+ }
218
+
219
+ function getHintElement(hintsElement, el) {
220
+ while (el && el != hintsElement) {
221
+ if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
222
+ el = el.parentNode;
223
+ }
224
+ }
225
+
226
+ function Widget(completion, data) {
227
+ this.id = "cm-complete-" + Math.floor(Math.random(1e6))
228
+ this.completion = completion;
229
+ this.data = data;
230
+ this.picked = false;
231
+ var widget = this, cm = completion.cm;
232
+ var ownerDocument = cm.getInputField().ownerDocument;
233
+ var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow;
234
+
235
+ var hints = this.hints = ownerDocument.createElement("ul");
236
+ hints.setAttribute("role", "listbox")
237
+ hints.setAttribute("aria-expanded", "true")
238
+ hints.id = this.id
239
+ var theme = completion.cm.options.theme;
240
+ hints.className = "CodeMirror-hints " + theme;
241
+ this.selectedHint = data.selectedHint || 0;
242
+
243
+ var completions = data.list;
244
+ for (var i = 0; i < completions.length; ++i) {
245
+ var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i];
246
+ var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
247
+ if (cur.className != null) className = cur.className + " " + className;
248
+ elt.className = className;
249
+ if (i == this.selectedHint) elt.setAttribute("aria-selected", "true")
250
+ elt.id = this.id + "-" + i
251
+ elt.setAttribute("role", "option")
252
+ if (cur.render) cur.render(elt, data, cur);
253
+ else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)));
254
+ elt.hintId = i;
255
+ }
256
+
257
+ var container = completion.options.container || ownerDocument.body;
258
+ var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
259
+ var left = pos.left, top = pos.bottom, below = true;
260
+ var offsetLeft = 0, offsetTop = 0;
261
+ if (container !== ownerDocument.body) {
262
+ // We offset the cursor position because left and top are relative to the offsetParent's top left corner.
263
+ var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1;
264
+ var offsetParent = isContainerPositioned ? container : container.offsetParent;
265
+ var offsetParentPosition = offsetParent.getBoundingClientRect();
266
+ var bodyPosition = ownerDocument.body.getBoundingClientRect();
267
+ offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft);
268
+ offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop);
269
+ }
270
+ hints.style.left = (left - offsetLeft) + "px";
271
+ hints.style.top = (top - offsetTop) + "px";
272
+
273
+ // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
274
+ var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
275
+ var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
276
+ container.appendChild(hints);
277
+ cm.getInputField().setAttribute("aria-autocomplete", "list")
278
+ cm.getInputField().setAttribute("aria-owns", this.id)
279
+ cm.getInputField().setAttribute("aria-activedescendant", this.id + "-" + this.selectedHint)
280
+
281
+ var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect();
282
+ var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false;
283
+
284
+ // Compute in the timeout to avoid reflow on init
285
+ var startScroll;
286
+ setTimeout(function() { startScroll = cm.getScrollInfo(); });
287
+
288
+ var overlapY = box.bottom - winH;
289
+ if (overlapY > 0) {
290
+ var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
291
+ if (curTop - height > 0) { // Fits above cursor
292
+ hints.style.top = (top = pos.top - height - offsetTop) + "px";
293
+ below = false;
294
+ } else if (height > winH) {
295
+ hints.style.height = (winH - 5) + "px";
296
+ hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px";
297
+ var cursor = cm.getCursor();
298
+ if (data.from.ch != cursor.ch) {
299
+ pos = cm.cursorCoords(cursor);
300
+ hints.style.left = (left = pos.left - offsetLeft) + "px";
301
+ box = hints.getBoundingClientRect();
302
+ }
303
+ }
304
+ }
305
+ var overlapX = box.right - winW;
306
+ if (scrolls) overlapX += cm.display.nativeBarWidth;
307
+ if (overlapX > 0) {
308
+ if (box.right - box.left > winW) {
309
+ hints.style.width = (winW - 5) + "px";
310
+ overlapX -= (box.right - box.left) - winW;
311
+ }
312
+ hints.style.left = (left = pos.left - overlapX - offsetLeft) + "px";
313
+ }
314
+ if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
315
+ node.style.paddingRight = cm.display.nativeBarWidth + "px"
316
+
317
+ cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
318
+ moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
319
+ setFocus: function(n) { widget.changeActive(n); },
320
+ menuSize: function() { return widget.screenAmount(); },
321
+ length: completions.length,
322
+ close: function() { completion.close(); },
323
+ pick: function() { widget.pick(); },
324
+ data: data
325
+ }));
326
+
327
+ if (completion.options.closeOnUnfocus) {
328
+ var closingOnBlur;
329
+ cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
330
+ cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
331
+ }
332
+
333
+ cm.on("scroll", this.onScroll = function() {
334
+ var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
335
+ if (!startScroll) startScroll = cm.getScrollInfo();
336
+ var newTop = top + startScroll.top - curScroll.top;
337
+ var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
338
+ if (!below) point += hints.offsetHeight;
339
+ if (point <= editor.top || point >= editor.bottom) return completion.close();
340
+ hints.style.top = newTop + "px";
341
+ hints.style.left = (left + startScroll.left - curScroll.left) + "px";
342
+ });
343
+
344
+ CodeMirror.on(hints, "dblclick", function(e) {
345
+ var t = getHintElement(hints, e.target || e.srcElement);
346
+ if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
347
+ });
348
+
349
+ CodeMirror.on(hints, "click", function(e) {
350
+ var t = getHintElement(hints, e.target || e.srcElement);
351
+ if (t && t.hintId != null) {
352
+ widget.changeActive(t.hintId);
353
+ if (completion.options.completeOnSingleClick) widget.pick();
354
+ }
355
+ });
356
+
357
+ CodeMirror.on(hints, "mousedown", function() {
358
+ setTimeout(function(){cm.focus();}, 20);
359
+ });
360
+
361
+ // The first hint doesn't need to be scrolled to on init
362
+ var selectedHintRange = this.getSelectedHintRange();
363
+ if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) {
364
+ this.scrollToActive();
365
+ }
366
+
367
+ CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
368
+ return true;
369
+ }
370
+
371
+ Widget.prototype = {
372
+ close: function() {
373
+ if (this.completion.widget != this) return;
374
+ this.completion.widget = null;
375
+ if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints);
376
+ this.completion.cm.removeKeyMap(this.keyMap);
377
+ var input = this.completion.cm.getInputField()
378
+ input.removeAttribute("aria-activedescendant")
379
+ input.removeAttribute("aria-owns")
380
+
381
+ var cm = this.completion.cm;
382
+ if (this.completion.options.closeOnUnfocus) {
383
+ cm.off("blur", this.onBlur);
384
+ cm.off("focus", this.onFocus);
385
+ }
386
+ cm.off("scroll", this.onScroll);
387
+ },
388
+
389
+ disable: function() {
390
+ this.completion.cm.removeKeyMap(this.keyMap);
391
+ var widget = this;
392
+ this.keyMap = {Enter: function() { widget.picked = true; }};
393
+ this.completion.cm.addKeyMap(this.keyMap);
394
+ },
395
+
396
+ pick: function() {
397
+ this.completion.pick(this.data, this.selectedHint);
398
+ },
399
+
400
+ changeActive: function(i, avoidWrap) {
401
+ if (i >= this.data.list.length)
402
+ i = avoidWrap ? this.data.list.length - 1 : 0;
403
+ else if (i < 0)
404
+ i = avoidWrap ? 0 : this.data.list.length - 1;
405
+ if (this.selectedHint == i) return;
406
+ var node = this.hints.childNodes[this.selectedHint];
407
+ if (node) {
408
+ node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
409
+ node.removeAttribute("aria-selected")
410
+ }
411
+ node = this.hints.childNodes[this.selectedHint = i];
412
+ node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
413
+ node.setAttribute("aria-selected", "true")
414
+ this.completion.cm.getInputField().setAttribute("aria-activedescendant", node.id)
415
+ this.scrollToActive()
416
+ CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
417
+ },
418
+
419
+ scrollToActive: function() {
420
+ var selectedHintRange = this.getSelectedHintRange();
421
+ var node1 = this.hints.childNodes[selectedHintRange.from];
422
+ var node2 = this.hints.childNodes[selectedHintRange.to];
423
+ var firstNode = this.hints.firstChild;
424
+ if (node1.offsetTop < this.hints.scrollTop)
425
+ this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
426
+ else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
427
+ this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
428
+ },
429
+
430
+ screenAmount: function() {
431
+ return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
432
+ },
433
+
434
+ getSelectedHintRange: function() {
435
+ var margin = this.completion.options.scrollMargin || 0;
436
+ return {
437
+ from: Math.max(0, this.selectedHint - margin),
438
+ to: Math.min(this.data.list.length - 1, this.selectedHint + margin),
439
+ };
440
+ }
441
+ };
442
+
443
+ function applicableHelpers(cm, helpers) {
444
+ if (!cm.somethingSelected()) return helpers
445
+ var result = []
446
+ for (var i = 0; i < helpers.length; i++)
447
+ if (helpers[i].supportsSelection) result.push(helpers[i])
448
+ return result
449
+ }
450
+
451
+ function fetchHints(hint, cm, options, callback) {
452
+ if (hint.async) {
453
+ hint(cm, callback, options)
454
+ } else {
455
+ var result = hint(cm, options)
456
+ if (result && result.then) result.then(callback)
457
+ else callback(result)
458
+ }
459
+ }
460
+
461
+ function resolveAutoHints(cm, pos) {
462
+ var helpers = cm.getHelpers(pos, "hint"), words
463
+ if (helpers.length) {
464
+ var resolved = function(cm, callback, options) {
465
+ var app = applicableHelpers(cm, helpers);
466
+ function run(i) {
467
+ if (i == app.length) return callback(null)
468
+ fetchHints(app[i], cm, options, function(result) {
469
+ if (result && result.list.length > 0) callback(result)
470
+ else run(i + 1)
471
+ })
472
+ }
473
+ run(0)
474
+ }
475
+ resolved.async = true
476
+ resolved.supportsSelection = true
477
+ return resolved
478
+ } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
479
+ return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
480
+ } else if (CodeMirror.hint.anyword) {
481
+ return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
482
+ } else {
483
+ return function() {}
484
+ }
485
+ }
486
+
487
+ CodeMirror.registerHelper("hint", "auto", {
488
+ resolve: resolveAutoHints
489
+ });
490
+
491
+ CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
492
+ var cur = cm.getCursor(), token = cm.getTokenAt(cur)
493
+ var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
494
+ if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
495
+ term = token.string.substr(0, cur.ch - token.start)
496
+ } else {
497
+ term = ""
498
+ from = cur
499
+ }
500
+ var found = [];
501
+ for (var i = 0; i < options.words.length; i++) {
502
+ var word = options.words[i];
503
+ if (word.slice(0, term.length) == term)
504
+ found.push(word);
505
+ }
506
+
507
+ if (found.length) return {list: found, from: from, to: to};
508
+ });
509
+
510
+ CodeMirror.commands.autocomplete = CodeMirror.showHint;
511
+
512
+ var defaultOptions = {
513
+ hint: CodeMirror.hint.auto,
514
+ completeSingle: true,
515
+ alignWithWord: true,
516
+ closeCharacters: /[\s()\[\]{};:>,]/,
517
+ closeOnPick: true,
518
+ closeOnUnfocus: true,
519
+ updateOnCursorActivity: true,
520
+ completeOnSingleClick: true,
521
+ container: null,
522
+ customKeys: null,
523
+ extraKeys: null,
524
+ paddingForScrollbar: true,
525
+ moveOnOverlap: true,
526
+ };
527
+
528
+ CodeMirror.defineOption("hintOptions", null);
529
+ });
@@ -0,0 +1,140 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: https://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var Pos = CodeMirror.Pos;
15
+
16
+ function matches(hint, typed, matchInMiddle) {
17
+ if (matchInMiddle) return hint.indexOf(typed) >= 0;
18
+ else return hint.lastIndexOf(typed, 0) == 0;
19
+ }
20
+
21
+ function getHints(cm, options) {
22
+ var tags = options && options.schemaInfo;
23
+ var quote = (options && options.quoteChar) || '"';
24
+ var matchInMiddle = options && options.matchInMiddle;
25
+ if (!tags) return;
26
+ var cur = cm.getCursor(), token = cm.getTokenAt(cur);
27
+ if (token.end > cur.ch) {
28
+ token.end = cur.ch;
29
+ token.string = token.string.slice(0, cur.ch - token.start);
30
+ }
31
+ var inner = CodeMirror.innerMode(cm.getMode(), token.state);
32
+ if (!inner.mode.xmlCurrentTag) return
33
+ var result = [], replaceToken = false, prefix;
34
+ var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
35
+ var tagName = tag && /^\w/.test(token.string), tagStart;
36
+
37
+ if (tagName) {
38
+ var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
39
+ var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
40
+ if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
41
+ } else if (tag && token.string == "<") {
42
+ tagType = "open";
43
+ } else if (tag && token.string == "</") {
44
+ tagType = "close";
45
+ }
46
+
47
+ var tagInfo = inner.mode.xmlCurrentTag(inner.state)
48
+ if (!tag && !tagInfo || tagType) {
49
+ if (tagName)
50
+ prefix = token.string;
51
+ replaceToken = tagType;
52
+ var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
53
+ var inner = context.length && context[context.length - 1]
54
+ var curTag = inner && tags[inner]
55
+ var childList = inner ? curTag && curTag.children : tags["!top"];
56
+ if (childList && tagType != "close") {
57
+ for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
58
+ result.push("<" + childList[i]);
59
+ } else if (tagType != "close") {
60
+ for (var name in tags)
61
+ if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
62
+ result.push("<" + name);
63
+ }
64
+ if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
65
+ result.push("</" + inner + ">");
66
+ } else {
67
+ // Attribute completion
68
+ var curTag = tagInfo && tags[tagInfo.name], attrs = curTag && curTag.attrs, attrDelims = curTag && curTag.attrDelims;
69
+ var globalAttrs = tags["!attrs"];
70
+ if (!attrs && !globalAttrs) return;
71
+ if (!attrs) {
72
+ attrs = globalAttrs;
73
+ } else if (globalAttrs) { // Combine tag-local and global attributes
74
+ var set = {};
75
+ for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
76
+ for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
77
+ attrs = set;
78
+ }
79
+ if (token.type == "string" || token.string == "=") { // A value
80
+ var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
81
+ Pos(cur.line, token.type == "string" ? token.start : token.end));
82
+ var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
83
+ if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
84
+ if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
85
+ let atValueDelim = (attrDelims && attrDelims[atName[1]]);
86
+ if (token.type == "string") {
87
+ prefix = token.string;
88
+ var n = 0;
89
+ if (/['"]/.test(token.string.charAt(0))) {
90
+ quote = token.string.charAt(0);
91
+ prefix = token.string.slice(1);
92
+ n++;
93
+ }
94
+ var len = token.string.length;
95
+ if (/['"]/.test(token.string.charAt(len - 1))) {
96
+ quote = token.string.charAt(len - 1);
97
+ prefix = token.string.substr(n, len - 2);
98
+ }
99
+ if (n) { // an opening quote
100
+ var line = cm.getLine(cur.line);
101
+ if (line.length > token.end && line.charAt(token.end) == quote) token.end++; // include a closing quote
102
+ }
103
+ replaceToken = true;
104
+ }
105
+ var returnHintsFromAtValues = function(atValues) {
106
+ let search = prefix,
107
+ preprefix = '';
108
+ if (atValueDelim) {
109
+ let spaceIdx = prefix.lastIndexOf(atValueDelim);
110
+ search = prefix.substr(spaceIdx + 1);
111
+ preprefix = prefix.substr(0, spaceIdx + 1);
112
+ }
113
+ if (atValues)
114
+ for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], search, matchInMiddle))
115
+ result.push(quote + preprefix + atValues[i] + quote);
116
+ return returnHints();
117
+ };
118
+ if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
119
+ return returnHintsFromAtValues(atValues);
120
+ } else { // An attribute name
121
+ if (token.type == "attribute") {
122
+ prefix = token.string;
123
+ replaceToken = true;
124
+ }
125
+ for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || matches(attr, prefix, matchInMiddle)))
126
+ result.push(attr);
127
+ }
128
+ }
129
+ function returnHints() {
130
+ return {
131
+ list: result,
132
+ from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
133
+ to: replaceToken ? Pos(cur.line, token.end) : cur
134
+ };
135
+ }
136
+ return returnHints();
137
+ }
138
+
139
+ CodeMirror.registerHelper("hint", "xml", getHints);
140
+ });