tiny-markdown-editor 0.1.3 → 0.1.5
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 +2 -2
- package/dist/tiny-mde.css +2 -6
- package/dist/tiny-mde.js +5488 -5066
- package/dist/tiny-mde.min.css +1 -1
- package/dist/tiny-mde.min.js +1 -1
- package/dist/tiny-mde.tiny.js +1 -1
- package/lib/TinyMDE.js +265 -506
- package/lib/TinyMDECommandBar.js +27 -102
- package/lib/grammar.js +102 -111
- package/lib/index.js +1 -3
- package/lib/svg/svg.js +1 -0
- package/lib/tiny.js +1 -2
- package/package.json +17 -17
package/lib/TinyMDE.js
CHANGED
|
@@ -1,122 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
require("core-js/modules/es.
|
|
4
|
-
|
|
5
|
-
require("core-js/modules/es.
|
|
6
|
-
|
|
7
|
-
require("core-js/modules/es.symbol.
|
|
8
|
-
|
|
9
|
-
require("core-js/modules/es.symbol.
|
|
10
|
-
|
|
11
|
-
require("core-js/modules/
|
|
12
|
-
|
|
13
|
-
require("core-js/modules/es.
|
|
14
|
-
|
|
15
|
-
require("core-js/modules/es.
|
|
16
|
-
|
|
17
|
-
require("core-js/modules/es.
|
|
18
|
-
|
|
19
|
-
require("core-js/modules/es.array.iterator");
|
|
20
|
-
|
|
21
|
-
require("core-js/modules/es.array.join");
|
|
22
|
-
|
|
23
|
-
require("core-js/modules/es.array.reduce");
|
|
24
|
-
|
|
25
|
-
require("core-js/modules/es.array.slice");
|
|
26
|
-
|
|
27
|
-
require("core-js/modules/es.array.splice");
|
|
28
|
-
|
|
29
|
-
require("core-js/modules/es.function.name");
|
|
30
|
-
|
|
31
|
-
require("core-js/modules/es.map");
|
|
32
|
-
|
|
33
|
-
require("core-js/modules/es.object.assign");
|
|
34
|
-
|
|
35
|
-
require("core-js/modules/es.object.get-prototype-of");
|
|
36
|
-
|
|
37
|
-
require("core-js/modules/es.object.keys");
|
|
38
|
-
|
|
39
|
-
require("core-js/modules/es.object.to-string");
|
|
40
|
-
|
|
41
|
-
require("core-js/modules/es.reflect.construct");
|
|
42
|
-
|
|
43
|
-
require("core-js/modules/es.regexp.constructor");
|
|
44
|
-
|
|
45
|
-
require("core-js/modules/es.regexp.exec");
|
|
46
|
-
|
|
47
|
-
require("core-js/modules/es.regexp.to-string");
|
|
48
|
-
|
|
49
|
-
require("core-js/modules/es.string.includes");
|
|
50
|
-
|
|
51
|
-
require("core-js/modules/es.string.iterator");
|
|
52
|
-
|
|
53
|
-
require("core-js/modules/es.string.match");
|
|
54
|
-
|
|
55
|
-
require("core-js/modules/es.string.replace");
|
|
56
|
-
|
|
57
|
-
require("core-js/modules/es.string.split");
|
|
58
|
-
|
|
59
|
-
require("core-js/modules/es.string.trim");
|
|
60
|
-
|
|
61
|
-
require("core-js/modules/es.weak-map");
|
|
62
|
-
|
|
63
|
-
require("core-js/modules/web.dom-collections.iterator");
|
|
64
|
-
|
|
3
|
+
require("core-js/modules/es.array.slice.js");
|
|
4
|
+
require("core-js/modules/es.object.to-string.js");
|
|
5
|
+
require("core-js/modules/es.array.from.js");
|
|
6
|
+
require("core-js/modules/es.string.iterator.js");
|
|
7
|
+
require("core-js/modules/es.symbol.js");
|
|
8
|
+
require("core-js/modules/es.symbol.description.js");
|
|
9
|
+
require("core-js/modules/es.symbol.iterator.js");
|
|
10
|
+
require("core-js/modules/es.array.iterator.js");
|
|
11
|
+
require("core-js/modules/web.dom-collections.iterator.js");
|
|
12
|
+
require("core-js/modules/es.object.set-prototype-of.js");
|
|
13
|
+
require("core-js/modules/es.regexp.constructor.js");
|
|
14
|
+
require("core-js/modules/es.regexp.to-string.js");
|
|
15
|
+
require("core-js/modules/es.weak-map.js");
|
|
16
|
+
require("core-js/modules/es.array.reduce.js");
|
|
17
|
+
require("core-js/modules/es.object.keys.js");
|
|
18
|
+
require("core-js/modules/es.symbol.replace.js");
|
|
65
19
|
Object.defineProperty(exports, "__esModule", {
|
|
66
20
|
value: true
|
|
67
21
|
});
|
|
68
22
|
exports.default = void 0;
|
|
69
|
-
|
|
23
|
+
require("core-js/modules/es.regexp.exec.js");
|
|
24
|
+
require("core-js/modules/es.string.split.js");
|
|
25
|
+
require("core-js/modules/es.string.replace.js");
|
|
26
|
+
require("core-js/modules/es.string.match.js");
|
|
27
|
+
require("core-js/modules/es.string.trim.js");
|
|
28
|
+
require("core-js/modules/es.array.concat.js");
|
|
29
|
+
require("core-js/modules/es.parse-int.js");
|
|
30
|
+
require("core-js/modules/es.array.splice.js");
|
|
31
|
+
require("core-js/modules/es.array.includes.js");
|
|
32
|
+
require("core-js/modules/es.string.includes.js");
|
|
33
|
+
require("core-js/modules/es.object.assign.js");
|
|
34
|
+
require("core-js/modules/es.object.define-property.js");
|
|
70
35
|
var _grammar = require("./grammar");
|
|
71
|
-
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
75
|
-
|
|
76
|
-
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
|
77
|
-
|
|
78
|
-
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
79
|
-
|
|
80
|
-
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
|
|
81
|
-
|
|
82
|
-
function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
|
|
83
|
-
|
|
84
|
-
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
|
|
85
|
-
|
|
86
|
-
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }
|
|
87
|
-
|
|
88
|
-
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
89
|
-
|
|
90
|
-
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
91
|
-
|
|
36
|
+
function _wrapRegExp() { _wrapRegExp = function _wrapRegExp(re, groups) { return new BabelRegExp(re, void 0, groups); }; var _super = RegExp.prototype, _groups = new WeakMap(); function BabelRegExp(re, flags, groups) { var _this = new RegExp(re, flags); return _groups.set(_this, groups || _groups.get(re)), _setPrototypeOf(_this, BabelRegExp.prototype); } function buildGroups(result, re) { var g = _groups.get(re); return Object.keys(g).reduce(function (groups, name) { var i = g[name]; if ("number" == typeof i) groups[name] = result[i];else { for (var k = 0; void 0 === result[i[k]] && k + 1 < i.length;) { k++; } groups[name] = result[i[k]]; } return groups; }, Object.create(null)); } return _inherits(BabelRegExp, RegExp), BabelRegExp.prototype.exec = function (str) { var result = _super.exec.call(this, str); if (result) { result.groups = buildGroups(result, this); var indices = result.indices; indices && (indices.groups = buildGroups(indices, this)); } return result; }, BabelRegExp.prototype[Symbol.replace] = function (str, substitution) { if ("string" == typeof substitution) { var groups = _groups.get(this); return _super[Symbol.replace].call(this, str, substitution.replace(/\$<([^>]+)>/g, function (_, name) { var group = groups[name]; return "$" + (Array.isArray(group) ? group.join("$") : group); })); } if ("function" == typeof substitution) { var _this = this; return _super[Symbol.replace].call(this, str, function () { var args = arguments; return "object" != _typeof(args[args.length - 1]) && (args = [].slice.call(args)).push(buildGroups(args, _this)), substitution.apply(this, args); }); } return _super[Symbol.replace].call(this, str, substitution); }, _wrapRegExp.apply(this, arguments); }
|
|
37
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
38
|
+
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
92
39
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
93
|
-
|
|
94
40
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
95
|
-
|
|
96
|
-
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
|
|
97
|
-
|
|
41
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
98
42
|
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
99
|
-
|
|
100
|
-
function
|
|
101
|
-
|
|
102
|
-
function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
103
|
-
|
|
43
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
44
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
104
45
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
105
|
-
|
|
106
46
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
107
|
-
|
|
108
47
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
109
|
-
|
|
110
48
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
111
|
-
|
|
112
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
113
|
-
|
|
49
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
114
50
|
var Editor = /*#__PURE__*/function () {
|
|
115
51
|
function Editor() {
|
|
116
52
|
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
117
|
-
|
|
118
53
|
_classCallCheck(this, Editor);
|
|
119
|
-
|
|
120
54
|
this.e = null;
|
|
121
55
|
this.textarea = null;
|
|
122
56
|
this.lines = [];
|
|
@@ -133,77 +67,67 @@ var Editor = /*#__PURE__*/function () {
|
|
|
133
67
|
};
|
|
134
68
|
var element = props.element;
|
|
135
69
|
this.textarea = props.textarea;
|
|
136
|
-
|
|
137
70
|
if (this.textarea && !this.textarea.tagName) {
|
|
138
71
|
this.textarea = document.getElementById(this.textarea);
|
|
139
72
|
if (!element) element = this.textarea;
|
|
140
73
|
}
|
|
141
|
-
|
|
142
74
|
if (element && !element.tagName) {
|
|
143
75
|
element = document.getElementById(props.element);
|
|
144
76
|
}
|
|
145
|
-
|
|
146
77
|
if (!element) {
|
|
147
78
|
element = document.getElementsByTagName('body')[0];
|
|
148
79
|
}
|
|
149
|
-
|
|
150
80
|
if (element.tagName == 'TEXTAREA') {
|
|
151
81
|
this.textarea = element;
|
|
152
82
|
element = this.textarea.parentNode;
|
|
153
83
|
}
|
|
154
|
-
|
|
155
84
|
if (this.textarea) {
|
|
156
85
|
this.textarea.style.display = 'none';
|
|
157
86
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
87
|
+
this.createEditorElement(element);
|
|
88
|
+
// TODO Placeholder for empty content
|
|
161
89
|
this.setContent(props.content || (this.textarea ? this.textarea.value : false) || '# Hello TinyMDE!\nEdit **here**');
|
|
162
90
|
}
|
|
91
|
+
|
|
163
92
|
/**
|
|
164
93
|
* Creates the editor element inside the target element of the DOM tree
|
|
165
94
|
* @param element The target element of the DOM tree
|
|
166
95
|
*/
|
|
167
|
-
|
|
168
|
-
|
|
169
96
|
_createClass(Editor, [{
|
|
170
97
|
key: "createEditorElement",
|
|
171
98
|
value: function createEditorElement(element) {
|
|
172
99
|
var _this = this;
|
|
173
|
-
|
|
174
100
|
this.e = document.createElement('div');
|
|
175
101
|
this.e.className = 'TinyMDE';
|
|
176
|
-
this.e.contentEditable = true;
|
|
102
|
+
this.e.contentEditable = true;
|
|
103
|
+
// The following is important for formatting purposes, but also since otherwise the browser replaces subsequent spaces with
|
|
177
104
|
// That breaks a lot of stuff, so we do this here and not in CSS—therefore, you don't have to remember to but this in the CSS file
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
105
|
+
this.e.style.whiteSpace = 'pre-wrap';
|
|
106
|
+
// Avoid formatting (B / I / U) popping up on iOS
|
|
181
107
|
this.e.style.webkitUserModify = 'read-write-plaintext-only';
|
|
182
|
-
|
|
183
108
|
if (this.textarea && this.textarea.parentNode == element && this.textarea.nextSibling) {
|
|
184
109
|
element.insertBefore(this.e, this.textarea.nextSibling);
|
|
185
110
|
} else {
|
|
186
111
|
element.appendChild(this.e);
|
|
187
112
|
}
|
|
188
|
-
|
|
189
113
|
this.e.addEventListener("input", function (e) {
|
|
190
114
|
return _this.handleInputEvent(e);
|
|
191
|
-
});
|
|
192
|
-
|
|
115
|
+
});
|
|
116
|
+
// this.e.addEventListener("keydown", (e) => this.handleKeydownEvent(e));
|
|
193
117
|
document.addEventListener("selectionchange", function (e) {
|
|
194
118
|
return _this.handleSelectionChangeEvent(e);
|
|
195
119
|
});
|
|
196
120
|
this.e.addEventListener("paste", function (e) {
|
|
197
121
|
return _this.handlePaste(e);
|
|
198
|
-
});
|
|
199
|
-
|
|
122
|
+
});
|
|
123
|
+
// this.e.addEventListener('keydown', (e) => this.handleKeyDown(e));
|
|
200
124
|
this.lineElements = this.e.childNodes; // this will automatically update
|
|
201
125
|
}
|
|
126
|
+
|
|
202
127
|
/**
|
|
203
128
|
* Sets the editor content.
|
|
204
129
|
* @param {string} content The new Markdown content
|
|
205
130
|
*/
|
|
206
|
-
|
|
207
131
|
}, {
|
|
208
132
|
key: "setContent",
|
|
209
133
|
value: function setContent(content) {
|
|
@@ -211,60 +135,57 @@ var Editor = /*#__PURE__*/function () {
|
|
|
211
135
|
while (this.e.firstChild) {
|
|
212
136
|
this.e.removeChild(this.e.firstChild);
|
|
213
137
|
}
|
|
214
|
-
|
|
215
138
|
this.lines = content.split(/(?:\r\n|\r|\n)/);
|
|
216
139
|
this.lineDirty = [];
|
|
217
|
-
|
|
218
140
|
for (var lineNum = 0; lineNum < this.lines.length; lineNum++) {
|
|
219
141
|
var le = document.createElement('div');
|
|
220
142
|
this.e.appendChild(le);
|
|
221
143
|
this.lineDirty.push(true);
|
|
222
144
|
}
|
|
223
|
-
|
|
224
145
|
this.lineTypes = new Array(this.lines.length);
|
|
225
146
|
this.updateFormatting();
|
|
226
147
|
this.fireChange();
|
|
227
148
|
}
|
|
149
|
+
|
|
228
150
|
/**
|
|
229
151
|
* Gets the editor content as a Markdown string.
|
|
230
152
|
* @returns {string} The editor content as a markdown string
|
|
231
153
|
*/
|
|
232
|
-
|
|
233
154
|
}, {
|
|
234
155
|
key: "getContent",
|
|
235
156
|
value: function getContent() {
|
|
236
157
|
return this.lines.join('\n');
|
|
237
158
|
}
|
|
159
|
+
|
|
238
160
|
/**
|
|
239
161
|
* This is the main method to update the formatting (from this.lines to HTML output)
|
|
240
162
|
*/
|
|
241
|
-
|
|
242
163
|
}, {
|
|
243
164
|
key: "updateFormatting",
|
|
244
165
|
value: function updateFormatting() {
|
|
245
166
|
// First, parse line types. This will update this.lineTypes, this.lineReplacements, and this.lineCaptures
|
|
246
167
|
// We don't apply the formatting yet
|
|
247
|
-
this.updateLineTypes();
|
|
248
|
-
|
|
249
|
-
this.updateLinkLabels();
|
|
250
|
-
|
|
168
|
+
this.updateLineTypes();
|
|
169
|
+
// Collect any valid link labels from link reference definitions—we need that for formatting to determine what's a valid link
|
|
170
|
+
this.updateLinkLabels();
|
|
171
|
+
// Now, apply the formatting
|
|
251
172
|
this.applyLineTypes();
|
|
252
173
|
}
|
|
174
|
+
|
|
253
175
|
/**
|
|
254
176
|
* Updates this.linkLabels: For every link reference definition (line type TMLinkReferenceDefinition), we collect the label
|
|
255
177
|
*/
|
|
256
|
-
|
|
257
178
|
}, {
|
|
258
179
|
key: "updateLinkLabels",
|
|
259
180
|
value: function updateLinkLabels() {
|
|
260
181
|
this.linkLabels = [];
|
|
261
|
-
|
|
262
182
|
for (var l = 0; l < this.lines.length; l++) {
|
|
263
183
|
if (this.lineTypes[l] == 'TMLinkReferenceDefinition') {
|
|
264
184
|
this.linkLabels.push(this.lineCaptures[l][_grammar.lineGrammar.TMLinkReferenceDefinition.labelPlaceholder]);
|
|
265
185
|
}
|
|
266
186
|
}
|
|
267
187
|
}
|
|
188
|
+
|
|
268
189
|
/**
|
|
269
190
|
* Helper function to replace placeholders from a RegExp capture. The replacement string can contain regular dollar placeholders (e.g., $1),
|
|
270
191
|
* which are interpreted like in String.replace(), but also double dollar placeholders ($$1). In the case of double dollar placeholders,
|
|
@@ -275,30 +196,28 @@ var Editor = /*#__PURE__*/function () {
|
|
|
275
196
|
* @param capture The result of a RegExp.exec() call
|
|
276
197
|
* @returns The replacement string, with placeholders replaced from the capture result.
|
|
277
198
|
*/
|
|
278
|
-
|
|
279
199
|
}, {
|
|
280
200
|
key: "replace",
|
|
281
201
|
value: function replace(replacement, capture) {
|
|
282
202
|
var _this2 = this;
|
|
283
|
-
|
|
284
203
|
return replacement.replace(/\$\$([0-9])/g, function (str, p1) {
|
|
285
204
|
return "<span class=\"TMInlineFormatted\">".concat(_this2.processInlineStyles(capture[p1]), "</span>");
|
|
286
205
|
}).replace(/\$([0-9])/g, function (str, p1) {
|
|
287
206
|
return (0, _grammar.htmlescape)(capture[p1]);
|
|
288
207
|
});
|
|
289
208
|
}
|
|
209
|
+
|
|
290
210
|
/**
|
|
291
211
|
* Applies the line types (from this.lineTypes as well as the capture result in this.lineReplacements and this.lineCaptures)
|
|
292
212
|
* and processes inline formatting for all lines.
|
|
293
213
|
*/
|
|
294
|
-
|
|
295
214
|
}, {
|
|
296
215
|
key: "applyLineTypes",
|
|
297
216
|
value: function applyLineTypes() {
|
|
298
217
|
for (var lineNum = 0; lineNum < this.lines.length; lineNum++) {
|
|
299
218
|
if (this.lineDirty[lineNum]) {
|
|
300
|
-
var contentHTML = this.replace(this.lineReplacements[lineNum], this.lineCaptures[lineNum]);
|
|
301
|
-
|
|
219
|
+
var contentHTML = this.replace(this.lineReplacements[lineNum], this.lineCaptures[lineNum]);
|
|
220
|
+
// this.lineHTML[lineNum] = (contentHTML == '' ? '<br />' : contentHTML); // Prevent empty elements which can't be selected etc.
|
|
302
221
|
this.lineElements[lineNum].className = this.lineTypes[lineNum];
|
|
303
222
|
this.lineElements[lineNum].removeAttribute('style');
|
|
304
223
|
this.lineElements[lineNum].innerHTML = contentHTML == '' ? '<br />' : contentHTML; // Prevent empty elements which can't be selected etc.
|
|
@@ -307,30 +226,28 @@ var Editor = /*#__PURE__*/function () {
|
|
|
307
226
|
this.lineElements[lineNum].dataset.lineNum = lineNum;
|
|
308
227
|
}
|
|
309
228
|
}
|
|
229
|
+
|
|
310
230
|
/**
|
|
311
231
|
* Determines line types for all lines based on the line / block grammar. Captures the results of the respective line
|
|
312
232
|
* grammar regular expressions.
|
|
313
233
|
* Updates this.lineTypes, this.lineCaptures, and this.lineReplacements.
|
|
314
234
|
*/
|
|
315
|
-
|
|
316
235
|
}, {
|
|
317
236
|
key: "updateLineTypes",
|
|
318
237
|
value: function updateLineTypes() {
|
|
319
238
|
var codeBlockType = false;
|
|
320
239
|
var codeBlockSeqLength = 0;
|
|
321
240
|
var htmlBlock = false;
|
|
322
|
-
|
|
323
241
|
for (var lineNum = 0; lineNum < this.lines.length; lineNum++) {
|
|
324
242
|
var lineType = 'TMPara';
|
|
325
243
|
var lineCapture = [this.lines[lineNum]];
|
|
326
244
|
var lineReplacement = '$$0'; // Default replacement for paragraph: Inline format the entire line
|
|
245
|
+
|
|
327
246
|
// Check ongoing code blocks
|
|
328
247
|
// if (lineNum > 0 && (this.lineTypes[lineNum - 1] == 'TMCodeFenceBacktickOpen' || this.lineTypes[lineNum - 1] == 'TMFencedCodeBacktick')) {
|
|
329
|
-
|
|
330
248
|
if (codeBlockType == 'TMCodeFenceBacktickOpen') {
|
|
331
249
|
// We're in a backtick-fenced code block, check if the current line closes it
|
|
332
250
|
var capture = _grammar.lineGrammar.TMCodeFenceBacktickClose.regexp.exec(this.lines[lineNum]);
|
|
333
|
-
|
|
334
251
|
if (capture && capture.groups['seq'].length >= codeBlockSeqLength) {
|
|
335
252
|
lineType = 'TMCodeFenceBacktickClose';
|
|
336
253
|
lineReplacement = _grammar.lineGrammar.TMCodeFenceBacktickClose.replacement;
|
|
@@ -341,32 +258,30 @@ var Editor = /*#__PURE__*/function () {
|
|
|
341
258
|
lineReplacement = '$0';
|
|
342
259
|
lineCapture = [this.lines[lineNum]];
|
|
343
260
|
}
|
|
344
|
-
}
|
|
261
|
+
}
|
|
262
|
+
// if (lineNum > 0 && (this.lineTypes[lineNum - 1] == 'TMCodeFenceTildeOpen' || this.lineTypes[lineNum - 1] == 'TMFencedCodeTilde')) {
|
|
345
263
|
else if (codeBlockType == 'TMCodeFenceTildeOpen') {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
} // Check HTML block types
|
|
360
|
-
|
|
264
|
+
// We're in a tilde-fenced code block
|
|
265
|
+
var _capture = _grammar.lineGrammar.TMCodeFenceTildeClose.regexp.exec(this.lines[lineNum]);
|
|
266
|
+
if (_capture && _capture.groups['seq'].length >= codeBlockSeqLength) {
|
|
267
|
+
lineType = 'TMCodeFenceTildeClose';
|
|
268
|
+
lineReplacement = _grammar.lineGrammar.TMCodeFenceTildeClose.replacement;
|
|
269
|
+
lineCapture = _capture;
|
|
270
|
+
codeBlockType = false;
|
|
271
|
+
} else {
|
|
272
|
+
lineType = 'TMFencedCodeTilde';
|
|
273
|
+
lineReplacement = '$0';
|
|
274
|
+
lineCapture = [this.lines[lineNum]];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
361
277
|
|
|
278
|
+
// Check HTML block types
|
|
362
279
|
if (lineType == 'TMPara' && htmlBlock === false) {
|
|
363
280
|
var _iterator = _createForOfIteratorHelper(_grammar.htmlBlockGrammar),
|
|
364
|
-
|
|
365
|
-
|
|
281
|
+
_step;
|
|
366
282
|
try {
|
|
367
283
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
368
284
|
var htmlBlockType = _step.value;
|
|
369
|
-
|
|
370
285
|
if (this.lines[lineNum].match(htmlBlockType.start)) {
|
|
371
286
|
// Matching start condition. Check if this tag can start here (not all start conditions allow breaking a paragraph).
|
|
372
287
|
if (htmlBlockType.paraInterrupt || lineNum == 0 || !(this.lineTypes[lineNum - 1] == 'TMPara' || this.lineTypes[lineNum - 1] == 'TMUL' || this.lineTypes[lineNum - 1] == 'TMOL' || this.lineTypes[lineNum - 1] == 'TMBlockquote')) {
|
|
@@ -381,14 +296,12 @@ var Editor = /*#__PURE__*/function () {
|
|
|
381
296
|
_iterator.f();
|
|
382
297
|
}
|
|
383
298
|
}
|
|
384
|
-
|
|
385
299
|
if (htmlBlock !== false) {
|
|
386
300
|
lineType = 'TMHTMLBlock';
|
|
387
301
|
lineReplacement = '$0'; // No formatting in TMHTMLBlock
|
|
388
|
-
|
|
389
302
|
lineCapture = [this.lines[lineNum]]; // This should already be set but better safe than sorry
|
|
390
|
-
// Check if HTML block should be closed
|
|
391
303
|
|
|
304
|
+
// Check if HTML block should be closed
|
|
392
305
|
if (htmlBlock.end) {
|
|
393
306
|
// Specific end condition
|
|
394
307
|
if (this.lines[lineNum].match(htmlBlock.end)) {
|
|
@@ -400,14 +313,13 @@ var Editor = /*#__PURE__*/function () {
|
|
|
400
313
|
htmlBlock = false;
|
|
401
314
|
}
|
|
402
315
|
}
|
|
403
|
-
}
|
|
404
|
-
|
|
316
|
+
}
|
|
405
317
|
|
|
318
|
+
// Check all regexps if we haven't applied one of the code block types
|
|
406
319
|
if (lineType == 'TMPara') {
|
|
407
320
|
for (var type in _grammar.lineGrammar) {
|
|
408
321
|
if (_grammar.lineGrammar[type].regexp) {
|
|
409
322
|
var _capture2 = _grammar.lineGrammar[type].regexp.exec(this.lines[lineNum]);
|
|
410
|
-
|
|
411
323
|
if (_capture2) {
|
|
412
324
|
lineType = type;
|
|
413
325
|
lineReplacement = _grammar.lineGrammar[type].replacement;
|
|
@@ -416,39 +328,37 @@ var Editor = /*#__PURE__*/function () {
|
|
|
416
328
|
}
|
|
417
329
|
}
|
|
418
330
|
}
|
|
419
|
-
}
|
|
420
|
-
|
|
331
|
+
}
|
|
421
332
|
|
|
333
|
+
// If we've opened a code block, remember that
|
|
422
334
|
if (lineType == 'TMCodeFenceBacktickOpen' || lineType == 'TMCodeFenceTildeOpen') {
|
|
423
335
|
codeBlockType = lineType;
|
|
424
336
|
codeBlockSeqLength = lineCapture.groups['seq'].length;
|
|
425
|
-
}
|
|
426
|
-
|
|
337
|
+
}
|
|
427
338
|
|
|
339
|
+
// Link reference definition and indented code can't interrupt a paragraph
|
|
428
340
|
if ((lineType == 'TMIndentedCode' || lineType == 'TMLinkReferenceDefinition') && lineNum > 0 && (this.lineTypes[lineNum - 1] == 'TMPara' || this.lineTypes[lineNum - 1] == 'TMUL' || this.lineTypes[lineNum - 1] == 'TMOL' || this.lineTypes[lineNum - 1] == 'TMBlockquote')) {
|
|
429
341
|
// Fall back to TMPara
|
|
430
342
|
lineType = 'TMPara';
|
|
431
343
|
lineCapture = [this.lines[lineNum]];
|
|
432
344
|
lineReplacement = '$$0';
|
|
433
|
-
}
|
|
434
|
-
|
|
345
|
+
}
|
|
435
346
|
|
|
347
|
+
// Setext H2 markers that can also be interpreted as an empty list item should be regarded as such (as per CommonMark spec)
|
|
436
348
|
if (lineType == 'TMSetextH2Marker') {
|
|
437
349
|
var _capture3 = _grammar.lineGrammar.TMUL.regexp.exec(this.lines[lineNum]);
|
|
438
|
-
|
|
439
350
|
if (_capture3) {
|
|
440
351
|
lineType = 'TMUL';
|
|
441
352
|
lineReplacement = _grammar.lineGrammar.TMUL.replacement;
|
|
442
353
|
lineCapture = _capture3;
|
|
443
354
|
}
|
|
444
|
-
}
|
|
445
|
-
|
|
355
|
+
}
|
|
446
356
|
|
|
357
|
+
// Setext headings are only valid if preceded by a paragraph (and if so, they change the type of the previous paragraph)
|
|
447
358
|
if (lineType == 'TMSetextH1Marker' || lineType == 'TMSetextH2Marker') {
|
|
448
359
|
if (lineNum == 0 || this.lineTypes[lineNum - 1] != 'TMPara') {
|
|
449
360
|
// Setext marker is invalid. However, a H2 marker might still be a valid HR, so let's check that
|
|
450
361
|
var _capture4 = _grammar.lineGrammar.TMHR.regexp.exec(this.lines[lineNum]);
|
|
451
|
-
|
|
452
362
|
if (_capture4) {
|
|
453
363
|
// Valid HR
|
|
454
364
|
lineType = 'TMHR';
|
|
@@ -464,34 +374,30 @@ var Editor = /*#__PURE__*/function () {
|
|
|
464
374
|
// Valid setext marker. Change types of preceding para lines
|
|
465
375
|
var headingLine = lineNum - 1;
|
|
466
376
|
var headingLineType = lineType == 'TMSetextH1Marker' ? 'TMSetextH1' : 'TMSetextH2';
|
|
467
|
-
|
|
468
377
|
do {
|
|
469
378
|
if (this.lineTypes[headingLineType] != headingLineType) {
|
|
470
379
|
this.lineTypes[headingLine] = headingLineType;
|
|
471
380
|
this.lineDirty[headingLineType] = true;
|
|
472
381
|
}
|
|
473
|
-
|
|
474
382
|
this.lineReplacements[headingLine] = '$$0';
|
|
475
383
|
this.lineCaptures[headingLine] = [this.lines[headingLine]];
|
|
476
384
|
headingLine--;
|
|
477
385
|
} while (headingLine >= 0 && this.lineTypes[headingLine] == 'TMPara');
|
|
478
386
|
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
|
|
387
|
+
}
|
|
388
|
+
// Lastly, save the line style to be applied later
|
|
482
389
|
if (this.lineTypes[lineNum] != lineType) {
|
|
483
390
|
this.lineTypes[lineNum] = lineType;
|
|
484
391
|
this.lineDirty[lineNum] = true;
|
|
485
392
|
}
|
|
486
|
-
|
|
487
393
|
this.lineReplacements[lineNum] = lineReplacement;
|
|
488
394
|
this.lineCaptures[lineNum] = lineCapture;
|
|
489
395
|
}
|
|
490
396
|
}
|
|
397
|
+
|
|
491
398
|
/**
|
|
492
399
|
* Updates all line contents from the HTML, then re-applies formatting.
|
|
493
400
|
*/
|
|
494
|
-
|
|
495
401
|
}, {
|
|
496
402
|
key: "updateLineContentsAndFormatting",
|
|
497
403
|
value: function updateLineContentsAndFormatting() {
|
|
@@ -499,6 +405,7 @@ var Editor = /*#__PURE__*/function () {
|
|
|
499
405
|
this.updateLineContents();
|
|
500
406
|
this.updateFormatting();
|
|
501
407
|
}
|
|
408
|
+
|
|
502
409
|
/**
|
|
503
410
|
* Attempts to parse a link or image at the current position. This assumes that the opening [ or ![ has already been matched.
|
|
504
411
|
* Returns false if this is not a valid link, image. See below for more information
|
|
@@ -508,7 +415,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
508
415
|
* Otherwise returns an object with two properties: output is the string to be included in the processed output,
|
|
509
416
|
* charCount is the number of input characters (from originalString) consumed.
|
|
510
417
|
*/
|
|
511
|
-
|
|
512
418
|
}, {
|
|
513
419
|
key: "parseLinkOrImage",
|
|
514
420
|
value: function parseLinkOrImage(originalString, isImage) {
|
|
@@ -523,81 +429,74 @@ var Editor = /*#__PURE__*/function () {
|
|
|
523
429
|
var linkLabel = [];
|
|
524
430
|
var linkDetails = []; // If matched, this will be an array: [whitespace + link destination delimiter, link destination, link destination delimiter, whitespace, link title delimiter, link title, link title delimiter + whitespace]. All can be empty strings.
|
|
525
431
|
|
|
526
|
-
textOuter: while (currentOffset < originalString.length && linkText === false
|
|
527
|
-
|
|
528
|
-
) {
|
|
529
|
-
var string = originalString.substr(currentOffset); // Capture any escapes and code blocks at current position, they bind more strongly than links
|
|
530
|
-
// We don't have to actually process them here, that'll be done later in case the link / image is valid, but we need to skip over them.
|
|
432
|
+
textOuter: while (currentOffset < originalString.length && linkText === false /* empty string is okay */) {
|
|
433
|
+
var string = originalString.substr(currentOffset);
|
|
531
434
|
|
|
435
|
+
// Capture any escapes and code blocks at current position, they bind more strongly than links
|
|
436
|
+
// We don't have to actually process them here, that'll be done later in case the link / image is valid, but we need to skip over them.
|
|
532
437
|
for (var _i = 0, _arr = ['escape', 'code', 'autolink', 'html']; _i < _arr.length; _i++) {
|
|
533
438
|
var rule = _arr[_i];
|
|
534
|
-
|
|
535
439
|
var cap = _grammar.inlineGrammar[rule].regexp.exec(string);
|
|
536
|
-
|
|
537
440
|
if (cap) {
|
|
538
441
|
currentOffset += cap[0].length;
|
|
539
442
|
continue textOuter;
|
|
540
443
|
}
|
|
541
|
-
}
|
|
542
|
-
|
|
444
|
+
}
|
|
543
445
|
|
|
446
|
+
// Check for image. It's okay for an image to be included in a link or image
|
|
544
447
|
if (string.match(_grammar.inlineGrammar.imageOpen.regexp)) {
|
|
545
448
|
// Opening image. It's okay if this is a matching pair of brackets
|
|
546
449
|
bracketLevel++;
|
|
547
450
|
currentOffset += 2;
|
|
548
451
|
continue textOuter;
|
|
549
|
-
}
|
|
550
|
-
|
|
452
|
+
}
|
|
551
453
|
|
|
454
|
+
// Check for link (not an image because that would have been captured and skipped over above)
|
|
552
455
|
if (string.match(_grammar.inlineGrammar.linkOpen.regexp)) {
|
|
553
456
|
// Opening bracket. Two things to do:
|
|
554
457
|
// 1) it's okay if this part of a pair of brackets.
|
|
555
458
|
// 2) If we are currently trying to parse a link, this nested bracket musn't start a valid link (no nested links allowed)
|
|
556
|
-
bracketLevel++;
|
|
557
|
-
|
|
459
|
+
bracketLevel++;
|
|
460
|
+
// if (bracketLevel >= 2) return false; // Nested unescaped brackets, this doesn't qualify as a link / image
|
|
558
461
|
if (!isImage) {
|
|
559
462
|
if (this.parseLinkOrImage(string, false)) {
|
|
560
463
|
// Valid link inside this possible link, which makes this link invalid (inner links beat outer ones)
|
|
561
464
|
return false;
|
|
562
465
|
}
|
|
563
466
|
}
|
|
564
|
-
|
|
565
467
|
currentOffset += 1;
|
|
566
468
|
continue textOuter;
|
|
567
|
-
}
|
|
568
|
-
|
|
469
|
+
}
|
|
569
470
|
|
|
471
|
+
// Check for closing bracket
|
|
570
472
|
if (string.match(/^\]/)) {
|
|
571
473
|
bracketLevel--;
|
|
572
|
-
|
|
573
474
|
if (bracketLevel == 0) {
|
|
574
475
|
// Found matching bracket and haven't found anything disqualifying this as link / image.
|
|
575
476
|
linkText = originalString.substr(textOffset, currentOffset - textOffset);
|
|
576
477
|
currentOffset++;
|
|
577
478
|
continue textOuter;
|
|
578
479
|
}
|
|
579
|
-
}
|
|
580
|
-
|
|
480
|
+
}
|
|
581
481
|
|
|
482
|
+
// Nothing matches, proceed to next char
|
|
582
483
|
currentOffset++;
|
|
583
|
-
}
|
|
584
|
-
|
|
484
|
+
}
|
|
585
485
|
|
|
486
|
+
// Did we find a link text (i.e., find a matching closing bracket?)
|
|
586
487
|
if (linkText === false) return false; // Nope
|
|
587
|
-
// So far, so good. We've got a valid link text. Let's see what type of link this is
|
|
588
488
|
|
|
589
|
-
|
|
489
|
+
// So far, so good. We've got a valid link text. Let's see what type of link this is
|
|
490
|
+
var nextChar = currentOffset < originalString.length ? originalString.substr(currentOffset, 1) : '';
|
|
590
491
|
|
|
492
|
+
// REFERENCE LINKS
|
|
591
493
|
if (nextChar == '[') {
|
|
592
494
|
var _string = originalString.substr(currentOffset);
|
|
593
|
-
|
|
594
495
|
var _cap = _grammar.inlineGrammar.linkLabel.regexp.exec(_string);
|
|
595
|
-
|
|
596
496
|
if (_cap) {
|
|
597
497
|
// Valid link label
|
|
598
498
|
currentOffset += _cap[0].length;
|
|
599
499
|
linkLabel.push(_cap[1], _cap[2], _cap[3]);
|
|
600
|
-
|
|
601
500
|
if (_cap[_grammar.inlineGrammar.linkLabel.labelPlaceholder]) {
|
|
602
501
|
// Full reference link
|
|
603
502
|
linkRef = _cap[_grammar.inlineGrammar.linkLabel.labelPlaceholder];
|
|
@@ -611,68 +510,59 @@ var Editor = /*#__PURE__*/function () {
|
|
|
611
510
|
}
|
|
612
511
|
} else if (nextChar != '(') {
|
|
613
512
|
// Shortcut ref link
|
|
614
|
-
linkRef = linkText.trim();
|
|
513
|
+
linkRef = linkText.trim();
|
|
514
|
+
|
|
515
|
+
// INLINE LINKS
|
|
615
516
|
} else {
|
|
616
517
|
// nextChar == '('
|
|
518
|
+
|
|
617
519
|
// Potential inline link
|
|
618
520
|
currentOffset++;
|
|
619
521
|
var parenthesisLevel = 1;
|
|
620
|
-
|
|
621
522
|
inlineOuter: while (currentOffset < originalString.length && parenthesisLevel > 0) {
|
|
622
|
-
var _string2 = originalString.substr(currentOffset);
|
|
623
|
-
|
|
523
|
+
var _string2 = originalString.substr(currentOffset);
|
|
624
524
|
|
|
525
|
+
// Process whitespace
|
|
625
526
|
var _cap2 = /^\s+/.exec(_string2);
|
|
626
|
-
|
|
627
527
|
if (_cap2) {
|
|
628
528
|
switch (linkDetails.length) {
|
|
629
529
|
case 0:
|
|
630
530
|
linkDetails.push(_cap2[0]);
|
|
631
531
|
break;
|
|
632
532
|
// Opening whitespace
|
|
633
|
-
|
|
634
533
|
case 1:
|
|
635
534
|
linkDetails.push(_cap2[0]);
|
|
636
535
|
break;
|
|
637
536
|
// Open destination, but not a destination yet; desination opened with <
|
|
638
|
-
|
|
639
537
|
case 2:
|
|
640
538
|
// Open destination with content in it. Whitespace only allowed if opened by angle bracket, otherwise this closes the destination
|
|
641
539
|
if (linkDetails[0].match(/</)) {
|
|
642
540
|
linkDetails[1] = linkDetails[1].concat(_cap2[0]);
|
|
643
541
|
} else {
|
|
644
542
|
if (parenthesisLevel != 1) return false; // Unbalanced parenthesis
|
|
645
|
-
|
|
646
543
|
linkDetails.push(''); // Empty end delimiter for destination
|
|
647
|
-
|
|
648
544
|
linkDetails.push(_cap2[0]); // Whitespace in between destination and title
|
|
649
545
|
}
|
|
650
546
|
|
|
651
547
|
break;
|
|
652
|
-
|
|
653
548
|
case 3:
|
|
654
549
|
linkDetails.push(_cap2[0]);
|
|
655
550
|
break;
|
|
656
551
|
// Whitespace between destination and title
|
|
657
|
-
|
|
658
552
|
case 4:
|
|
659
553
|
return false;
|
|
660
554
|
// This should never happen (no opener for title yet, but more whitespace to capture)
|
|
661
|
-
|
|
662
555
|
case 5:
|
|
663
556
|
linkDetails.push('');
|
|
664
557
|
// Whitespace at beginning of title, push empty title and continue
|
|
665
|
-
|
|
666
558
|
case 6:
|
|
667
559
|
linkDetails[5] = linkDetails[5].concat(_cap2[0]);
|
|
668
560
|
break;
|
|
669
561
|
// Whitespace in title
|
|
670
|
-
|
|
671
562
|
case 7:
|
|
672
563
|
linkDetails[6] = linkDetails[6].concat(_cap2[0]);
|
|
673
564
|
break;
|
|
674
565
|
// Whitespace after closing delimiter
|
|
675
|
-
|
|
676
566
|
default:
|
|
677
567
|
return false;
|
|
678
568
|
// We should never get here
|
|
@@ -680,44 +570,36 @@ var Editor = /*#__PURE__*/function () {
|
|
|
680
570
|
|
|
681
571
|
currentOffset += _cap2[0].length;
|
|
682
572
|
continue inlineOuter;
|
|
683
|
-
}
|
|
684
|
-
|
|
573
|
+
}
|
|
685
574
|
|
|
575
|
+
// Process backslash escapes
|
|
686
576
|
_cap2 = _grammar.inlineGrammar.escape.regexp.exec(_string2);
|
|
687
|
-
|
|
688
577
|
if (_cap2) {
|
|
689
578
|
switch (linkDetails.length) {
|
|
690
579
|
case 0:
|
|
691
580
|
linkDetails.push('');
|
|
692
581
|
// this opens the link destination, add empty opening delimiter and proceed to next case
|
|
693
|
-
|
|
694
582
|
case 1:
|
|
695
583
|
linkDetails.push(_cap2[0]);
|
|
696
584
|
break;
|
|
697
585
|
// This opens the link destination, append it
|
|
698
|
-
|
|
699
586
|
case 2:
|
|
700
587
|
linkDetails[1] = linkDetails[1].concat(_cap2[0]);
|
|
701
588
|
break;
|
|
702
589
|
// Part of the link destination
|
|
703
|
-
|
|
704
590
|
case 3:
|
|
705
591
|
return false;
|
|
706
592
|
// Lacking opening delimiter for link title
|
|
707
|
-
|
|
708
593
|
case 4:
|
|
709
594
|
return false;
|
|
710
595
|
// Lcaking opening delimiter for link title
|
|
711
|
-
|
|
712
596
|
case 5:
|
|
713
597
|
linkDetails.push('');
|
|
714
598
|
// This opens the link title
|
|
715
|
-
|
|
716
599
|
case 6:
|
|
717
600
|
linkDetails[5] = linkDetails[5].concat(_cap2[0]);
|
|
718
601
|
break;
|
|
719
602
|
// Part of the link title
|
|
720
|
-
|
|
721
603
|
default:
|
|
722
604
|
return false;
|
|
723
605
|
// After link title was closed, without closing parenthesis
|
|
@@ -725,85 +607,75 @@ var Editor = /*#__PURE__*/function () {
|
|
|
725
607
|
|
|
726
608
|
currentOffset += _cap2[0].length;
|
|
727
609
|
continue inlineOuter;
|
|
728
|
-
}
|
|
729
|
-
|
|
610
|
+
}
|
|
730
611
|
|
|
612
|
+
// Process opening angle bracket as deilimiter of destination
|
|
731
613
|
if (linkDetails.length < 2 && _string2.match(/^</)) {
|
|
732
614
|
if (linkDetails.length == 0) linkDetails.push('');
|
|
733
615
|
linkDetails[0] = linkDetails[0].concat('<');
|
|
734
616
|
currentOffset++;
|
|
735
617
|
continue inlineOuter;
|
|
736
|
-
}
|
|
737
|
-
|
|
618
|
+
}
|
|
738
619
|
|
|
620
|
+
// Process closing angle bracket as delimiter of destination
|
|
739
621
|
if ((linkDetails.length == 1 || linkDetails.length == 2) && _string2.match(/^>/)) {
|
|
740
622
|
if (linkDetails.length == 1) linkDetails.push(''); // Empty link destination
|
|
741
|
-
|
|
742
623
|
linkDetails.push('>');
|
|
743
624
|
currentOffset++;
|
|
744
625
|
continue inlineOuter;
|
|
745
|
-
}
|
|
746
|
-
|
|
626
|
+
}
|
|
747
627
|
|
|
748
|
-
|
|
628
|
+
// Process non-parenthesis delimiter for title.
|
|
629
|
+
_cap2 = /^["']/.exec(_string2);
|
|
630
|
+
// For this to be a valid opener, we have to either have no destination, only whitespace so far,
|
|
749
631
|
// or a destination with trailing whitespace.
|
|
750
|
-
|
|
751
632
|
if (_cap2 && (linkDetails.length == 0 || linkDetails.length == 1 || linkDetails.length == 4)) {
|
|
752
633
|
while (linkDetails.length < 4) {
|
|
753
634
|
linkDetails.push('');
|
|
754
635
|
}
|
|
755
|
-
|
|
756
636
|
linkDetails.push(_cap2[0]);
|
|
757
637
|
currentOffset++;
|
|
758
638
|
continue inlineOuter;
|
|
759
|
-
}
|
|
760
|
-
|
|
639
|
+
}
|
|
761
640
|
|
|
641
|
+
// For this to be a valid closer, we have to have an opener and some or no title, and this has to match the opener
|
|
762
642
|
if (_cap2 && (linkDetails.length == 5 || linkDetails.length == 6) && linkDetails[4] == _cap2[0]) {
|
|
763
643
|
if (linkDetails.length == 5) linkDetails.push(''); // Empty link title
|
|
764
|
-
|
|
765
644
|
linkDetails.push(_cap2[0]);
|
|
766
645
|
currentOffset++;
|
|
767
646
|
continue inlineOuter;
|
|
768
|
-
}
|
|
769
|
-
//
|
|
770
|
-
|
|
647
|
+
}
|
|
648
|
+
// Other cases (linkDetails.length == 2, 3, 7) will be handled with the "default" case below.
|
|
771
649
|
|
|
650
|
+
// Process opening parenthesis
|
|
772
651
|
if (_string2.match(/^\(/)) {
|
|
773
652
|
switch (linkDetails.length) {
|
|
774
653
|
case 0:
|
|
775
654
|
linkDetails.push('');
|
|
776
655
|
// this opens the link destination, add empty opening delimiter and proceed to next case
|
|
777
|
-
|
|
778
656
|
case 1:
|
|
779
657
|
linkDetails.push('');
|
|
780
658
|
// This opens the link destination
|
|
781
|
-
|
|
782
659
|
case 2:
|
|
783
660
|
// Part of the link destination
|
|
784
661
|
linkDetails[1] = linkDetails[1].concat('(');
|
|
785
662
|
if (!linkDetails[0].match(/<$/)) parenthesisLevel++;
|
|
786
663
|
break;
|
|
787
|
-
|
|
788
664
|
case 3:
|
|
789
665
|
linkDetails.push('');
|
|
790
666
|
// opening delimiter for link title
|
|
791
|
-
|
|
792
667
|
case 4:
|
|
793
668
|
linkDetails.push('(');
|
|
794
669
|
break;
|
|
795
670
|
// opening delimiter for link title
|
|
796
|
-
|
|
797
671
|
case 5:
|
|
798
672
|
linkDetails.push('');
|
|
799
673
|
// opens the link title, add empty title content and proceed to next case
|
|
800
|
-
|
|
801
674
|
case 6:
|
|
802
675
|
// Part of the link title. Un-escaped parenthesis only allowed in " or ' delimited title
|
|
803
676
|
if (linkDetails[4] == '(') return false;
|
|
804
677
|
linkDetails[5] = linkDetails[5].concat('(');
|
|
805
678
|
break;
|
|
806
|
-
|
|
807
679
|
default:
|
|
808
680
|
return false;
|
|
809
681
|
// After link title was closed, without closing parenthesis
|
|
@@ -811,18 +683,16 @@ var Editor = /*#__PURE__*/function () {
|
|
|
811
683
|
|
|
812
684
|
currentOffset++;
|
|
813
685
|
continue inlineOuter;
|
|
814
|
-
}
|
|
815
|
-
|
|
686
|
+
}
|
|
816
687
|
|
|
688
|
+
// Process closing parenthesis
|
|
817
689
|
if (_string2.match(/^\)/)) {
|
|
818
690
|
if (linkDetails.length <= 2) {
|
|
819
691
|
// We are inside the link destination. Parentheses have to be matched if not in angle brackets
|
|
820
692
|
while (linkDetails.length < 2) {
|
|
821
693
|
linkDetails.push('');
|
|
822
694
|
}
|
|
823
|
-
|
|
824
695
|
if (!linkDetails[0].match(/<$/)) parenthesisLevel--;
|
|
825
|
-
|
|
826
696
|
if (parenthesisLevel > 0) {
|
|
827
697
|
linkDetails[1] = linkDetails[1].concat(')');
|
|
828
698
|
}
|
|
@@ -846,47 +716,38 @@ var Editor = /*#__PURE__*/function () {
|
|
|
846
716
|
linkDetails.push('');
|
|
847
717
|
}
|
|
848
718
|
}
|
|
849
|
-
|
|
850
719
|
currentOffset++;
|
|
851
720
|
continue inlineOuter;
|
|
852
|
-
}
|
|
853
|
-
|
|
721
|
+
}
|
|
854
722
|
|
|
723
|
+
// Any old character
|
|
855
724
|
_cap2 = /^./.exec(_string2);
|
|
856
|
-
|
|
857
725
|
if (_cap2) {
|
|
858
726
|
switch (linkDetails.length) {
|
|
859
727
|
case 0:
|
|
860
728
|
linkDetails.push('');
|
|
861
729
|
// this opens the link destination, add empty opening delimiter and proceed to next case
|
|
862
|
-
|
|
863
730
|
case 1:
|
|
864
731
|
linkDetails.push(_cap2[0]);
|
|
865
732
|
break;
|
|
866
733
|
// This opens the link destination, append it
|
|
867
|
-
|
|
868
734
|
case 2:
|
|
869
735
|
linkDetails[1] = linkDetails[1].concat(_cap2[0]);
|
|
870
736
|
break;
|
|
871
737
|
// Part of the link destination
|
|
872
|
-
|
|
873
738
|
case 3:
|
|
874
739
|
return false;
|
|
875
740
|
// Lacking opening delimiter for link title
|
|
876
|
-
|
|
877
741
|
case 4:
|
|
878
742
|
return false;
|
|
879
743
|
// Lcaking opening delimiter for link title
|
|
880
|
-
|
|
881
744
|
case 5:
|
|
882
745
|
linkDetails.push('');
|
|
883
746
|
// This opens the link title
|
|
884
|
-
|
|
885
747
|
case 6:
|
|
886
748
|
linkDetails[5] = linkDetails[5].concat(_cap2[0]);
|
|
887
749
|
break;
|
|
888
750
|
// Part of the link title
|
|
889
|
-
|
|
890
751
|
default:
|
|
891
752
|
return false;
|
|
892
753
|
// After link title was closed, without closing parenthesis
|
|
@@ -895,7 +756,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
895
756
|
currentOffset += _cap2[0].length;
|
|
896
757
|
continue inlineOuter;
|
|
897
758
|
}
|
|
898
|
-
|
|
899
759
|
throw "Infinite loop"; // we should never get here since the last test matches any character
|
|
900
760
|
}
|
|
901
761
|
|
|
@@ -905,14 +765,11 @@ var Editor = /*#__PURE__*/function () {
|
|
|
905
765
|
if (linkRef !== false) {
|
|
906
766
|
// Ref link; check that linkRef is valid
|
|
907
767
|
var valid = false;
|
|
908
|
-
|
|
909
768
|
var _iterator2 = _createForOfIteratorHelper(this.linkLabels),
|
|
910
|
-
|
|
911
|
-
|
|
769
|
+
_step2;
|
|
912
770
|
try {
|
|
913
771
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
914
772
|
var _label = _step2.value;
|
|
915
|
-
|
|
916
773
|
if (_label == linkRef) {
|
|
917
774
|
valid = true;
|
|
918
775
|
break;
|
|
@@ -923,60 +780,52 @@ var Editor = /*#__PURE__*/function () {
|
|
|
923
780
|
} finally {
|
|
924
781
|
_iterator2.f();
|
|
925
782
|
}
|
|
926
|
-
|
|
927
783
|
var label = valid ? "TMLinkLabel TMLinkLabel_Valid" : "TMLinkLabel TMLinkLabel_Invalid";
|
|
928
784
|
var output = "<span class=\"TMMark TMMark_".concat(type, "\">").concat(opener, "</span><span class=\"").concat(type, " ").concat(linkLabel.length < 3 || !linkLabel[1] ? label : "", "\">").concat(this.processInlineStyles(linkText), "</span><span class=\"TMMark TMMark_").concat(type, "\">]</span>");
|
|
929
|
-
|
|
930
785
|
if (linkLabel.length >= 3) {
|
|
931
786
|
output = output.concat("<span class=\"TMMark TMMark_".concat(type, "\">").concat(linkLabel[0], "</span>"), "<span class=\"".concat(label, "\">").concat(linkLabel[1], "</span>"), "<span class=\"TMMark TMMark_".concat(type, "\">").concat(linkLabel[2], "</span>"));
|
|
932
787
|
}
|
|
933
|
-
|
|
934
788
|
return {
|
|
935
789
|
output: output,
|
|
936
790
|
charCount: currentOffset
|
|
937
791
|
};
|
|
938
792
|
} else if (linkDetails) {
|
|
939
793
|
// Inline link
|
|
794
|
+
|
|
940
795
|
// This should never happen, but better safe than sorry.
|
|
941
796
|
while (linkDetails.length < 7) {
|
|
942
797
|
linkDetails.push('');
|
|
943
798
|
}
|
|
944
|
-
|
|
945
799
|
return {
|
|
946
800
|
output: "<span class=\"TMMark TMMark_".concat(type, "\">").concat(opener, "</span><span class=\"").concat(type, "\">").concat(this.processInlineStyles(linkText), "</span><span class=\"TMMark TMMark_").concat(type, "\">](").concat(linkDetails[0], "</span><span class=\"").concat(type, "Destination\">").concat(linkDetails[1], "</span><span class=\"TMMark TMMark_").concat(type, "\">").concat(linkDetails[2]).concat(linkDetails[3]).concat(linkDetails[4], "</span><span class=\"").concat(type, "Title\">").concat(linkDetails[5], "</span><span class=\"TMMark TMMark_").concat(type, "\">").concat(linkDetails[6], ")</span>"),
|
|
947
801
|
charCount: currentOffset
|
|
948
802
|
};
|
|
949
803
|
}
|
|
950
|
-
|
|
951
804
|
return false;
|
|
952
805
|
}
|
|
806
|
+
|
|
953
807
|
/**
|
|
954
808
|
* Formats a markdown string as HTML, using Markdown inline formatting.
|
|
955
809
|
* @param {string} originalString The input (markdown inline formatted) string
|
|
956
810
|
* @returns {string} The HTML formatted output
|
|
957
811
|
*/
|
|
958
|
-
|
|
959
812
|
}, {
|
|
960
813
|
key: "processInlineStyles",
|
|
961
814
|
value: function processInlineStyles(originalString) {
|
|
962
815
|
var _this3 = this;
|
|
963
|
-
|
|
964
816
|
var processed = '';
|
|
965
817
|
var stack = []; // Stack is an array of objects of the format: {delimiter, delimString, count, output}
|
|
966
|
-
|
|
967
818
|
var offset = 0;
|
|
968
819
|
var string = originalString;
|
|
969
|
-
|
|
970
820
|
var _loop = function _loop() {
|
|
971
821
|
var _loop2 = function _loop2() {
|
|
972
822
|
var rule = _arr2[_i2];
|
|
973
|
-
|
|
974
823
|
var cap = _grammar.inlineGrammar[rule].regexp.exec(string);
|
|
975
|
-
|
|
976
824
|
if (cap) {
|
|
977
825
|
string = string.substr(cap[0].length);
|
|
978
826
|
offset += cap[0].length;
|
|
979
|
-
processed += _grammar.inlineGrammar[rule].replacement
|
|
827
|
+
processed += _grammar.inlineGrammar[rule].replacement
|
|
828
|
+
// .replace(/\$\$([1-9])/g, (str, p1) => processInlineStyles(cap[p1])) // todo recursive calling
|
|
980
829
|
.replace(/\$([1-9])/g, function (str, p1) {
|
|
981
830
|
return (0, _grammar.htmlescape)(cap[p1]);
|
|
982
831
|
});
|
|
@@ -985,70 +834,68 @@ var Editor = /*#__PURE__*/function () {
|
|
|
985
834
|
};
|
|
986
835
|
}
|
|
987
836
|
};
|
|
988
|
-
|
|
989
837
|
// Process simple rules (non-delimiter)
|
|
990
838
|
for (var _i2 = 0, _arr2 = ['escape', 'code', 'autolink', 'html']; _i2 < _arr2.length; _i2++) {
|
|
991
839
|
var _ret2 = _loop2();
|
|
992
|
-
|
|
993
840
|
if (_typeof(_ret2) === "object") return _ret2.v;
|
|
994
|
-
}
|
|
995
|
-
|
|
841
|
+
}
|
|
996
842
|
|
|
843
|
+
// Check for links / images
|
|
997
844
|
var potentialLink = string.match(_grammar.inlineGrammar.linkOpen.regexp);
|
|
998
845
|
var potentialImage = string.match(_grammar.inlineGrammar.imageOpen.regexp);
|
|
999
|
-
|
|
1000
846
|
if (potentialImage || potentialLink) {
|
|
1001
847
|
var result = _this3.parseLinkOrImage(string, potentialImage);
|
|
1002
|
-
|
|
1003
848
|
if (result) {
|
|
1004
849
|
processed = "".concat(processed).concat(result.output);
|
|
1005
850
|
string = string.substr(result.charCount);
|
|
1006
851
|
offset += result.charCount;
|
|
1007
852
|
return "continue|outer";
|
|
1008
853
|
}
|
|
1009
|
-
}
|
|
1010
|
-
|
|
854
|
+
}
|
|
1011
855
|
|
|
856
|
+
// Check for em / strong delimiters
|
|
1012
857
|
var cap = /(^\*+)|(^_+)/.exec(string);
|
|
1013
|
-
|
|
1014
858
|
if (cap) {
|
|
1015
859
|
var delimCount = cap[0].length;
|
|
1016
860
|
var delimString = cap[0];
|
|
1017
861
|
var currentDelimiter = cap[0][0]; // This should be * or _
|
|
1018
862
|
|
|
1019
|
-
string = string.substr(cap[0].length);
|
|
863
|
+
string = string.substr(cap[0].length);
|
|
1020
864
|
|
|
1021
|
-
|
|
865
|
+
// We have a delimiter run. Let's check if it can open or close an emphasis.
|
|
1022
866
|
|
|
867
|
+
var preceding = offset > 0 ? originalString.substr(0, offset) : ' '; // beginning and end of line count as whitespace
|
|
1023
868
|
var following = offset + cap[0].length < originalString.length ? string : ' ';
|
|
1024
869
|
var punctuationFollows = following.match(_grammar.punctuationLeading);
|
|
1025
870
|
var punctuationPrecedes = preceding.match(_grammar.punctuationTrailing);
|
|
1026
871
|
var whitespaceFollows = following.match(/^\s/);
|
|
1027
|
-
var whitespacePrecedes = preceding.match(/\s$/);
|
|
872
|
+
var whitespacePrecedes = preceding.match(/\s$/);
|
|
1028
873
|
|
|
874
|
+
// These are the rules for right-flanking and left-flanking delimiter runs as per CommonMark spec
|
|
1029
875
|
var canOpen = !whitespaceFollows && (!punctuationFollows || !!whitespacePrecedes || !!punctuationPrecedes);
|
|
1030
|
-
var canClose = !whitespacePrecedes && (!punctuationPrecedes || !!whitespaceFollows || !!punctuationFollows);
|
|
876
|
+
var canClose = !whitespacePrecedes && (!punctuationPrecedes || !!whitespaceFollows || !!punctuationFollows);
|
|
1031
877
|
|
|
878
|
+
// Underscores have more detailed rules than just being part of left- or right-flanking run:
|
|
1032
879
|
if (currentDelimiter == '_' && canOpen && canClose) {
|
|
1033
880
|
canOpen = punctuationPrecedes;
|
|
1034
881
|
canClose = punctuationFollows;
|
|
1035
|
-
}
|
|
1036
|
-
|
|
882
|
+
}
|
|
1037
883
|
|
|
884
|
+
// If the delimiter can close, check the stack if there's something it can close
|
|
1038
885
|
if (canClose) {
|
|
1039
|
-
var stackPointer = stack.length - 1;
|
|
1040
|
-
|
|
886
|
+
var stackPointer = stack.length - 1;
|
|
887
|
+
// See if we can find a matching opening delimiter, move down through the stack
|
|
1041
888
|
while (delimCount && stackPointer >= 0) {
|
|
1042
889
|
if (stack[stackPointer].delimiter == currentDelimiter) {
|
|
1043
890
|
// We found a matching delimiter, let's construct the formatted string
|
|
891
|
+
|
|
1044
892
|
// Firstly, if we skipped any stack levels, pop them immediately (non-matching delimiters)
|
|
1045
893
|
while (stackPointer < stack.length - 1) {
|
|
1046
894
|
var _entry = stack.pop();
|
|
1047
|
-
|
|
1048
895
|
processed = "".concat(_entry.output).concat(_entry.delimString.substr(0, _entry.count)).concat(processed);
|
|
1049
|
-
}
|
|
1050
|
-
|
|
896
|
+
}
|
|
1051
897
|
|
|
898
|
+
// Then, format the string
|
|
1052
899
|
if (delimCount >= 2 && stack[stackPointer].count >= 2) {
|
|
1053
900
|
// Strong
|
|
1054
901
|
processed = "<span class=\"TMMark\">".concat(currentDelimiter).concat(currentDelimiter, "</span><strong class=\"TMStrong\">").concat(processed, "</strong><span class=\"TMMark\">").concat(currentDelimiter).concat(currentDelimiter, "</span>");
|
|
@@ -1059,12 +906,11 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1059
906
|
processed = "<span class=\"TMMark\">".concat(currentDelimiter, "</span><em class=\"TMEm\">").concat(processed, "</em><span class=\"TMMark\">").concat(currentDelimiter, "</span>");
|
|
1060
907
|
delimCount -= 1;
|
|
1061
908
|
stack[stackPointer].count -= 1;
|
|
1062
|
-
}
|
|
1063
|
-
|
|
909
|
+
}
|
|
1064
910
|
|
|
911
|
+
// If that stack level is empty now, pop it
|
|
1065
912
|
if (stack[stackPointer].count == 0) {
|
|
1066
913
|
var _entry2 = stack.pop();
|
|
1067
|
-
|
|
1068
914
|
processed = "".concat(_entry2.output).concat(processed);
|
|
1069
915
|
stackPointer--;
|
|
1070
916
|
}
|
|
@@ -1074,9 +920,8 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1074
920
|
stackPointer--;
|
|
1075
921
|
}
|
|
1076
922
|
}
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
|
|
923
|
+
}
|
|
924
|
+
// If there are still delimiters left, and the delimiter run can open, push it on the stack
|
|
1080
925
|
if (delimCount && canOpen) {
|
|
1081
926
|
stack.push({
|
|
1082
927
|
delimiter: currentDelimiter,
|
|
@@ -1085,43 +930,36 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1085
930
|
output: processed
|
|
1086
931
|
});
|
|
1087
932
|
processed = ''; // Current formatted output has been pushed on the stack and will be prepended when the stack gets popped
|
|
1088
|
-
|
|
1089
933
|
delimCount = 0;
|
|
1090
|
-
}
|
|
1091
|
-
|
|
934
|
+
}
|
|
1092
935
|
|
|
936
|
+
// Any delimiters that are left (closing unmatched) are appended to the output.
|
|
1093
937
|
if (delimCount) {
|
|
1094
938
|
processed = "".concat(processed).concat(delimString.substr(0, delimCount));
|
|
1095
939
|
}
|
|
1096
|
-
|
|
1097
940
|
offset += cap[0].length;
|
|
1098
941
|
return "continue|outer";
|
|
1099
|
-
}
|
|
1100
|
-
|
|
942
|
+
}
|
|
1101
943
|
|
|
944
|
+
// Check for strikethrough delimiter
|
|
1102
945
|
cap = /^~~/.exec(string);
|
|
1103
|
-
|
|
1104
946
|
if (cap) {
|
|
1105
947
|
var consumed = false;
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
948
|
+
var _stackPointer = stack.length - 1;
|
|
949
|
+
// See if we can find a matching opening delimiter, move down through the stack
|
|
1110
950
|
while (!consumed && _stackPointer >= 0) {
|
|
1111
951
|
if (stack[_stackPointer].delimiter == '~') {
|
|
1112
952
|
// We found a matching delimiter, let's construct the formatted string
|
|
953
|
+
|
|
1113
954
|
// Firstly, if we skipped any stack levels, pop them immediately (non-matching delimiters)
|
|
1114
955
|
while (_stackPointer < stack.length - 1) {
|
|
1115
956
|
var _entry4 = stack.pop();
|
|
1116
|
-
|
|
1117
957
|
processed = "".concat(_entry4.output).concat(_entry4.delimString.substr(0, _entry4.count)).concat(processed);
|
|
1118
|
-
}
|
|
1119
|
-
|
|
958
|
+
}
|
|
1120
959
|
|
|
960
|
+
// Then, format the string
|
|
1121
961
|
processed = "<span class=\"TMMark\">~~</span><del class=\"TMStrikethrough\">".concat(processed, "</del><span class=\"TMMark\">~~</span>");
|
|
1122
|
-
|
|
1123
962
|
var _entry3 = stack.pop();
|
|
1124
|
-
|
|
1125
963
|
processed = "".concat(_entry3.output).concat(processed);
|
|
1126
964
|
consumed = true;
|
|
1127
965
|
} else {
|
|
@@ -1129,9 +967,9 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1129
967
|
// Go down one level in the stack
|
|
1130
968
|
_stackPointer--;
|
|
1131
969
|
}
|
|
1132
|
-
}
|
|
1133
|
-
|
|
970
|
+
}
|
|
1134
971
|
|
|
972
|
+
// If there are still delimiters left, and the delimiter run can open, push it on the stack
|
|
1135
973
|
if (!consumed) {
|
|
1136
974
|
stack.push({
|
|
1137
975
|
delimiter: '~',
|
|
@@ -1145,11 +983,10 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1145
983
|
offset += cap[0].length;
|
|
1146
984
|
string = string.substr(cap[0].length);
|
|
1147
985
|
return "continue|outer";
|
|
1148
|
-
}
|
|
1149
|
-
|
|
986
|
+
}
|
|
1150
987
|
|
|
988
|
+
// Process 'default' rule
|
|
1151
989
|
cap = _grammar.inlineGrammar.default.regexp.exec(string);
|
|
1152
|
-
|
|
1153
990
|
if (cap) {
|
|
1154
991
|
string = string.substr(cap[0].length);
|
|
1155
992
|
offset += cap[0].length;
|
|
@@ -1158,42 +995,37 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1158
995
|
});
|
|
1159
996
|
return "continue|outer";
|
|
1160
997
|
}
|
|
1161
|
-
|
|
1162
998
|
throw 'Infinite loop!';
|
|
1163
999
|
};
|
|
1164
|
-
|
|
1165
1000
|
outer: while (string) {
|
|
1166
1001
|
var _ret = _loop();
|
|
1167
|
-
|
|
1168
1002
|
if (_ret === "continue|outer") continue outer;
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1003
|
+
}
|
|
1171
1004
|
|
|
1005
|
+
// Empty the stack, any opening delimiters are unused
|
|
1172
1006
|
while (stack.length) {
|
|
1173
1007
|
var entry = stack.pop();
|
|
1174
1008
|
processed = "".concat(entry.output).concat(entry.delimString.substr(0, entry.count)).concat(processed);
|
|
1175
1009
|
}
|
|
1176
|
-
|
|
1177
1010
|
return processed;
|
|
1178
1011
|
}
|
|
1012
|
+
|
|
1179
1013
|
/**
|
|
1180
1014
|
* Clears the line dirty flag (resets it to an array of false)
|
|
1181
1015
|
*/
|
|
1182
|
-
|
|
1183
1016
|
}, {
|
|
1184
1017
|
key: "clearDirtyFlag",
|
|
1185
1018
|
value: function clearDirtyFlag() {
|
|
1186
1019
|
this.lineDirty = new Array(this.lines.length);
|
|
1187
|
-
|
|
1188
1020
|
for (var i = 0; i < this.lineDirty.length; i++) {
|
|
1189
1021
|
this.lineDirty[i] = false;
|
|
1190
1022
|
}
|
|
1191
1023
|
}
|
|
1024
|
+
|
|
1192
1025
|
/**
|
|
1193
1026
|
* Updates the class properties (lines, lineElements) from the DOM.
|
|
1194
1027
|
* @returns true if contents changed
|
|
1195
1028
|
*/
|
|
1196
|
-
|
|
1197
1029
|
}, {
|
|
1198
1030
|
key: "updateLineContents",
|
|
1199
1031
|
value: function updateLineContents() {
|
|
@@ -1201,40 +1033,33 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1201
1033
|
// Check if we have changed anything about the number of lines (inserted or deleted a paragraph)
|
|
1202
1034
|
// < 0 means line(s) removed; > 0 means line(s) added
|
|
1203
1035
|
var lineDelta = this.e.childElementCount - this.lines.length;
|
|
1204
|
-
|
|
1205
1036
|
if (lineDelta) {
|
|
1206
1037
|
// yup. Let's try how much we can salvage (find out which lines from beginning and end were unchanged)
|
|
1207
1038
|
// Find lines from the beginning that haven't changed...
|
|
1208
1039
|
var firstChangedLine = 0;
|
|
1209
|
-
|
|
1210
1040
|
while (firstChangedLine <= this.lines.length && firstChangedLine <= this.lineElements.length && this.lineElements[firstChangedLine] // Check that the line element hasn't been deleted
|
|
1211
1041
|
&& this.lines[firstChangedLine] == this.lineElements[firstChangedLine].textContent) {
|
|
1212
1042
|
firstChangedLine++;
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1043
|
+
}
|
|
1215
1044
|
|
|
1045
|
+
// End also from the end
|
|
1216
1046
|
var lastChangedLine = -1;
|
|
1217
|
-
|
|
1218
1047
|
while (-lastChangedLine < this.lines.length && -lastChangedLine < this.lineElements.length && this.lines[this.lines.length + lastChangedLine] == this.lineElements[this.lineElements.length + lastChangedLine].textContent) {
|
|
1219
1048
|
lastChangedLine--;
|
|
1220
1049
|
}
|
|
1221
|
-
|
|
1222
1050
|
var linesToDelete = this.lines.length + lastChangedLine + 1 - firstChangedLine;
|
|
1223
1051
|
if (linesToDelete < -lineDelta) linesToDelete = -lineDelta;
|
|
1224
1052
|
if (linesToDelete < 0) linesToDelete = 0;
|
|
1225
1053
|
var linesToAdd = [];
|
|
1226
|
-
|
|
1227
1054
|
for (var l = 0; l < linesToDelete + lineDelta; l++) {
|
|
1228
1055
|
linesToAdd.push(this.lineElements[firstChangedLine + l].textContent);
|
|
1229
1056
|
}
|
|
1230
|
-
|
|
1231
1057
|
this.spliceLines(firstChangedLine, linesToDelete, linesToAdd, false);
|
|
1232
1058
|
} else {
|
|
1233
1059
|
// No lines added or removed
|
|
1234
1060
|
for (var line = 0; line < this.lineElements.length; line++) {
|
|
1235
1061
|
var e = this.lineElements[line];
|
|
1236
1062
|
var ct = e.textContent;
|
|
1237
|
-
|
|
1238
1063
|
if (this.lines[line] !== ct) {
|
|
1239
1064
|
// Line changed, update it
|
|
1240
1065
|
this.lines[line] = ct;
|
|
@@ -1243,62 +1068,56 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1243
1068
|
}
|
|
1244
1069
|
}
|
|
1245
1070
|
}
|
|
1071
|
+
|
|
1246
1072
|
/**
|
|
1247
1073
|
* Processes a new paragraph.
|
|
1248
1074
|
* @param sel The current selection
|
|
1249
1075
|
*/
|
|
1250
|
-
|
|
1251
1076
|
}, {
|
|
1252
1077
|
key: "processNewParagraph",
|
|
1253
1078
|
value: function processNewParagraph(sel) {
|
|
1254
|
-
if (!sel) return;
|
|
1079
|
+
if (!sel) return;
|
|
1255
1080
|
|
|
1081
|
+
// Update lines from content
|
|
1256
1082
|
this.updateLineContents();
|
|
1257
|
-
var continuableType = false;
|
|
1083
|
+
var continuableType = false;
|
|
1084
|
+
// Let's see if we need to continue a list
|
|
1258
1085
|
|
|
1259
1086
|
var checkLine = sel.col > 0 ? sel.row : sel.row - 1;
|
|
1260
|
-
|
|
1261
1087
|
switch (this.lineTypes[checkLine]) {
|
|
1262
1088
|
case 'TMUL':
|
|
1263
1089
|
continuableType = 'TMUL';
|
|
1264
1090
|
break;
|
|
1265
|
-
|
|
1266
1091
|
case 'TMOL':
|
|
1267
1092
|
continuableType = 'TMOL';
|
|
1268
1093
|
break;
|
|
1269
|
-
|
|
1270
1094
|
case 'TMIndentedCode':
|
|
1271
1095
|
continuableType = 'TMIndentedCode';
|
|
1272
1096
|
break;
|
|
1273
1097
|
}
|
|
1274
|
-
|
|
1275
1098
|
var lines = this.lines[sel.row].replace(/\n\n$/, '\n').split(/(?:\r\n|\n|\r)/);
|
|
1276
|
-
|
|
1277
1099
|
if (lines.length == 1) {
|
|
1278
1100
|
// No new line
|
|
1279
1101
|
this.updateFormatting();
|
|
1280
1102
|
return;
|
|
1281
1103
|
}
|
|
1282
|
-
|
|
1283
1104
|
this.spliceLines(sel.row, 1, lines, true);
|
|
1284
1105
|
sel.row++;
|
|
1285
1106
|
sel.col = 0;
|
|
1286
|
-
|
|
1287
1107
|
if (continuableType) {
|
|
1288
1108
|
// Check if the previous line was non-empty
|
|
1289
1109
|
var capture = _grammar.lineGrammar[continuableType].regexp.exec(this.lines[sel.row - 1]);
|
|
1290
|
-
|
|
1291
1110
|
if (capture) {
|
|
1292
1111
|
// Convention: capture[1] is the line type marker, capture[2] is the content
|
|
1293
1112
|
if (capture[2]) {
|
|
1294
1113
|
// Previous line has content, continue the continuable type
|
|
1114
|
+
|
|
1295
1115
|
// Hack for OL: increment number
|
|
1296
1116
|
if (continuableType == 'TMOL') {
|
|
1297
1117
|
capture[1] = capture[1].replace(/\d{1,9}/, function (result) {
|
|
1298
1118
|
return parseInt(result[0]) + 1;
|
|
1299
1119
|
});
|
|
1300
1120
|
}
|
|
1301
|
-
|
|
1302
1121
|
this.lines[sel.row] = "".concat(capture[1]).concat(this.lines[sel.row]);
|
|
1303
1122
|
this.lineDirty[sel.row] = true;
|
|
1304
1123
|
sel.col = capture[1].length;
|
|
@@ -1309,9 +1128,10 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1309
1128
|
}
|
|
1310
1129
|
}
|
|
1311
1130
|
}
|
|
1312
|
-
|
|
1313
1131
|
this.updateFormatting();
|
|
1314
|
-
}
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
// /**
|
|
1315
1135
|
// * Processes a "delete" input action.
|
|
1316
1136
|
// * @param {object} focus The selection
|
|
1317
1137
|
// * @param {boolean} forward If true, performs a forward delete, otherwise performs a backward delete
|
|
@@ -1334,6 +1154,7 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1334
1154
|
// // Otherwise, we're at the very beginning and can't delete backwards
|
|
1335
1155
|
// }
|
|
1336
1156
|
// }
|
|
1157
|
+
|
|
1337
1158
|
// }
|
|
1338
1159
|
|
|
1339
1160
|
/**
|
|
@@ -1342,7 +1163,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1342
1163
|
* @param {boolean} getAnchor if set to true, gets the selection anchor (start point of the selection), otherwise gets the focus (end point).
|
|
1343
1164
|
* @return {object} An object representing the selection, with properties col and row.
|
|
1344
1165
|
*/
|
|
1345
|
-
|
|
1346
1166
|
}, {
|
|
1347
1167
|
key: "getSelection",
|
|
1348
1168
|
value: function getSelection() {
|
|
@@ -1351,27 +1171,23 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1351
1171
|
var startNode = getAnchor ? selection.anchorNode : selection.focusNode;
|
|
1352
1172
|
if (!startNode) return null;
|
|
1353
1173
|
var offset = startNode.nodeType === Node.TEXT_NODE ? getAnchor ? selection.anchorOffset : selection.focusOffset : 0;
|
|
1354
|
-
|
|
1355
1174
|
if (startNode == this.e) {
|
|
1356
1175
|
return {
|
|
1357
1176
|
row: 0,
|
|
1358
1177
|
col: offset
|
|
1359
1178
|
};
|
|
1360
1179
|
}
|
|
1361
|
-
|
|
1362
1180
|
var col = this.computeColumn(startNode, offset);
|
|
1363
1181
|
if (col === null) return null; // We are outside of the editor
|
|
1364
|
-
// Find the row node
|
|
1365
1182
|
|
|
1183
|
+
// Find the row node
|
|
1366
1184
|
var node = startNode;
|
|
1367
|
-
|
|
1368
1185
|
while (node.parentElement != this.e) {
|
|
1369
1186
|
node = node.parentElement;
|
|
1370
1187
|
}
|
|
1371
|
-
|
|
1372
|
-
|
|
1188
|
+
var row = 0;
|
|
1189
|
+
// Check if we can read a line number from the data-line-num attribute.
|
|
1373
1190
|
// The last condition is a security measure since inserting a new paragraph copies the previous rows' line number
|
|
1374
|
-
|
|
1375
1191
|
if (node.dataset && node.dataset.lineNum && (!node.previousSibling || node.previousSibling.dataset.lineNum != node.dataset.lineNum)) {
|
|
1376
1192
|
row = parseInt(node.dataset.lineNum);
|
|
1377
1193
|
} else {
|
|
@@ -1380,33 +1196,30 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1380
1196
|
node = node.previousSibling;
|
|
1381
1197
|
}
|
|
1382
1198
|
}
|
|
1383
|
-
|
|
1384
1199
|
return {
|
|
1385
1200
|
row: row,
|
|
1386
1201
|
col: col,
|
|
1387
1202
|
node: startNode
|
|
1388
1203
|
};
|
|
1389
1204
|
}
|
|
1205
|
+
|
|
1390
1206
|
/**
|
|
1391
1207
|
* Computes a column within an editor line from a node and offset within that node.
|
|
1392
1208
|
* @param {Node} startNode The node
|
|
1393
1209
|
* @param {int} offset THe selection
|
|
1394
1210
|
* @returns {int} the column, or null if the node is not inside the editor
|
|
1395
1211
|
*/
|
|
1396
|
-
|
|
1397
1212
|
}, {
|
|
1398
1213
|
key: "computeColumn",
|
|
1399
1214
|
value: function computeColumn(startNode, offset) {
|
|
1400
1215
|
var node = startNode;
|
|
1401
|
-
var col = offset;
|
|
1402
|
-
|
|
1216
|
+
var col = offset;
|
|
1217
|
+
// First, make sure we're actually in the editor.
|
|
1403
1218
|
while (node && node.parentNode != this.e) {
|
|
1404
1219
|
node = node.parentNode;
|
|
1405
1220
|
}
|
|
1406
|
-
|
|
1407
1221
|
if (node == null) return null;
|
|
1408
1222
|
node = startNode;
|
|
1409
|
-
|
|
1410
1223
|
while (node.parentNode != this.e) {
|
|
1411
1224
|
if (node.previousSibling) {
|
|
1412
1225
|
node = node.previousSibling;
|
|
@@ -1415,40 +1228,35 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1415
1228
|
node = node.parentNode;
|
|
1416
1229
|
}
|
|
1417
1230
|
}
|
|
1418
|
-
|
|
1419
1231
|
return col;
|
|
1420
1232
|
}
|
|
1233
|
+
|
|
1421
1234
|
/**
|
|
1422
1235
|
* Computes DOM node and offset within that node from a position expressed as row and column.
|
|
1423
1236
|
* @param {int} row Row (line number)
|
|
1424
1237
|
* @param {int} col Column
|
|
1425
1238
|
* @returns An object with two properties: node and offset. offset may be null;
|
|
1426
1239
|
*/
|
|
1427
|
-
|
|
1428
1240
|
}, {
|
|
1429
1241
|
key: "computeNodeAndOffset",
|
|
1430
1242
|
value: function computeNodeAndOffset(row, col) {
|
|
1431
1243
|
var bindRight = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
1432
|
-
|
|
1433
1244
|
if (row >= this.lineElements.length) {
|
|
1434
1245
|
// Selection past the end of text, set selection to end of text
|
|
1435
1246
|
row = this.lineElements.length - 1;
|
|
1436
1247
|
col = this.lines[row].length;
|
|
1437
1248
|
}
|
|
1438
|
-
|
|
1439
1249
|
if (col > this.lines[row].length) {
|
|
1440
1250
|
col = this.lines[row].length;
|
|
1441
1251
|
}
|
|
1442
|
-
|
|
1443
1252
|
var parentNode = this.lineElements[row];
|
|
1444
1253
|
var node = parentNode.firstChild;
|
|
1445
|
-
var childrenComplete = false;
|
|
1446
|
-
|
|
1254
|
+
var childrenComplete = false;
|
|
1255
|
+
// default return value
|
|
1447
1256
|
var rv = {
|
|
1448
1257
|
node: parentNode.firstChild ? parentNode.firstChild : parentNode,
|
|
1449
1258
|
offset: 0
|
|
1450
1259
|
};
|
|
1451
|
-
|
|
1452
1260
|
while (node != parentNode) {
|
|
1453
1261
|
if (!childrenComplete && node.nodeType === Node.TEXT_NODE) {
|
|
1454
1262
|
if (node.nodeValue.length >= col) {
|
|
@@ -1470,7 +1278,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1470
1278
|
col -= node.nodeValue.length;
|
|
1471
1279
|
}
|
|
1472
1280
|
}
|
|
1473
|
-
|
|
1474
1281
|
if (!childrenComplete && node.firstChild) {
|
|
1475
1282
|
node = node.firstChild;
|
|
1476
1283
|
} else if (node.nextSibling) {
|
|
@@ -1480,56 +1287,49 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1480
1287
|
childrenComplete = true;
|
|
1481
1288
|
node = node.parentNode;
|
|
1482
1289
|
}
|
|
1483
|
-
}
|
|
1484
|
-
// Or we are binding right and the selection is at the end of the line
|
|
1485
|
-
|
|
1290
|
+
}
|
|
1486
1291
|
|
|
1292
|
+
// Either, the position was invalid and we just return the default return value
|
|
1293
|
+
// Or we are binding right and the selection is at the end of the line
|
|
1487
1294
|
return rv;
|
|
1488
1295
|
}
|
|
1296
|
+
|
|
1489
1297
|
/**
|
|
1490
1298
|
* Sets the selection based on rows and columns within the editor Markdown content.
|
|
1491
1299
|
* @param {object} focus Object representing the selection, needs to have properties row and col.
|
|
1492
1300
|
*/
|
|
1493
|
-
|
|
1494
1301
|
}, {
|
|
1495
1302
|
key: "setSelection",
|
|
1496
1303
|
value: function setSelection(focus) {
|
|
1497
1304
|
var anchor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
1498
1305
|
if (!focus) return;
|
|
1499
1306
|
var range = document.createRange();
|
|
1500
|
-
|
|
1501
1307
|
var _this$computeNodeAndO = this.computeNodeAndOffset(focus.row, focus.col, anchor && anchor.row == focus.row && anchor.col > focus.col),
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1308
|
+
focusNode = _this$computeNodeAndO.node,
|
|
1309
|
+
focusOffset = _this$computeNodeAndO.offset; // Bind selection right if anchor is in the same row and behind the focus
|
|
1506
1310
|
var anchorNode = null,
|
|
1507
|
-
|
|
1508
|
-
|
|
1311
|
+
anchorOffset = null;
|
|
1509
1312
|
if (anchor && (anchor.row != focus.row || anchor.col != focus.col)) {
|
|
1510
1313
|
var _this$computeNodeAndO2 = this.computeNodeAndOffset(anchor.row, anchor.col, focus.row == anchor.row && focus.col > anchor.col),
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1314
|
+
node = _this$computeNodeAndO2.node,
|
|
1315
|
+
offset = _this$computeNodeAndO2.offset;
|
|
1514
1316
|
anchorNode = node;
|
|
1515
1317
|
anchorOffset = offset;
|
|
1516
1318
|
}
|
|
1517
|
-
|
|
1518
1319
|
if (anchorNode) range.setStart(anchorNode, anchorOffset);else range.setStart(focusNode, focusOffset);
|
|
1519
1320
|
range.setEnd(focusNode, focusOffset);
|
|
1520
1321
|
var windowSelection = window.getSelection();
|
|
1521
1322
|
windowSelection.removeAllRanges();
|
|
1522
1323
|
windowSelection.addRange(range);
|
|
1523
1324
|
}
|
|
1325
|
+
|
|
1524
1326
|
/**
|
|
1525
1327
|
* Event handler for input events
|
|
1526
1328
|
*/
|
|
1527
|
-
|
|
1528
1329
|
}, {
|
|
1529
1330
|
key: "handleInputEvent",
|
|
1530
1331
|
value: function handleInputEvent(event) {
|
|
1531
1332
|
var focus = this.getSelection();
|
|
1532
|
-
|
|
1533
1333
|
if ((event.inputType == 'insertParagraph' || event.inputType == 'insertLineBreak') && focus) {
|
|
1534
1334
|
this.clearDirtyFlag();
|
|
1535
1335
|
this.processNewParagraph(focus);
|
|
@@ -1547,22 +1347,21 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1547
1347
|
}
|
|
1548
1348
|
}
|
|
1549
1349
|
}
|
|
1550
|
-
|
|
1551
1350
|
this.updateLineContentsAndFormatting();
|
|
1552
1351
|
}
|
|
1553
|
-
|
|
1554
1352
|
if (focus) this.setSelection(focus);
|
|
1555
1353
|
this.fireChange();
|
|
1556
1354
|
}
|
|
1355
|
+
|
|
1557
1356
|
/**
|
|
1558
1357
|
* Event handler for "selectionchange" events.
|
|
1559
1358
|
*/
|
|
1560
|
-
|
|
1561
1359
|
}, {
|
|
1562
1360
|
key: "handleSelectionChangeEvent",
|
|
1563
1361
|
value: function handleSelectionChangeEvent() {
|
|
1564
1362
|
this.fireSelection();
|
|
1565
1363
|
}
|
|
1364
|
+
|
|
1566
1365
|
/**
|
|
1567
1366
|
* Convenience function to "splice" new lines into the arrays this.lines, this.lineDirty, this.lineTypes, and the DOM elements
|
|
1568
1367
|
* underneath the editor element.
|
|
@@ -1574,58 +1373,51 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1574
1373
|
* @param {array} linesToInsert Array of strings representing the lines to be inserted
|
|
1575
1374
|
* @param {boolean} adjustLineElements If true, then <div> elements are also inserted in the DOM at the respective position
|
|
1576
1375
|
*/
|
|
1577
|
-
|
|
1578
1376
|
}, {
|
|
1579
1377
|
key: "spliceLines",
|
|
1580
1378
|
value: function spliceLines(startLine) {
|
|
1581
1379
|
var _this$lines, _this$lineTypes, _this$lineDirty;
|
|
1582
|
-
|
|
1583
1380
|
var linesToDelete = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
1584
1381
|
var linesToInsert = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
|
|
1585
1382
|
var adjustLineElements = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
|
1586
|
-
|
|
1587
1383
|
if (adjustLineElements) {
|
|
1588
1384
|
for (var i = 0; i < linesToDelete; i++) {
|
|
1589
1385
|
this.e.removeChild(this.e.childNodes[startLine]);
|
|
1590
1386
|
}
|
|
1591
1387
|
}
|
|
1592
|
-
|
|
1593
1388
|
var insertedBlank = [];
|
|
1594
1389
|
var insertedDirty = [];
|
|
1595
|
-
|
|
1596
1390
|
for (var _i3 = 0; _i3 < linesToInsert.length; _i3++) {
|
|
1597
1391
|
insertedBlank.push('');
|
|
1598
1392
|
insertedDirty.push(true);
|
|
1599
|
-
|
|
1600
1393
|
if (adjustLineElements) {
|
|
1601
1394
|
if (this.e.childNodes[startLine]) this.e.insertBefore(document.createElement('div'), this.e.childNodes[startLine]);else this.e.appendChild(document.createElement('div'));
|
|
1602
1395
|
}
|
|
1603
1396
|
}
|
|
1604
|
-
|
|
1605
1397
|
(_this$lines = this.lines).splice.apply(_this$lines, [startLine, linesToDelete].concat(_toConsumableArray(linesToInsert)));
|
|
1606
|
-
|
|
1607
1398
|
(_this$lineTypes = this.lineTypes).splice.apply(_this$lineTypes, [startLine, linesToDelete].concat(insertedBlank));
|
|
1608
|
-
|
|
1609
1399
|
(_this$lineDirty = this.lineDirty).splice.apply(_this$lineDirty, [startLine, linesToDelete].concat(insertedDirty));
|
|
1610
1400
|
}
|
|
1401
|
+
|
|
1611
1402
|
/**
|
|
1612
1403
|
* Event handler for the "paste" event
|
|
1613
1404
|
*/
|
|
1614
|
-
|
|
1615
1405
|
}, {
|
|
1616
1406
|
key: "handlePaste",
|
|
1617
1407
|
value: function handlePaste(event) {
|
|
1618
|
-
event.preventDefault();
|
|
1408
|
+
event.preventDefault();
|
|
1619
1409
|
|
|
1620
|
-
|
|
1410
|
+
// get text representation of clipboard
|
|
1411
|
+
var text = (event.originalEvent || event).clipboardData.getData('text/plain');
|
|
1621
1412
|
|
|
1413
|
+
// insert text manually
|
|
1622
1414
|
this.paste(text);
|
|
1623
1415
|
}
|
|
1416
|
+
|
|
1624
1417
|
/**
|
|
1625
1418
|
* Pastes the text at the current selection (or at the end, if no current selection)
|
|
1626
1419
|
* @param {string} text
|
|
1627
1420
|
*/
|
|
1628
|
-
|
|
1629
1421
|
}, {
|
|
1630
1422
|
key: "paste",
|
|
1631
1423
|
value: function paste(text) {
|
|
@@ -1634,7 +1426,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1634
1426
|
if (!anchor) anchor = this.getSelection(true);
|
|
1635
1427
|
if (!focus) focus = this.getSelection(false);
|
|
1636
1428
|
var beginning, end;
|
|
1637
|
-
|
|
1638
1429
|
if (!focus) {
|
|
1639
1430
|
focus = {
|
|
1640
1431
|
row: this.lines.length - 1,
|
|
@@ -1645,7 +1436,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1645
1436
|
if (!anchor) {
|
|
1646
1437
|
anchor = focus;
|
|
1647
1438
|
}
|
|
1648
|
-
|
|
1649
1439
|
if (anchor.row < focus.row || anchor.row == focus.row && anchor.col <= focus.col) {
|
|
1650
1440
|
beginning = anchor;
|
|
1651
1441
|
end = focus;
|
|
@@ -1653,7 +1443,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1653
1443
|
beginning = focus;
|
|
1654
1444
|
end = anchor;
|
|
1655
1445
|
}
|
|
1656
|
-
|
|
1657
1446
|
var insertedLines = text.split(/(?:\r\n|\r|\n)/);
|
|
1658
1447
|
var lineBefore = this.lines[beginning.row].substr(0, beginning.col);
|
|
1659
1448
|
var lineEnd = this.lines[end.row].substr(end.col);
|
|
@@ -1667,41 +1456,36 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1667
1456
|
this.setSelection(focus);
|
|
1668
1457
|
this.fireChange();
|
|
1669
1458
|
}
|
|
1459
|
+
|
|
1670
1460
|
/**
|
|
1671
1461
|
* Computes the (lowest in the DOM tree) common ancestor of two DOM nodes.
|
|
1672
1462
|
* @param {Node} node1 the first node
|
|
1673
1463
|
* @param {Node} node2 the second node
|
|
1674
1464
|
* @returns {Node} The commen ancestor node, or null if there is no common ancestor
|
|
1675
1465
|
*/
|
|
1676
|
-
|
|
1677
1466
|
}, {
|
|
1678
1467
|
key: "computeCommonAncestor",
|
|
1679
1468
|
value: function computeCommonAncestor(node1, node2) {
|
|
1680
1469
|
if (!node1 || !node2) return null;
|
|
1681
1470
|
if (node1 == node2) return node1;
|
|
1682
|
-
|
|
1683
1471
|
var ancestry = function ancestry(node) {
|
|
1684
1472
|
var ancestry = [];
|
|
1685
|
-
|
|
1686
1473
|
while (node) {
|
|
1687
1474
|
ancestry.unshift(node);
|
|
1688
1475
|
node = node.parentNode;
|
|
1689
1476
|
}
|
|
1690
|
-
|
|
1691
1477
|
return ancestry;
|
|
1692
1478
|
};
|
|
1693
|
-
|
|
1694
1479
|
var ancestry1 = ancestry(node1);
|
|
1695
1480
|
var ancestry2 = ancestry(node2);
|
|
1696
1481
|
if (ancestry1[0] != ancestry2[0]) return null;
|
|
1697
1482
|
var i;
|
|
1698
|
-
|
|
1699
1483
|
for (i = 0; ancestry1[i] == ancestry2[i]; i++) {
|
|
1700
1484
|
;
|
|
1701
1485
|
}
|
|
1702
|
-
|
|
1703
1486
|
return ancestry1[i - 1];
|
|
1704
1487
|
}
|
|
1488
|
+
|
|
1705
1489
|
/**
|
|
1706
1490
|
* Finds the (lowest in the DOM tree) enclosing DOM node with a given class.
|
|
1707
1491
|
* @param {object} focus The focus selection object
|
|
@@ -1709,35 +1493,30 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1709
1493
|
* @param {string} className The class name to find
|
|
1710
1494
|
* @returns {Node} The enclosing DOM node with the respective class (inside the editor), if there is one; null otherwise.
|
|
1711
1495
|
*/
|
|
1712
|
-
|
|
1713
1496
|
}, {
|
|
1714
1497
|
key: "computeEnclosingMarkupNode",
|
|
1715
1498
|
value: function computeEnclosingMarkupNode(focus, anchor, className) {
|
|
1716
1499
|
var node = null;
|
|
1717
1500
|
if (!focus) return null;
|
|
1718
|
-
|
|
1719
1501
|
if (!anchor) {
|
|
1720
1502
|
node = focus.node;
|
|
1721
1503
|
} else {
|
|
1722
1504
|
if (focus.row != anchor.row) return null;
|
|
1723
1505
|
node = this.computeCommonAncestor(focus.node, anchor.node);
|
|
1724
1506
|
}
|
|
1725
|
-
|
|
1726
1507
|
if (!node) return null;
|
|
1727
|
-
|
|
1728
1508
|
while (node != this.e) {
|
|
1729
1509
|
if (node.className && node.className.includes(className)) return node;
|
|
1730
1510
|
node = node.parentNode;
|
|
1731
|
-
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1511
|
+
}
|
|
1512
|
+
// Ascended all the way to the editor element
|
|
1734
1513
|
return null;
|
|
1735
1514
|
}
|
|
1515
|
+
|
|
1736
1516
|
/**
|
|
1737
1517
|
* Returns the state (true / false) of all commands.
|
|
1738
1518
|
* @param focus Focus of the selection. If not given, assumes the current focus.
|
|
1739
1519
|
*/
|
|
1740
|
-
|
|
1741
1520
|
}, {
|
|
1742
1521
|
key: "getCommandState",
|
|
1743
1522
|
value: function getCommandState() {
|
|
@@ -1746,18 +1525,14 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1746
1525
|
var commandState = {};
|
|
1747
1526
|
if (!focus) focus = this.getSelection(false);
|
|
1748
1527
|
if (!anchor) anchor = this.getSelection(true);
|
|
1749
|
-
|
|
1750
1528
|
if (!focus) {
|
|
1751
1529
|
for (var cmd in _grammar.commands) {
|
|
1752
1530
|
commandState[cmd] = null;
|
|
1753
1531
|
}
|
|
1754
|
-
|
|
1755
1532
|
return commandState;
|
|
1756
1533
|
}
|
|
1757
|
-
|
|
1758
1534
|
if (!anchor) anchor = focus;
|
|
1759
1535
|
var start, end;
|
|
1760
|
-
|
|
1761
1536
|
if (anchor.row < focus.row || anchor.row == focus.row && anchor.col < focus.col) {
|
|
1762
1537
|
start = anchor;
|
|
1763
1538
|
end = focus;
|
|
@@ -1765,7 +1540,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1765
1540
|
start = focus;
|
|
1766
1541
|
end = anchor;
|
|
1767
1542
|
}
|
|
1768
|
-
|
|
1769
1543
|
if (end.row > start.row && end.col == 0) {
|
|
1770
1544
|
end.row--;
|
|
1771
1545
|
end.col = this.lines[end.row].length; // Selection to beginning of next line is said to end at the beginning of the last line
|
|
@@ -1777,37 +1551,35 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1777
1551
|
commandState[_cmd] = null;
|
|
1778
1552
|
} else {
|
|
1779
1553
|
// The command state is true if there is a respective enclosing markup node (e.g., the selection is enclosed in a <b>..</b>) ...
|
|
1780
|
-
commandState[_cmd] = !!this.computeEnclosingMarkupNode(focus, anchor, _grammar.commands[_cmd].className) ||
|
|
1554
|
+
commandState[_cmd] = !!this.computeEnclosingMarkupNode(focus, anchor, _grammar.commands[_cmd].className) ||
|
|
1555
|
+
// ... or if it's an empty string preceded by and followed by formatting markers, e.g. **|** where | is the cursor
|
|
1556
|
+
|
|
1781
1557
|
focus.col == anchor.col && !!this.lines[focus.row].substr(0, focus.col).match(_grammar.commands[_cmd].unset.prePattern) && !!this.lines[focus.row].substr(focus.col).match(_grammar.commands[_cmd].unset.postPattern);
|
|
1782
1558
|
}
|
|
1783
1559
|
}
|
|
1784
|
-
|
|
1785
1560
|
if (_grammar.commands[_cmd].type == 'line') {
|
|
1786
1561
|
if (!focus) {
|
|
1787
1562
|
commandState[_cmd] = null;
|
|
1788
1563
|
} else {
|
|
1789
1564
|
var state = this.lineTypes[start.row] == _grammar.commands[_cmd].className;
|
|
1790
|
-
|
|
1791
1565
|
for (var line = start.row; line <= end.row; line++) {
|
|
1792
1566
|
if (this.lineTypes[line] == _grammar.commands[_cmd].className != state) {
|
|
1793
1567
|
state = null;
|
|
1794
1568
|
break;
|
|
1795
1569
|
}
|
|
1796
1570
|
}
|
|
1797
|
-
|
|
1798
1571
|
commandState[_cmd] = state;
|
|
1799
1572
|
}
|
|
1800
1573
|
}
|
|
1801
1574
|
}
|
|
1802
|
-
|
|
1803
1575
|
return commandState;
|
|
1804
1576
|
}
|
|
1577
|
+
|
|
1805
1578
|
/**
|
|
1806
1579
|
* Sets a command state
|
|
1807
1580
|
* @param {string} command
|
|
1808
1581
|
* @param {boolean} state
|
|
1809
1582
|
*/
|
|
1810
|
-
|
|
1811
1583
|
}, {
|
|
1812
1584
|
key: "setCommandState",
|
|
1813
1585
|
value: function setCommandState(command, state) {
|
|
@@ -1819,8 +1591,9 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1819
1591
|
if (anchor.row != focus.row) return;
|
|
1820
1592
|
if (!this.isInlineFormattingAllowed(focus, anchor)) return;
|
|
1821
1593
|
var markupNode = this.computeEnclosingMarkupNode(focus, anchor, _grammar.commands[command].className);
|
|
1822
|
-
this.clearDirtyFlag();
|
|
1594
|
+
this.clearDirtyFlag();
|
|
1823
1595
|
|
|
1596
|
+
// First case: There's an enclosing markup node, remove the markers around that markup node
|
|
1824
1597
|
if (markupNode) {
|
|
1825
1598
|
this.lineDirty[focus.row] = true;
|
|
1826
1599
|
var startCol = this.computeColumn(markupNode, 0);
|
|
@@ -1832,72 +1605,66 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1832
1605
|
anchor.col = left.length;
|
|
1833
1606
|
focus.col = anchor.col + len;
|
|
1834
1607
|
this.updateFormatting();
|
|
1835
|
-
this.setSelection(focus, anchor);
|
|
1608
|
+
this.setSelection(focus, anchor);
|
|
1609
|
+
|
|
1610
|
+
// Second case: Empty selection with surrounding formatting markers, remove those
|
|
1836
1611
|
} else if (focus.col == anchor.col && !!this.lines[focus.row].substr(0, focus.col).match(_grammar.commands[command].unset.prePattern) && !!this.lines[focus.row].substr(focus.col).match(_grammar.commands[command].unset.postPattern)) {
|
|
1837
1612
|
this.lineDirty[focus.row] = true;
|
|
1838
|
-
|
|
1839
1613
|
var _left = this.lines[focus.row].substr(0, focus.col).replace(_grammar.commands[command].unset.prePattern, '');
|
|
1840
|
-
|
|
1841
1614
|
var _right = this.lines[focus.row].substr(focus.col).replace(_grammar.commands[command].unset.postPattern, '');
|
|
1842
|
-
|
|
1843
1615
|
this.lines[focus.row] = _left.concat(_right);
|
|
1844
1616
|
focus.col = anchor.col = _left.length;
|
|
1845
1617
|
this.updateFormatting();
|
|
1846
|
-
this.setSelection(focus, anchor);
|
|
1618
|
+
this.setSelection(focus, anchor);
|
|
1619
|
+
|
|
1620
|
+
// Not currently formatted, insert formatting markers
|
|
1847
1621
|
} else {
|
|
1848
1622
|
// Trim any spaces from the selection
|
|
1849
1623
|
var _ref = focus.col < anchor.col ? {
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
var match = this.lines[focus.row].substr(_startCol, endCol - _startCol).match( /*#__PURE__*/_wrapRegExp(/^([\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*).*[\0-\x08\x0E-\x1F!-\x9F\xA1-\u167F\u1681-\u1FFF\u200B-\u2027\u202A-\u202E\u2030-\u205E\u2060-\u2FFF\u3001-\uFEFE\uFF00-\uFFFF]([\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*)$/, {
|
|
1624
|
+
startCol: focus.col,
|
|
1625
|
+
endCol: anchor.col
|
|
1626
|
+
} : {
|
|
1627
|
+
startCol: anchor.col,
|
|
1628
|
+
endCol: focus.col
|
|
1629
|
+
},
|
|
1630
|
+
_startCol = _ref.startCol,
|
|
1631
|
+
endCol = _ref.endCol;
|
|
1632
|
+
var match = this.lines[focus.row].substr(_startCol, endCol - _startCol).match( /*#__PURE__*/_wrapRegExp(/^(\s*).*\S(\s*)$/, {
|
|
1860
1633
|
leading: 1,
|
|
1861
1634
|
trailing: 2
|
|
1862
1635
|
}));
|
|
1863
|
-
|
|
1864
1636
|
if (match) {
|
|
1865
1637
|
_startCol += match.groups.leading.length;
|
|
1866
1638
|
endCol -= match.groups.trailing.length;
|
|
1867
1639
|
}
|
|
1868
|
-
|
|
1869
1640
|
focus.col = _startCol;
|
|
1870
|
-
anchor.col = endCol;
|
|
1641
|
+
anchor.col = endCol;
|
|
1871
1642
|
|
|
1872
|
-
|
|
1643
|
+
// Just insert markup before and after and hope for the best.
|
|
1644
|
+
this.wrapSelection(_grammar.commands[command].set.pre, _grammar.commands[command].set.post, focus, anchor);
|
|
1645
|
+
// TODO clean this up so that markup remains properly nested
|
|
1873
1646
|
}
|
|
1874
1647
|
} else if (_grammar.commands[command].type == 'line') {
|
|
1875
1648
|
var _anchor = this.getSelection(true);
|
|
1876
|
-
|
|
1877
1649
|
var _focus = this.getSelection(false);
|
|
1878
|
-
|
|
1879
1650
|
if (!_anchor) _anchor = _focus;
|
|
1880
1651
|
if (!_focus) return;
|
|
1881
1652
|
this.clearDirtyFlag();
|
|
1882
1653
|
var start = _anchor.row > _focus.row ? _focus : _anchor;
|
|
1883
1654
|
var end = _anchor.row > _focus.row ? _anchor : _focus;
|
|
1884
|
-
|
|
1885
1655
|
if (end.row > start.row && end.col == 0) {
|
|
1886
1656
|
end.row--;
|
|
1887
1657
|
}
|
|
1888
|
-
|
|
1889
1658
|
for (var line = start.row; line <= end.row; line++) {
|
|
1890
1659
|
if (state && this.lineTypes[line] != _grammar.commands[command].className) {
|
|
1891
1660
|
this.lines[line] = this.lines[line].replace(_grammar.commands[command].set.pattern, _grammar.commands[command].set.replacement.replace('$#', line - start.row + 1));
|
|
1892
1661
|
this.lineDirty[line] = true;
|
|
1893
1662
|
}
|
|
1894
|
-
|
|
1895
1663
|
if (!state && this.lineTypes[line] == _grammar.commands[command].className) {
|
|
1896
1664
|
this.lines[line] = this.lines[line].replace(_grammar.commands[command].unset.pattern, _grammar.commands[command].unset.replacement);
|
|
1897
1665
|
this.lineDirty[line] = true;
|
|
1898
1666
|
}
|
|
1899
1667
|
}
|
|
1900
|
-
|
|
1901
1668
|
this.updateFormatting();
|
|
1902
1669
|
this.setSelection({
|
|
1903
1670
|
row: end.row,
|
|
@@ -1908,40 +1675,41 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1908
1675
|
});
|
|
1909
1676
|
}
|
|
1910
1677
|
}
|
|
1678
|
+
|
|
1911
1679
|
/**
|
|
1912
1680
|
* Returns whether or not inline formatting is allowed at the current focus
|
|
1913
1681
|
* @param {object} focus The current focus
|
|
1914
1682
|
*/
|
|
1915
|
-
|
|
1916
1683
|
}, {
|
|
1917
1684
|
key: "isInlineFormattingAllowed",
|
|
1918
1685
|
value: function isInlineFormattingAllowed() {
|
|
1919
1686
|
// TODO Remove parameters from all calls
|
|
1920
1687
|
var sel = window.getSelection();
|
|
1921
|
-
if (!sel) return false;
|
|
1922
|
-
|
|
1688
|
+
if (!sel) return false;
|
|
1689
|
+
|
|
1690
|
+
// Check if we can find a common ancestor with the class `TMInlineFormatted`
|
|
1923
1691
|
|
|
1692
|
+
// Special case: Empty selection right before `TMInlineFormatted`
|
|
1924
1693
|
if (sel.isCollapsed && sel.focusNode.nodeType == 3 && sel.focusOffset == sel.focusNode.nodeValue.length) {
|
|
1925
1694
|
var node;
|
|
1926
|
-
|
|
1927
1695
|
for (node = sel.focusNode; node && node.nextSibling == null; node = node.parentNode) {
|
|
1928
1696
|
;
|
|
1929
1697
|
}
|
|
1930
|
-
|
|
1931
1698
|
if (node && node.nextSibling.className && node.nextSibling.className.includes('TMInlineFormatted')) return true;
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1699
|
+
}
|
|
1934
1700
|
|
|
1701
|
+
// Look for a common ancestor
|
|
1935
1702
|
var ancestor = this.computeCommonAncestor(sel.focusNode, sel.anchorNode);
|
|
1936
|
-
if (!ancestor) return false;
|
|
1703
|
+
if (!ancestor) return false;
|
|
1937
1704
|
|
|
1705
|
+
// Check if there's an ancestor of class 'TMInlineFormatted' or 'TMBlankLine'
|
|
1938
1706
|
while (ancestor && ancestor != this.e) {
|
|
1939
1707
|
if (ancestor.className && (ancestor.className.includes('TMInlineFormatted') || ancestor.className.includes('TMBlankLine'))) return true;
|
|
1940
1708
|
ancestor = ancestor.parentNode;
|
|
1941
1709
|
}
|
|
1942
|
-
|
|
1943
1710
|
return false;
|
|
1944
1711
|
}
|
|
1712
|
+
|
|
1945
1713
|
/**
|
|
1946
1714
|
* Wraps the current selection in the strings pre and post. If the selection is not on one line, returns.
|
|
1947
1715
|
* @param {string} pre The string to insert before the selection.
|
|
@@ -1949,7 +1717,6 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1949
1717
|
* @param {object} focus The current selection focus. If null, selection will be computed.
|
|
1950
1718
|
* @param {object} anchor The current selection focus. If null, selection will be computed.
|
|
1951
1719
|
*/
|
|
1952
|
-
|
|
1953
1720
|
}, {
|
|
1954
1721
|
key: "wrapSelection",
|
|
1955
1722
|
value: function wrapSelection(pre, post) {
|
|
@@ -1970,31 +1737,29 @@ var Editor = /*#__PURE__*/function () {
|
|
|
1970
1737
|
this.updateFormatting();
|
|
1971
1738
|
this.setSelection(focus, anchor);
|
|
1972
1739
|
}
|
|
1740
|
+
|
|
1973
1741
|
/**
|
|
1974
1742
|
* Toggles the command state for a command (true <-> false)
|
|
1975
1743
|
* @param {string} command The editor command
|
|
1976
1744
|
*/
|
|
1977
|
-
|
|
1978
1745
|
}, {
|
|
1979
1746
|
key: "toggleCommandState",
|
|
1980
1747
|
value: function toggleCommandState(command) {
|
|
1981
1748
|
if (!this.lastCommandState) this.lastCommandState = this.getCommandState();
|
|
1982
1749
|
this.setCommandState(command, !this.lastCommandState[command]);
|
|
1983
1750
|
}
|
|
1751
|
+
|
|
1984
1752
|
/**
|
|
1985
1753
|
* Fires a change event. Updates the linked textarea and notifies any event listeners.
|
|
1986
1754
|
*/
|
|
1987
|
-
|
|
1988
1755
|
}, {
|
|
1989
1756
|
key: "fireChange",
|
|
1990
1757
|
value: function fireChange() {
|
|
1991
1758
|
if (!this.textarea && !this.listeners.change.length) return;
|
|
1992
1759
|
var content = this.getContent();
|
|
1993
1760
|
if (this.textarea) this.textarea.value = content;
|
|
1994
|
-
|
|
1995
1761
|
var _iterator3 = _createForOfIteratorHelper(this.listeners.change),
|
|
1996
|
-
|
|
1997
|
-
|
|
1762
|
+
_step3;
|
|
1998
1763
|
try {
|
|
1999
1764
|
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
2000
1765
|
var listener = _step3.value;
|
|
@@ -2009,10 +1774,10 @@ var Editor = /*#__PURE__*/function () {
|
|
|
2009
1774
|
_iterator3.f();
|
|
2010
1775
|
}
|
|
2011
1776
|
}
|
|
1777
|
+
|
|
2012
1778
|
/**
|
|
2013
1779
|
* Fires a "selection changed" event.
|
|
2014
1780
|
*/
|
|
2015
|
-
|
|
2016
1781
|
}, {
|
|
2017
1782
|
key: "fireSelection",
|
|
2018
1783
|
value: function fireSelection() {
|
|
@@ -2020,16 +1785,13 @@ var Editor = /*#__PURE__*/function () {
|
|
|
2020
1785
|
var focus = this.getSelection(false);
|
|
2021
1786
|
var anchor = this.getSelection(true);
|
|
2022
1787
|
var commandState = this.getCommandState(focus, anchor);
|
|
2023
|
-
|
|
2024
1788
|
if (this.lastCommandState) {
|
|
2025
1789
|
Object.assign(this.lastCommandState, commandState);
|
|
2026
1790
|
} else {
|
|
2027
1791
|
this.lastCommandState = Object.assign({}, commandState);
|
|
2028
1792
|
}
|
|
2029
|
-
|
|
2030
1793
|
var _iterator4 = _createForOfIteratorHelper(this.listeners.selection),
|
|
2031
|
-
|
|
2032
|
-
|
|
1794
|
+
_step4;
|
|
2033
1795
|
try {
|
|
2034
1796
|
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
2035
1797
|
var listener = _step4.value;
|
|
@@ -2046,27 +1808,24 @@ var Editor = /*#__PURE__*/function () {
|
|
|
2046
1808
|
}
|
|
2047
1809
|
}
|
|
2048
1810
|
}
|
|
1811
|
+
|
|
2049
1812
|
/**
|
|
2050
1813
|
* Adds an event listener.
|
|
2051
1814
|
* @param {string} type The type of event to listen to. Can be 'change' or 'selection'
|
|
2052
1815
|
* @param {*} listener Function of the type (event) => {} to be called when the event occurs.
|
|
2053
1816
|
*/
|
|
2054
|
-
|
|
2055
1817
|
}, {
|
|
2056
1818
|
key: "addEventListener",
|
|
2057
1819
|
value: function addEventListener(type, listener) {
|
|
2058
1820
|
if (type.match(/^(?:change|input)$/i)) {
|
|
2059
1821
|
this.listeners.change.push(listener);
|
|
2060
1822
|
}
|
|
2061
|
-
|
|
2062
1823
|
if (type.match(/^(?:selection|selectionchange)$/i)) {
|
|
2063
1824
|
this.listeners.selection.push(listener);
|
|
2064
1825
|
}
|
|
2065
1826
|
}
|
|
2066
1827
|
}]);
|
|
2067
|
-
|
|
2068
1828
|
return Editor;
|
|
2069
1829
|
}();
|
|
2070
|
-
|
|
2071
1830
|
var _default = Editor;
|
|
2072
1831
|
exports.default = _default;
|