1 | "use strict";
|
2 |
|
3 | var _toConsumableArray2 = require("babel-runtime/helpers/toConsumableArray");
|
4 |
|
5 | var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
|
6 |
|
7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
8 |
|
9 | var PLACEHOLDERS = {
|
10 | id: "__id__",
|
11 | display: "__display__",
|
12 | type: "__type__"
|
13 | };
|
14 |
|
15 | var escapeMap = {
|
16 | '&': '&',
|
17 | '<': '<',
|
18 | '>': '>',
|
19 | '"': '"',
|
20 | "'": ''',
|
21 | '`': '`'
|
22 | };
|
23 | var createEscaper = function createEscaper(map) {
|
24 | var escaper = function escaper(match) {
|
25 | return map[match];
|
26 | };
|
27 | var keys = [];
|
28 | for (var key in map) {
|
29 | if (map.hasOwnProperty(key)) keys.push(key);
|
30 | }
|
31 | var source = '(?:' + keys.join('|') + ')';
|
32 | var testRegexp = RegExp(source);
|
33 | var replaceRegexp = RegExp(source, 'g');
|
34 | return function (string) {
|
35 | string = string == null ? '' : '' + string;
|
36 | return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
|
37 | };
|
38 | };
|
39 |
|
40 | var numericComparator = function numericComparator(a, b) {
|
41 | a = a === null ? Number.MAX_VALUE : a;
|
42 | b = b === null ? Number.MAX_VALUE : b;
|
43 | return a - b;
|
44 | };
|
45 |
|
46 | module.exports = {
|
47 |
|
48 | escapeHtml: createEscaper(escapeMap),
|
49 |
|
50 | escapeRegex: function escapeRegex(str) {
|
51 | return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
52 | },
|
53 |
|
54 | markupToRegex: function markupToRegex(markup, matchAtEnd) {
|
55 | var markupPattern = this.escapeRegex(markup);
|
56 | markupPattern = markupPattern.replace(PLACEHOLDERS.display, "(.+?)");
|
57 | markupPattern = markupPattern.replace(PLACEHOLDERS.id, "(.+?)");
|
58 | markupPattern = markupPattern.replace(PLACEHOLDERS.type, "(.+?)");
|
59 | if (matchAtEnd) {
|
60 |
|
61 | markupPattern = markupPattern + "$";
|
62 | }
|
63 | return new RegExp(markupPattern, "g");
|
64 | },
|
65 |
|
66 | spliceString: function spliceString(str, start, end, insert) {
|
67 | return str.substring(0, start) + insert + str.substring(end);
|
68 | },
|
69 |
|
70 | extend: function extend(obj) {
|
71 | var source, prop;
|
72 | for (var i = 1, length = arguments.length; i < length; i++) {
|
73 | source = arguments[i];
|
74 | for (prop in source) {
|
75 | if (hasOwnProperty.call(source, prop)) {
|
76 | obj[prop] = source[prop];
|
77 | }
|
78 | }
|
79 | }
|
80 | return obj;
|
81 | },
|
82 |
|
83 | isNumber: function isNumber(obj) {
|
84 | return Object.prototype.toString.call(obj) === "[object Number]";
|
85 | },
|
86 |
|
87 | |
88 |
|
89 |
|
90 | getPositionOfCapturingGroup: function getPositionOfCapturingGroup(markup, parameterName) {
|
91 | if (parameterName !== "id" && parameterName !== "display" && parameterName !== "type") {
|
92 | throw new Error("parameterName must be 'id', 'display', or 'type'");
|
93 | }
|
94 |
|
95 |
|
96 | var indexDisplay = markup.indexOf(PLACEHOLDERS.display);
|
97 | var indexId = markup.indexOf(PLACEHOLDERS.id);
|
98 | var indexType = markup.indexOf(PLACEHOLDERS.type);
|
99 |
|
100 |
|
101 | if (indexDisplay < 0) indexDisplay = null;
|
102 | if (indexId < 0) indexId = null;
|
103 | if (indexType < 0) indexType = null;
|
104 |
|
105 | if (indexDisplay === null && indexId === null) {
|
106 |
|
107 | throw new Error("The markup `" + markup + "` must contain at least one of the placeholders `__id__` or `__display__`");
|
108 | }
|
109 |
|
110 | if (indexType === null && parameterName === "type") {
|
111 |
|
112 | return null;
|
113 | }
|
114 |
|
115 |
|
116 | var sortedIndices = [indexDisplay, indexId, indexType].sort(numericComparator);
|
117 |
|
118 |
|
119 |
|
120 | if (indexDisplay === null) indexDisplay = indexId;
|
121 | if (indexId === null) indexId = indexDisplay;
|
122 |
|
123 | if (parameterName === "id") return sortedIndices.indexOf(indexId);
|
124 | if (parameterName === "display") return sortedIndices.indexOf(indexDisplay);
|
125 | if (parameterName === "type") return indexType === null ? null : sortedIndices.indexOf(indexType);
|
126 | },
|
127 |
|
128 |
|
129 |
|
130 |
|
131 | iterateMentionsMarkup: function iterateMentionsMarkup(value, markup, textIteratee, markupIteratee, displayTransform) {
|
132 | var regex = this.markupToRegex(markup);
|
133 | var displayPos = this.getPositionOfCapturingGroup(markup, "display");
|
134 | var idPos = this.getPositionOfCapturingGroup(markup, "id");
|
135 | var typePos = this.getPositionOfCapturingGroup(markup, "type");
|
136 |
|
137 | var match;
|
138 | var start = 0;
|
139 | var currentPlainTextIndex = 0;
|
140 |
|
141 |
|
142 | while ((match = regex.exec(value)) !== null) {
|
143 |
|
144 | var id = match[idPos + 1];
|
145 | var display = match[displayPos + 1];
|
146 | var type = typePos !== null ? match[typePos + 1] : null;
|
147 |
|
148 | if (displayTransform) display = displayTransform(id, display, type);
|
149 |
|
150 | var substr = value.substring(start, match.index);
|
151 | textIteratee(substr, start, currentPlainTextIndex);
|
152 | currentPlainTextIndex += substr.length;
|
153 |
|
154 | markupIteratee(match[0], match.index, currentPlainTextIndex, id, display, type, start);
|
155 | currentPlainTextIndex += display.length;
|
156 |
|
157 | start = regex.lastIndex;
|
158 | }
|
159 |
|
160 | if (start < value.length) {
|
161 | textIteratee(value.substring(start), start, currentPlainTextIndex);
|
162 | }
|
163 | },
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | mapPlainTextIndex: function mapPlainTextIndex(value, markup, indexInPlainText) {
|
173 | var inMarkupCorrection = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'START';
|
174 | var displayTransform = arguments[4];
|
175 |
|
176 | if (!this.isNumber(indexInPlainText)) {
|
177 | return indexInPlainText;
|
178 | }
|
179 |
|
180 | var result;
|
181 | var textIteratee = function textIteratee(substr, index, substrPlainTextIndex) {
|
182 | if (result !== undefined) return;
|
183 |
|
184 | if (substrPlainTextIndex + substr.length >= indexInPlainText) {
|
185 |
|
186 | result = index + indexInPlainText - substrPlainTextIndex;
|
187 | }
|
188 | };
|
189 | var markupIteratee = function markupIteratee(markup, index, mentionPlainTextIndex, id, display, type, lastMentionEndIndex) {
|
190 | if (result !== undefined) return;
|
191 |
|
192 | if (mentionPlainTextIndex + display.length > indexInPlainText) {
|
193 |
|
194 |
|
195 |
|
196 | if (inMarkupCorrection === 'NULL') {
|
197 | result = null;
|
198 | } else {
|
199 | result = index + (inMarkupCorrection === 'END' ? markup.length : 0);
|
200 | }
|
201 | }
|
202 | };
|
203 |
|
204 | this.iterateMentionsMarkup(value, markup, textIteratee, markupIteratee, displayTransform);
|
205 |
|
206 |
|
207 |
|
208 | return result === undefined ? value.length : result;
|
209 | },
|
210 |
|
211 |
|
212 |
|
213 |
|
214 | findStartOfMentionInPlainText: function findStartOfMentionInPlainText(value, markup, indexInPlainText, displayTransform) {
|
215 | var result = indexInPlainText;
|
216 | var foundMention = false;
|
217 |
|
218 | var markupIteratee = function markupIteratee(markup, index, mentionPlainTextIndex, id, display, type, lastMentionEndIndex) {
|
219 | if (mentionPlainTextIndex <= indexInPlainText && mentionPlainTextIndex + display.length > indexInPlainText) {
|
220 | result = mentionPlainTextIndex;
|
221 | foundMention = true;
|
222 | }
|
223 | };
|
224 | this.iterateMentionsMarkup(value, markup, function () {}, markupIteratee, displayTransform);
|
225 |
|
226 | if (foundMention) {
|
227 | return result;
|
228 | }
|
229 | },
|
230 |
|
231 |
|
232 | isInsideOfMention: function isInsideOfMention(value, markup, indexInPlainText, displayTransform) {
|
233 | var mentionStart = this.findStartOfMentionInPlainText(value, markup, indexInPlainText, displayTransform);
|
234 | return mentionStart !== undefined && mentionStart !== indexInPlainText;
|
235 | },
|
236 |
|
237 |
|
238 |
|
239 | applyChangeToValue: function applyChangeToValue(value, markup, plainTextValue, selectionStartBeforeChange, selectionEndBeforeChange, selectionEndAfterChange, displayTransform) {
|
240 | var oldPlainTextValue = this.getPlainText(value, markup, displayTransform);
|
241 |
|
242 | var lengthDelta = oldPlainTextValue.length - plainTextValue.length;
|
243 | if (selectionStartBeforeChange === 'undefined') {
|
244 | selectionStartBeforeChange = selectionEndAfterChange + lengthDelta;
|
245 | }
|
246 |
|
247 | if (selectionEndBeforeChange === 'undefined') {
|
248 | selectionEndBeforeChange = selectionStartBeforeChange;
|
249 | }
|
250 |
|
251 |
|
252 | if (selectionStartBeforeChange === selectionEndBeforeChange && selectionEndBeforeChange === selectionEndAfterChange && oldPlainTextValue.length === plainTextValue.length) {
|
253 | selectionStartBeforeChange = selectionStartBeforeChange - 1;
|
254 | }
|
255 |
|
256 |
|
257 | var insert = plainTextValue.slice(selectionStartBeforeChange, selectionEndAfterChange);
|
258 |
|
259 |
|
260 | var spliceStart = Math.min(selectionStartBeforeChange, selectionEndAfterChange);
|
261 |
|
262 | var spliceEnd = selectionEndBeforeChange;
|
263 | if (selectionStartBeforeChange === selectionEndAfterChange) {
|
264 |
|
265 | spliceEnd = Math.max(selectionEndBeforeChange, selectionStartBeforeChange + lengthDelta);
|
266 | }
|
267 |
|
268 | var mappedSpliceStart = this.mapPlainTextIndex(value, markup, spliceStart, 'START', displayTransform);
|
269 | var mappedSpliceEnd = this.mapPlainTextIndex(value, markup, spliceEnd, 'END', displayTransform);
|
270 |
|
271 | var controlSpliceStart = this.mapPlainTextIndex(value, markup, spliceStart, 'NULL', displayTransform);
|
272 | var controlSpliceEnd = this.mapPlainTextIndex(value, markup, spliceEnd, 'NULL', displayTransform);
|
273 | var willRemoveMention = controlSpliceStart === null || controlSpliceEnd === null;
|
274 |
|
275 | var newValue = this.spliceString(value, mappedSpliceStart, mappedSpliceEnd, insert);
|
276 |
|
277 | if (!willRemoveMention) {
|
278 |
|
279 | var controlPlainTextValue = this.getPlainText(newValue, markup, displayTransform);
|
280 | if (controlPlainTextValue !== plainTextValue) {
|
281 |
|
282 |
|
283 |
|
284 | spliceStart = 0;
|
285 | while (plainTextValue[spliceStart] === controlPlainTextValue[spliceStart]) {
|
286 | spliceStart++;
|
287 | }
|
288 | insert = plainTextValue.slice(spliceStart, selectionEndAfterChange);
|
289 |
|
290 |
|
291 | spliceEnd = oldPlainTextValue.lastIndexOf(plainTextValue.substring(selectionEndAfterChange));
|
292 |
|
293 |
|
294 | mappedSpliceStart = this.mapPlainTextIndex(value, markup, spliceStart, 'START', displayTransform);
|
295 | mappedSpliceEnd = this.mapPlainTextIndex(value, markup, spliceEnd, 'END', displayTransform);
|
296 | newValue = this.spliceString(value, mappedSpliceStart, mappedSpliceEnd, insert);
|
297 | }
|
298 | }
|
299 |
|
300 | return newValue;
|
301 | },
|
302 |
|
303 | getPlainText: function getPlainText(value, markup, displayTransform) {
|
304 | var regex = this.markupToRegex(markup);
|
305 | var idPos = this.getPositionOfCapturingGroup(markup, "id");
|
306 | var displayPos = this.getPositionOfCapturingGroup(markup, "display");
|
307 | var typePos = this.getPositionOfCapturingGroup(markup, "type");
|
308 | return value.replace(regex, function () {
|
309 |
|
310 | var id = arguments[idPos + 1];
|
311 | var display = arguments[displayPos + 1];
|
312 | var type = arguments[typePos + 1];
|
313 | if (displayTransform) display = displayTransform(id, display, type);
|
314 | return display;
|
315 | });
|
316 | },
|
317 |
|
318 | getMentions: function getMentions(value, markup) {
|
319 | var mentions = [];
|
320 | this.iterateMentionsMarkup(value, markup, function () {}, function (match, index, plainTextIndex, id, display, type, start) {
|
321 | mentions.push({
|
322 | id: id,
|
323 | display: display,
|
324 | type: type,
|
325 | index: index,
|
326 | plainTextIndex: plainTextIndex
|
327 | });
|
328 | });
|
329 | return mentions;
|
330 | },
|
331 |
|
332 | makeMentionsMarkup: function makeMentionsMarkup(markup, id, display, type) {
|
333 | var result = markup.replace(PLACEHOLDERS.id, id);
|
334 | result = result.replace(PLACEHOLDERS.display, display);
|
335 | result = result.replace(PLACEHOLDERS.type, type);
|
336 | return result;
|
337 | },
|
338 |
|
339 | countSuggestions: function countSuggestions(suggestions) {
|
340 | var result = 0;
|
341 | for (var prop in suggestions) {
|
342 | if (suggestions.hasOwnProperty(prop)) {
|
343 | result += suggestions[prop].results.length;
|
344 | }
|
345 | }
|
346 | return result;
|
347 | },
|
348 |
|
349 | getSuggestions: function getSuggestions(suggestions) {
|
350 | var result = [];
|
351 |
|
352 | for (var mentionType in suggestions) {
|
353 | if (!suggestions.hasOwnProperty(mentionType)) {
|
354 | return;
|
355 | }
|
356 |
|
357 | result = result.concat({
|
358 | suggestions: suggestions[mentionType].results,
|
359 | descriptor: suggestions[mentionType]
|
360 | });
|
361 | }
|
362 |
|
363 | return result;
|
364 | },
|
365 |
|
366 | getSuggestion: function getSuggestion(suggestions, index) {
|
367 | return this.getSuggestions(suggestions).reduce(function (result, _ref) {
|
368 | var suggestions = _ref.suggestions,
|
369 | descriptor = _ref.descriptor;
|
370 | return [].concat((0, _toConsumableArray3.default)(result), (0, _toConsumableArray3.default)(suggestions.map(function (suggestion) {
|
371 | return {
|
372 | suggestion: suggestion,
|
373 | descriptor: descriptor
|
374 | };
|
375 | })));
|
376 | }, [])[index];
|
377 | }
|
378 |
|
379 | }; |
\ | No newline at end of file |