@ohos-ports/advanced-mark.js 3.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1284 @@
1
+ /*!***************************************************
2
+ * advanced-mark.js v3.0.0
3
+ * https://github.com/angezid/advanced-mark.js
4
+ * MIT licensed
5
+ * Copyright (c) 2022–2026, angezid
6
+ * Based on 'mark.js', license https://git.io/vwTVl
7
+ *****************************************************/
8
+
9
+ class DOMIterator {
10
+ constructor(ctx, opt) {
11
+ this.ctx = ctx;
12
+ this.opt = opt;
13
+ this.map = new Map();
14
+ }
15
+ static matches(element, selector) {
16
+ if ( !selector || !selector.length) {
17
+ return false;
18
+ }
19
+ const selectors = typeof selector === 'string' ? [selector] : selector,
20
+ fn = element.matches;
21
+ return fn && selectors.some(sel => fn.call(element, sel));
22
+ }
23
+ getContexts() {
24
+ let ctx = this.ctx,
25
+ win = this.opt.window,
26
+ sort = false;
27
+ if ( !ctx) return [];
28
+ if (Array.isArray(ctx)) {
29
+ sort = true;
30
+ } else if (typeof ctx === 'string') {
31
+ ctx = win.document.querySelectorAll(ctx);
32
+ } else if (typeof ctx.length === 'undefined') {
33
+ ctx = [ctx];
34
+ }
35
+ const array = [];
36
+ for (let i = 0; i < ctx.length; i++) {
37
+ if ( !array.includes(ctx[i]) && !array.some(node => node.contains(ctx[i]))) {
38
+ array.push(ctx[i]);
39
+ }
40
+ }
41
+ if (sort) {
42
+ array.sort((a, b) => {
43
+ return (a.compareDocumentPosition(b) & win.Node.DOCUMENT_POSITION_FOLLOWING) > 0 ? -1 : 1;
44
+ });
45
+ }
46
+ return array;
47
+ }
48
+ getIframeContents(iframe, successFn, errorFn) {
49
+ try {
50
+ const doc = iframe.contentWindow.document;
51
+ if (doc) {
52
+ this.map.set(iframe, 'ready');
53
+ successFn({ iframe: iframe, context: doc });
54
+ }
55
+ } catch (e) {
56
+ errorFn({ iframe: iframe, error: e });
57
+ }
58
+ }
59
+ observeIframeLoad(ifr, successFn, errorFn) {
60
+ if (this.map.has(ifr)) return;
61
+ let id = null;
62
+ const listener = () => {
63
+ clearTimeout(id);
64
+ ifr.removeEventListener('load', listener);
65
+ this.getIframeContents(ifr, successFn, errorFn);
66
+ };
67
+ ifr.addEventListener('load', listener);
68
+ this.map.set(ifr, true);
69
+ id = setTimeout(listener, this.opt.iframesTimeout);
70
+ }
71
+ onIframeReady(ifr, successFn, errorFn) {
72
+ const bl = 'about:blank',
73
+ src = ifr.getAttribute('src'),
74
+ win = ifr.contentWindow;
75
+ try {
76
+ if (win.document.readyState !== 'complete' || src && src.trim() !== bl && win.location.href === bl) {
77
+ this.observeIframeLoad(ifr, successFn, errorFn);
78
+ } else {
79
+ this.getIframeContents(ifr, successFn, errorFn);
80
+ }
81
+ } catch (e) {
82
+ errorFn(e);
83
+ }
84
+ }
85
+ waitForIframes(ctx, doneCb) {
86
+ const shadow = this.opt.shadowDOM;
87
+ let count = 0,
88
+ iframes = 0,
89
+ array,
90
+ node;
91
+ const collect = context => {
92
+ const iterator = this.createIterator(context, this.opt.window.NodeFilter.SHOW_ELEMENT);
93
+ while ((node = iterator.nextNode())) {
94
+ if (this.isIframe(node) && !this.map.has(node)) {
95
+ array.push(node);
96
+ iframes++;
97
+ }
98
+ if (shadow && node.shadowRoot && node.shadowRoot.mode === 'open') {
99
+ collect(node.shadowRoot);
100
+ }
101
+ }
102
+ };
103
+ const loop = (obj) => {
104
+ array = [];
105
+ if ( !obj.iframe || obj.context.location.href !== 'about:blank') {
106
+ collect(obj.context);
107
+ if ( !obj.iframe && !array.length) {
108
+ doneCb();
109
+ return;
110
+ }
111
+ }
112
+ if (array.length) {
113
+ array.forEach(iframe => {
114
+ this.onIframeReady(iframe, obj => {
115
+ count++;
116
+ loop(obj);
117
+ }, obj => {
118
+ if (this.opt.debug) {
119
+ console.log(obj.error || obj);
120
+ }
121
+ if (++count === iframes) doneCb();
122
+ });
123
+ });
124
+ } else if (count === iframes) {
125
+ doneCb();
126
+ }
127
+ };
128
+ loop({ context: ctx });
129
+ }
130
+ createIterator(ctx, whatToShow) {
131
+ const win = this.opt.window;
132
+ return win.document.createNodeIterator(ctx, whatToShow, () => win.NodeFilter.FILTER_ACCEPT, false);
133
+ }
134
+ addRemoveStyle(root, style, add) {
135
+ if (add && !style) return;
136
+ let elem = root.querySelector('style[data-markjs]');
137
+ if (add) {
138
+ if ( !elem) {
139
+ elem = this.opt.window.document.createElement('style');
140
+ elem.setAttribute('data-markjs', 'true');
141
+ root.appendChild(elem);
142
+ }
143
+ elem.textContent = style;
144
+ } else if (elem) {
145
+ root.removeChild(elem);
146
+ }
147
+ }
148
+ isIframe(node) {
149
+ return node.tagName === 'IFRAME' && !DOMIterator.matches(node, this.opt.exclude);
150
+ }
151
+ iterateThroughNodes(ctx, whatToShow, filterCb, eachCb, doneCb) {
152
+ const filter = this.opt.window.NodeFilter,
153
+ shadow = this.opt.shadowDOM,
154
+ iframe = this.opt.iframes;
155
+ if (iframe || shadow) {
156
+ const showElement = (whatToShow & filter.SHOW_ELEMENT) > 0,
157
+ showText = (whatToShow & filter.SHOW_TEXT) > 0;
158
+ const traverse = node => {
159
+ let iterator = this.createIterator(node, whatToShow | filter.SHOW_ELEMENT),
160
+ root;
161
+ while ((node = iterator.nextNode())) {
162
+ if (node.nodeType === 1) {
163
+ if (showElement && filterCb(node)) {
164
+ eachCb(node);
165
+ }
166
+ if (iframe && this.isIframe(node) && this.map.get(node) === 'ready') {
167
+ const doc = node.contentWindow.document;
168
+ if (doc) {
169
+ if (this.opt.highlight && showText) {
170
+ node.contentWindow.CSS.highlights.set(this.opt.highlightName, this.opt.highlight);
171
+ }
172
+ this.addRemoveStyle(doc.head, iframe.style, showText);
173
+ traverse(doc);
174
+ }
175
+ }
176
+ if (shadow && (root = node.shadowRoot) && root.mode === 'open') {
177
+ this.addRemoveStyle(root, shadow.style, showText);
178
+ traverse(root);
179
+ }
180
+ } else if (showText && node.nodeType === 3 && filterCb(node)) {
181
+ eachCb(node);
182
+ }
183
+ }
184
+ };
185
+ traverse(ctx);
186
+ } else {
187
+ const iterator = this.createIterator(ctx, whatToShow);
188
+ let node;
189
+ while ((node = iterator.nextNode())) {
190
+ if (filterCb(node)) {
191
+ eachCb(node);
192
+ }
193
+ }
194
+ }
195
+ doneCb();
196
+ }
197
+ forEachNode(whatToShow, each, filter, done = () => {}) {
198
+ const contexts = this.getContexts();
199
+ let open = contexts.length;
200
+ if ( !open) done();
201
+ const ready = () => {
202
+ contexts.forEach(ctx => {
203
+ this.iterateThroughNodes(ctx, whatToShow, filter, each, () => {
204
+ if (--open <= 0) done();
205
+ });
206
+ });
207
+ };
208
+ if (this.opt.iframes) {
209
+ let count = open;
210
+ contexts.forEach(ctx => {
211
+ this.waitForIframes(ctx, () => {
212
+ if (--count <= 0) ready();
213
+ });
214
+ });
215
+ } else {
216
+ ready();
217
+ }
218
+ }
219
+ }
220
+
221
+ class RegExpCreator {
222
+ constructor(options) {
223
+ this.opt = Object.assign({}, {
224
+ 'diacritics': true,
225
+ 'synonyms': {},
226
+ 'accuracy': 'partially',
227
+ 'caseSensitive': false,
228
+ 'ignoreJoiners': false,
229
+ 'ignorePunctuation': [],
230
+ 'wildcards': 'disabled'
231
+ }, options);
232
+ }
233
+ get chars() {
234
+ if ( !this._chars) {
235
+ this._chars = [];
236
+ ['aàáảãạăằắẳẵặâầấẩẫậäåāą', 'cçćč', 'dđď', 'eèéẻẽẹêềếểễệëěēę',
237
+ 'iìíỉĩịîïī', 'lł', 'nñňń', 'oòóỏõọôồốổỗộơởỡớờợöøōő', 'rř',
238
+ 'sšśșş', 'tťțţ', 'uùúủũụưừứửữựûüůūű', 'yýỳỷỹỵÿ', 'zžżź'].forEach(str => {
239
+ this._chars.push(str, str.toUpperCase());
240
+ });
241
+ }
242
+ return this._chars;
243
+ }
244
+ create(terms) {
245
+ const flags = `g${this.opt.caseSensitive ? '' : 'i'}`;
246
+ terms = terms.map(str => {
247
+ return '(' + this.createPattern(str, flags) + ')';
248
+ });
249
+ const obj = this.createAccuracy(terms.join('|'));
250
+ return new RegExp(`${obj.lookbehind}(${obj.pattern})${obj.lookahead}`, flags);
251
+ }
252
+ createPattern(str, flags) {
253
+ str = this.checkWildcardsEscape(str);
254
+ str = this.createSynonyms(str, flags);
255
+ const joiners = this.getJoinersPunctuation();
256
+ if (joiners) {
257
+ str = this.setupIgnoreJoiners(str);
258
+ }
259
+ if (this.opt.diacritics) {
260
+ str = this.createDiacritics(str);
261
+ }
262
+ str = str.replace(/\s+/g, '[\\s]+');
263
+ if (joiners) {
264
+ str = this.createJoiners(str, joiners);
265
+ }
266
+ if (this.opt.wildcards !== 'disabled') {
267
+ str = this.createWildcards(str);
268
+ }
269
+ return str;
270
+ }
271
+ escape(str) {
272
+ return str.replace(/[[\]/{}()*+?.\\^$|]/g, '\\$&');
273
+ }
274
+ preprocess(val) {
275
+ if (val && val.length) {
276
+ return this.distinct(typeof val === 'string' ? val.split('') : val).join('').replace(/[-^\]\\]/g, '\\$&');
277
+ }
278
+ return '';
279
+ }
280
+ distinct(array) {
281
+ const result = [];
282
+ array.forEach(item => {
283
+ if (item.trim() && !result.includes(item)) {
284
+ result.push(item);
285
+ }
286
+ });
287
+ return result;
288
+ }
289
+ createSynonyms(str, flags) {
290
+ const syn = this.opt.synonyms;
291
+ for (const key in syn) {
292
+ if (syn.hasOwnProperty(key)) {
293
+ let array = Array.isArray(syn[key]) ? syn[key] : [syn[key]];
294
+ array.unshift(key);
295
+ array = this.distinct(array);
296
+ if (array.length > 1) {
297
+ array.sort((a, b) => b.length - a.length);
298
+ array = array.map(term => this.checkWildcardsEscape(term));
299
+ const pattern = array.map(term => this.escape(term)).join('|');
300
+ str = str.replace(new RegExp(pattern, flags), `(?:${array.join('|')})`);
301
+ }
302
+ }
303
+ }
304
+ return str;
305
+ }
306
+ checkWildcardsEscape(str) {
307
+ if (this.opt.wildcards !== 'disabled') {
308
+ str = str.replace(/(\\.)+|[?*]/g, (m, gr) => gr ? m : m === '?' ? '\x01' : '\x02')
309
+ .replace(/\\(?=[?*\x01\x02])/g, '');
310
+ }
311
+ return this.escape(str);
312
+ }
313
+ createWildcards(str) {
314
+ const spaces = this.opt.wildcards === 'withSpaces',
315
+ boundary = this.opt.blockElementsBoundary,
316
+ anyChar = `[^${spaces && boundary ? '\x01' : ''}]*?`;
317
+ return str
318
+ .replace(/\x01/g, spaces ? '[^]?' : '\\S?')
319
+ .replace(/\x02/g, spaces ? anyChar : '\\S*');
320
+ }
321
+ setupIgnoreJoiners(str) {
322
+ const reg = /((?:\\\\)+|\x02|\(\?:|\|)|\\?(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|.)(?=([|)\x02]|$)|.)/g;
323
+ return str.replace(reg, (m, gr1, gr2) => {
324
+ return gr1 || typeof gr2 !== 'undefined' ? m : m + '\x00';
325
+ });
326
+ }
327
+ createJoiners(str, joiners) {
328
+ return str.split(/\x00+/).join(`[${joiners}]*`);
329
+ }
330
+ getJoinersPunctuation() {
331
+ let punct = this.preprocess(this.opt.ignorePunctuation),
332
+ str = punct ? punct : '';
333
+ if (this.opt.ignoreJoiners) {
334
+ str += '\\u00ad\\u200b\\u200c\\u200d';
335
+ }
336
+ return str;
337
+ }
338
+ createDiacritics(str) {
339
+ const array = this.chars;
340
+ return str.split('').map(ch => {
341
+ for (let i = 0; i < array.length; i += 2) {
342
+ const lowerCase = array[i].includes(ch);
343
+ if (this.opt.caseSensitive) {
344
+ if (lowerCase) {
345
+ return '[' + array[i] + ']';
346
+ }
347
+ if (array[i+1].includes(ch)) {
348
+ return '[' + array[i+1] + ']';
349
+ }
350
+ } else if (lowerCase || array[i+1].includes(ch)) {
351
+ return '[' + array[i] + array[i+1] + ']';
352
+ }
353
+ }
354
+ return ch;
355
+ }).join('');
356
+ }
357
+ createAccuracy(str) {
358
+ const chars = '!-/:-@[-`{-~¡¿';
359
+ let accuracy = this.opt.accuracy,
360
+ lookbehind = '()',
361
+ pattern = str,
362
+ lookahead = '',
363
+ limiters;
364
+ if (accuracy !== 'partially') {
365
+ if (typeof accuracy !== 'string') {
366
+ limiters = this.preprocess(accuracy.limiters);
367
+ accuracy = accuracy.value;
368
+ }
369
+ if (accuracy === 'exactly') {
370
+ const charSet = limiters ? '[\\s' + limiters + ']' : '\\s';
371
+ lookbehind = `(^|${charSet})`;
372
+ lookahead = `(?=$|${charSet})`;
373
+ } else {
374
+ const chs = limiters || chars,
375
+ charSet = `[^\\s${chs}]*`;
376
+ pattern = `(?:${str})`;
377
+ if (accuracy === 'complementary') {
378
+ pattern = charSet + pattern + charSet;
379
+ } else if (accuracy === 'startsWith') {
380
+ lookbehind = `(^|[\\s${chs}])`;
381
+ pattern = pattern.split(/\[\\s\]\+/).join(charSet + '[\\s]+') + charSet;
382
+ }
383
+ }
384
+ }
385
+ return { lookbehind, pattern, lookahead };
386
+ }
387
+ }
388
+
389
+ class Mark$1 {
390
+ constructor(ctx) {
391
+ this.ctx = ctx;
392
+ this.nodeNames = ['script', 'style', 'title', 'head', 'html'];
393
+ }
394
+ set opt(val) {
395
+ if ( !(val && val.window && val.window.document) && typeof window === 'undefined') {
396
+ throw new Error('Mark.js: please provide a window object as an option.');
397
+ }
398
+ const win = val && val.window || window,
399
+ highlight = val && val.highlight && val.highlight instanceof Highlight;
400
+ this._opt = Object.assign({}, {
401
+ 'window': win,
402
+ 'element': '',
403
+ 'className': '',
404
+ 'exclude': [],
405
+ 'iframes': false,
406
+ 'iframesTimeout': 5000,
407
+ 'separateWordSearch': true,
408
+ 'staticRanges': true,
409
+ 'rangeAcrossElements': true,
410
+ 'acrossElements': false,
411
+ 'ignoreGroups': 0,
412
+ 'each': () => {},
413
+ 'noMatch': () => {},
414
+ 'filter': () => true,
415
+ 'done': () => {},
416
+ 'debug': false,
417
+ 'log': win.console
418
+ }, val);
419
+ if ( !this._opt.element) {
420
+ this._opt.element = 'mark';
421
+ }
422
+ this.filter = win.NodeFilter;
423
+ this.empty = win.document.createTextNode('');
424
+ if ( !this._opt.highlightName) {
425
+ this._opt.highlightName = 'advanced-markjs';
426
+ }
427
+ if (highlight) {
428
+ this.rangeArray = [];
429
+ } else {
430
+ this._opt.highlight = null;
431
+ }
432
+ }
433
+ get opt() {
434
+ return this._opt;
435
+ }
436
+ get iterator() {
437
+ return new DOMIterator(this.ctx, this.opt);
438
+ }
439
+ log(msg, level = 'debug') {
440
+ if (this.opt.debug) {
441
+ const log = this.opt.log;
442
+ if (typeof log === 'object' && typeof log[level] === 'function') {
443
+ log[level](`mark.js: ${msg}`);
444
+ }
445
+ }
446
+ }
447
+ report(array) {
448
+ array.forEach(item => {
449
+ this.log(`${item.text} ${JSON.stringify(item.obj)}`, item.level || 'debug');
450
+ if ( !item.skip) {
451
+ this.opt.noMatch(item.obj);
452
+ }
453
+ });
454
+ }
455
+ getSeachTerms(sv) {
456
+ const search = typeof sv === 'string' ? [sv] : sv,
457
+ separate = this.opt.separateWordSearch,
458
+ array = [],
459
+ termStats = {},
460
+ split = str => {
461
+ str.split(/ +/).forEach(word => add(word));
462
+ },
463
+ add = str => {
464
+ if (str.trim() && !array.includes(str)) {
465
+ array.push(str);
466
+ termStats[str] = 0;
467
+ }
468
+ };
469
+ search.forEach(str => {
470
+ if (separate) {
471
+ if (separate === 'preserveTerms') {
472
+ str.split(/"("*[^"]+"*)"/).forEach((term, i) => {
473
+ if (i % 2 > 0) add(term);
474
+ else split(term);
475
+ });
476
+ } else {
477
+ split(str);
478
+ }
479
+ } else {
480
+ add(str);
481
+ }
482
+ });
483
+ array.sort((a, b) => b.length - a.length);
484
+ return { terms: array, termStats };
485
+ }
486
+ isNumeric(value) {
487
+ return Number(parseFloat(value)) == value;
488
+ }
489
+ checkRanges(array, logs, min, max) {
490
+ const level = 'error';
491
+ const ranges = array.filter(range => {
492
+ if (this.isNumeric(range.start) && this.isNumeric(range.length)) {
493
+ range.start = parseInt(range.start);
494
+ range.length = parseInt(range.length);
495
+ if (range.start >= min && range.start < max && range.length > 0) {
496
+ return true;
497
+ }
498
+ }
499
+ logs.push({ text: 'Invalid range: ', obj: range, level });
500
+ return false;
501
+ }).sort((a, b) => a.start - b.start);
502
+ if (this.opt.wrapAllRanges) {
503
+ return ranges;
504
+ }
505
+ let lastIndex = 0, index;
506
+ return ranges.filter(range => {
507
+ index = range.start + range.length;
508
+ if (range.start >= lastIndex) {
509
+ lastIndex = index;
510
+ return true;
511
+ }
512
+ logs.push({ text: (index < lastIndex ? 'Nest' : 'Overlapp') + 'ing range: ', obj: range, level });
513
+ return false;
514
+ });
515
+ }
516
+ setType(tags, boundary) {
517
+ const custom = Array.isArray(boundary.tagNames) && boundary.tagNames.length;
518
+ if (custom) {
519
+ boundary.tagNames.forEach(name => tags[name.toLowerCase()] = 2);
520
+ }
521
+ if ( !custom || boundary.extend) {
522
+ for (const key in tags) {
523
+ tags[key] = 2;
524
+ }
525
+ }
526
+ tags['br'] = 3;
527
+ }
528
+ getTextNodesAcross(cb) {
529
+ const tags = { div: 1, p: 1, li: 1, td: 1, tr: 1, th: 1, ul: 1,
530
+ ol: 1, dd: 1, dl: 1, dt: 1, h1: 1, h2: 1, h3: 1, h4: 1,
531
+ h5: 1, h6: 1, hr: 1, blockquote: 1, figcaption: 1, figure: 1,
532
+ pre: 1, table: 1, thead: 1, tbody: 1, tfoot: 1, input: 1,
533
+ img: 1, nav: 1, details: 1, label: 1, form: 1, select: 1, menu: 1,
534
+ br: 3, menuitem: 1,
535
+ main: 1, section: 1, article: 1, aside: 1, picture: 1, output: 1,
536
+ button: 1, header: 1, footer: 1, address: 1, area: 1, canvas: 1,
537
+ map: 1, fieldset: 1, textarea: 1, track: 1, video: 1, audio: 1,
538
+ body: 1, iframe: 1, meter: 1, object: 1, svg: 1 };
539
+ const nodes = [],
540
+ boundary = this.opt.blockElementsBoundary,
541
+ priorityType = boundary ? 2 : 1;
542
+ let ch = '\x01', tempType, type, prevNode;
543
+ if (boundary) {
544
+ this.setType(tags, boundary);
545
+ if (boundary.char) {
546
+ ch = boundary.char.charAt(0);
547
+ }
548
+ }
549
+ const obj = {
550
+ text: '', regex: /\s/, tags: tags,
551
+ boundary: boundary, str: '', ch: ch
552
+ };
553
+ this.iterator.forEachNode(this.filter.SHOW_ELEMENT | this.filter.SHOW_TEXT, node => {
554
+ if (prevNode) {
555
+ nodes.push(this.getNodeInfo(prevNode, node, type, obj));
556
+ }
557
+ type = null;
558
+ prevNode = node;
559
+ }, node => {
560
+ if (node.nodeType === 1) {
561
+ tempType = tags[node.nodeName.toLowerCase()];
562
+ if (tempType === 3) {
563
+ obj.str += '\n';
564
+ }
565
+ if ( !type || tempType === priorityType) {
566
+ type = tempType;
567
+ }
568
+ return false;
569
+ }
570
+ return !this.excluded(node.parentNode);
571
+ }, () => {
572
+ if (prevNode) {
573
+ nodes.push(this.getNodeInfo(prevNode, null, type, obj));
574
+ }
575
+ cb({
576
+ text: obj.text,
577
+ nodes: nodes,
578
+ lastIndex: 0
579
+ });
580
+ });
581
+ }
582
+ getNodeInfo(prevNode, node, type, obj) {
583
+ const start = obj.text.length,
584
+ ch = obj.ch;
585
+ let offset = 0,
586
+ str = obj.str,
587
+ text = prevNode.textContent;
588
+ if (node) {
589
+ const startBySpace = obj.regex.test(node.textContent[0]),
590
+ both = startBySpace && obj.regex.test(text[text.length - 1]);
591
+ if (obj.boundary || !both) {
592
+ let separate = type;
593
+ if (!type) {
594
+ let parent = prevNode.parentNode;
595
+ while (parent) {
596
+ type = obj.tags[parent.nodeName.toLowerCase()];
597
+ if (type) {
598
+ separate = !(parent === node.parentNode || parent.contains(node));
599
+ break;
600
+ }
601
+ parent = parent.parentNode;
602
+ }
603
+ }
604
+ if (separate) {
605
+ if ( !both) {
606
+ str += type === 1 ? ' ' : type === 2 ? ' ' + ch + ' ' : '';
607
+ } else if (type === 2) {
608
+ str += both ? ch : startBySpace ? ' ' + ch : ch + ' ';
609
+ }
610
+ }
611
+ }
612
+ }
613
+ if (str) {
614
+ text += str;
615
+ offset = str.length;
616
+ obj.str = '';
617
+ }
618
+ obj.text += text;
619
+ return this.createInfo(prevNode, start, obj.text.length - offset, offset);
620
+ }
621
+ getRangesTextNodes(cb, lines) {
622
+ const nodes = [],
623
+ regex = /\n/g,
624
+ newLines = [0],
625
+ show = this.filter.SHOW_TEXT | (lines ? this.filter.SHOW_ELEMENT : 0);
626
+ let text = '',
627
+ len = 0,
628
+ rm;
629
+ this.iterator.forEachNode(show, node => {
630
+ if (lines) {
631
+ while ((rm = regex.exec(node.textContent)) !== null) {
632
+ newLines.push(len + rm.index);
633
+ }
634
+ }
635
+ text += node.textContent;
636
+ nodes.push({
637
+ start: len,
638
+ end: (len = text.length),
639
+ offset: 0,
640
+ node: node
641
+ });
642
+ }, node => {
643
+ if (lines && node.nodeType === 1) {
644
+ if (node.tagName.toLowerCase() === 'br') {
645
+ newLines.push(len);
646
+ }
647
+ return false;
648
+ }
649
+ return !this.excluded(node.parentNode);
650
+ }, () => {
651
+ const dict = { text, nodes, lastIndex: 0 };
652
+ if (lines) {
653
+ newLines.push(len);
654
+ dict.newLines = newLines;
655
+ }
656
+ cb(dict);
657
+ });
658
+ }
659
+ getTextNodes(cb) {
660
+ const nodes = [];
661
+ let start = 0;
662
+ this.iterator.forEachNode(this.filter.SHOW_TEXT, node => {
663
+ nodes.push({
664
+ node,
665
+ start
666
+ });
667
+ start += node.textContent.length;
668
+ }, node => {
669
+ return !this.excluded(node.parentNode);
670
+ }, () => {
671
+ cb({ nodes, lastIndex: 0 });
672
+ });
673
+ }
674
+ excluded(elem) {
675
+ return this.nodeNames.includes(elem.nodeName.toLowerCase()) || DOMIterator.matches(elem, this.opt.exclude);
676
+ }
677
+ wrapRangeInsert(dict, n, s, e, start, index) {
678
+ const ended = e === n.node.textContent.length,
679
+ end = n.end;
680
+ let type = 1,
681
+ splitIndex = e,
682
+ node = n.node;
683
+ if (s !== 0) {
684
+ node = node.splitText(s);
685
+ splitIndex = e - s;
686
+ type = ended ? 2 : 3;
687
+ } else if (ended) {
688
+ type = 0;
689
+ }
690
+ const retNode = ended ? this.empty : node.splitText(splitIndex),
691
+ mark = this.createElement(node),
692
+ markChild = mark.childNodes[0],
693
+ nodeInfo = this.createInfo(retNode, type === 0 || type === 2 ? end : n.start + e, end, n.offset);
694
+ if (type === 0) {
695
+ n.node = markChild;
696
+ return { mark, nodeInfo, increment: 0 };
697
+ }
698
+ const info = this.createInfo(markChild, type === 1 ? n.start : start, n.start + e, 0);
699
+ if (type === 1) {
700
+ dict.nodes.splice(index, 1, info, nodeInfo);
701
+ } else {
702
+ if (type === 2) {
703
+ dict.nodes.splice(index + 1, 0, info);
704
+ } else {
705
+ dict.nodes.splice(index + 1, 0, info, nodeInfo);
706
+ }
707
+ n.end = start;
708
+ n.offset = 0;
709
+ }
710
+ return { mark, nodeInfo, increment: type < 3 ? 1 : 2 };
711
+ }
712
+ createInfo(node, start, end, offset) {
713
+ return { node, start, end, offset };
714
+ }
715
+ wrapRange(n, start, end, eachCb) {
716
+ let node = n.node,
717
+ retNode;
718
+ if (this.rangeArray) {
719
+ this.createRange(node, start, node, end, n.start + start, eachCb);
720
+ retNode = node;
721
+ } else {
722
+ let ended = end === node.textContent.length,
723
+ index = end;
724
+ if (start !== 0) {
725
+ node = node.splitText(start);
726
+ index = end - start;
727
+ }
728
+ retNode = ended ? this.empty : node.splitText(index);
729
+ eachCb(this.createElement(node));
730
+ }
731
+ return retNode;
732
+ }
733
+ createRange(startNode, startOffset, endNode, endOffset, absoluteOffset, eachCb) {
734
+ let range;
735
+ if (this.opt.staticRanges) {
736
+ range = new StaticRange({ startContainer: startNode, startOffset, endContainer: endNode, endOffset });
737
+ } else {
738
+ range = new Range();
739
+ range.setStart(startNode, startOffset);
740
+ range.setEnd(endNode, endOffset);
741
+ }
742
+ range.absoluteOffset = absoluteOffset;
743
+ eachCb(range, true);
744
+ if (range) this.rangeArray.push(range);
745
+ }
746
+ createElement(node) {
747
+ let markNode = this.opt.window.document.createElement(this.opt.element);
748
+ markNode.setAttribute('data-markjs', 'true');
749
+ if (this.opt.className) {
750
+ markNode.setAttribute('class', this.opt.className);
751
+ }
752
+ markNode.textContent = node.textContent;
753
+ node.parentNode.replaceChild(markNode, node);
754
+ return markNode;
755
+ }
756
+ wrapRangeAcross(dict, start, end, filterCb, eachCb) {
757
+ let i = dict.lastIndex,
758
+ rangeStart = true,
759
+ startInfo,
760
+ filterNodes = [],
761
+ e;
762
+ const wrapAllRanges = this.opt.wrapAllRanges,
763
+ highlightAPI = !!this.opt.highlight,
764
+ singleRange = highlightAPI && this.opt.rangeAcrossElements;
765
+ if (wrapAllRanges) {
766
+ while (i > 0 && dict.nodes[i].start > start) {
767
+ i--;
768
+ }
769
+ }
770
+ for (i; i < dict.nodes.length; i++) {
771
+ if (i + 1 === dict.nodes.length || dict.nodes[i+1].start > start) {
772
+ let n = dict.nodes[i];
773
+ if (singleRange) {
774
+ filterNodes.push(n.node);
775
+ } else if ( !filterCb(n.node)) {
776
+ break;
777
+ }
778
+ const s = start - n.start;
779
+ e = (end > n.end ? n.end : end) - n.start;
780
+ if (s >= 0 && e > s) {
781
+ if (singleRange) {
782
+ if (rangeStart) {
783
+ startInfo = [n.node, s, n.start + s];
784
+ }
785
+ } else if ( !highlightAPI && wrapAllRanges) {
786
+ const obj = this.wrapRangeInsert(dict, n, s, e, start, i);
787
+ n = obj.nodeInfo;
788
+ eachCb(obj.mark, rangeStart);
789
+ } else {
790
+ n.node = this.wrapRange(n, s, e, elemOrRange => {
791
+ eachCb(elemOrRange, rangeStart);
792
+ });
793
+ if ( !highlightAPI) n.start += e;
794
+ }
795
+ rangeStart = false;
796
+ }
797
+ if (end > n.end) {
798
+ start = n.end + n.offset;
799
+ } else {
800
+ if (startInfo && filterCb(filterNodes)) {
801
+ this.createRange(startInfo[0], startInfo[1], n.node, e, startInfo[2], eachCb);
802
+ }
803
+ break;
804
+ }
805
+ }
806
+ }
807
+ dict.lastIndex = i;
808
+ }
809
+ wrapGroups(n, match, regex, filterCb, eachCb) {
810
+ let lastIndex = 0,
811
+ offset = 0,
812
+ i = 0,
813
+ highlightAPI = this.opt.highlight,
814
+ isWrapped = false,
815
+ group, start, end = 0;
816
+ while (++i < match.length) {
817
+ group = match[i];
818
+ if (group) {
819
+ start = match.indices[i][0];
820
+ if (start >= lastIndex) {
821
+ end = match.indices[i][1];
822
+ if (filterCb(n.node, group, i)) {
823
+ n.node = this.wrapRange(n, start - offset, end - offset, elemOrRange => {
824
+ eachCb(elemOrRange);
825
+ });
826
+ if (end > lastIndex) {
827
+ lastIndex = end;
828
+ }
829
+ if ( !highlightAPI) offset = end;
830
+ isWrapped = true;
831
+ }
832
+ }
833
+ }
834
+ }
835
+ if (isWrapped) {
836
+ if ( !highlightAPI) regex.lastIndex = 0;
837
+ } else if (match[0].length === 0) {
838
+ this.setLastIndex(regex, end);
839
+ }
840
+ }
841
+ wrapGroupsAcross(dict, match, regex, filterCb, eachCb) {
842
+ let lastIndex = 0,
843
+ i = 0,
844
+ end = 0,
845
+ start,
846
+ group,
847
+ isWrapped;
848
+ while (++i < match.length) {
849
+ group = match[i];
850
+ if (group) {
851
+ start = match.indices[i][0];
852
+ if (this.opt.wrapAllRanges || start >= lastIndex) {
853
+ end = match.indices[i][1];
854
+ isWrapped = false;
855
+ this.wrapRangeAcross(dict, start, end, nodeOrArray => {
856
+ return filterCb(nodeOrArray, group, i);
857
+ }, (elemOrRange, groupStart) => {
858
+ isWrapped = true;
859
+ eachCb(elemOrRange, groupStart);
860
+ });
861
+ if (isWrapped && end > lastIndex) {
862
+ lastIndex = end;
863
+ }
864
+ }
865
+ }
866
+ }
867
+ if (match[0].length === 0) {
868
+ this.setLastIndex(regex, end);
869
+ }
870
+ }
871
+ setLastIndex(regex, end) {
872
+ const index = regex.lastIndex;
873
+ regex.lastIndex = end > index ? end : end > 0 ? index + 1 : Infinity;
874
+ }
875
+ processGroups(regex, unused, info, filterCb, eachCb, endCb) {
876
+ let count = info.count, match, filterStart, eachStart;
877
+ this.getTextNodes(dict => {
878
+ dict.nodes.every(n => {
879
+ while ((match = regex.exec(n.node.textContent)) !== null) {
880
+ info.match = match;
881
+ filterStart = eachStart = true;
882
+ this.wrapGroups(n, match, regex, (node, group, grIndex) => {
883
+ info.matchStart = filterStart;
884
+ info.groupIndex = grIndex;
885
+ filterStart = false;
886
+ return filterCb(node, group, info);
887
+ }, (elemOrRange) => {
888
+ if (eachStart) count++;
889
+ info.count = count;
890
+ info.matchStart = eachStart;
891
+ eachStart = false;
892
+ eachCb(elemOrRange, info);
893
+ });
894
+ if (info.abort) break;
895
+ }
896
+ return !info.abort;
897
+ });
898
+ endCb(count);
899
+ });
900
+ }
901
+ processGroupsAcross(regex, unused, info, filterCb, eachCb, endCb) {
902
+ let count = info.count, match, filterStart, eachStart;
903
+ this.getTextNodesAcross(dict => {
904
+ while ((match = regex.exec(dict.text)) !== null) {
905
+ info.match = match;
906
+ filterStart = eachStart = true;
907
+ this.wrapGroupsAcross(dict, match, regex, (nodeOrArray, group, grIndex) => {
908
+ info.groupStart = undefined;
909
+ info.matchStart = filterStart;
910
+ info.groupIndex = grIndex;
911
+ filterStart = false;
912
+ return filterCb(nodeOrArray, group, info);
913
+ }, (elemOrRange, groupStart) => {
914
+ if (eachStart) count++;
915
+ info.count = count;
916
+ info.matchStart = eachStart;
917
+ info.groupStart = groupStart;
918
+ eachCb(elemOrRange, info);
919
+ eachStart = false;
920
+ });
921
+ if (info.abort) break;
922
+ }
923
+ endCb(count);
924
+ });
925
+ }
926
+ processMatches(regex, ignoreGroups, info, filterCb, eachCb, endCb) {
927
+ const index = ignoreGroups === 0 ? 0 : ignoreGroups + 1;
928
+ let count = info.count, match, str;
929
+ this.getTextNodes(dict => {
930
+ dict.nodes.every(n => {
931
+ while ((match = regex.exec(n.node.textContent)) !== null) {
932
+ if ((str = match[index]) === '') {
933
+ regex.lastIndex++;
934
+ continue;
935
+ }
936
+ info.match = match;
937
+ if ( !filterCb(n.node, str, info)) {
938
+ continue;
939
+ }
940
+ let i = 0, start = match.index;
941
+ while (++i < index) {
942
+ if (match[i]) {
943
+ start += match[i].length;
944
+ }
945
+ }
946
+ n.node = this.wrapRange(n, start, start + str.length, elemOrRange => {
947
+ info.count = ++count;
948
+ eachCb(elemOrRange, info);
949
+ });
950
+ if ( !this.opt.highlight) regex.lastIndex = 0;
951
+ if (info.abort) break;
952
+ }
953
+ return !info.abort;
954
+ });
955
+ endCb(count);
956
+ });
957
+ }
958
+ processMatchesAcross(regex, ignoreGroups, info, filterCb, eachCb, endCb) {
959
+ const index = ignoreGroups === 0 ? 0 : ignoreGroups + 1;
960
+ let count = info.count, match, str, matchStart;
961
+ this.getTextNodesAcross(dict => {
962
+ while ((match = regex.exec(dict.text)) !== null) {
963
+ if ((str = match[index]) === '') {
964
+ regex.lastIndex++;
965
+ continue;
966
+ }
967
+ info.match = match;
968
+ matchStart = true;
969
+ let i = 0, start = match.index;
970
+ while (++i < index) {
971
+ if (match[i]) {
972
+ start += match[i].length;
973
+ }
974
+ }
975
+ this.wrapRangeAcross(dict, start, start + str.length, nodeOrArray => {
976
+ info.matchStart = matchStart;
977
+ matchStart = false;
978
+ return filterCb(nodeOrArray, str, info);
979
+ }, (elemOrRange, mStart) => {
980
+ if (mStart) count++;
981
+ info.count = count;
982
+ info.matchStart = mStart;
983
+ eachCb(elemOrRange, info);
984
+ });
985
+ if (info.abort) break;
986
+ }
987
+ endCb(count);
988
+ });
989
+ }
990
+ processRanges(ranges, filterCb, eachCb, endCb) {
991
+ const lines = this.opt.markLines,
992
+ logs = [],
993
+ skipped = [],
994
+ level = 'warn';
995
+ let count = 0;
996
+ this.getRangesTextNodes(dict => {
997
+ const max = lines ? dict.newLines.length : dict.text.length,
998
+ array = this.checkRanges(ranges, logs, lines ? 1 : 0, max);
999
+ array.forEach((range, index) => {
1000
+ let start = range.start,
1001
+ end = start + range.length;
1002
+ if (end > max) {
1003
+ logs.push({ text: `Range was limited to: ${max}`, obj: range, skip: true, level });
1004
+ end = max;
1005
+ }
1006
+ if (lines) {
1007
+ start = dict.newLines[start-1];
1008
+ if (dict.text[start] === '\n') {
1009
+ start++;
1010
+ }
1011
+ end = dict.newLines[end-1];
1012
+ }
1013
+ const substr = dict.text.slice(start, end);
1014
+ if (substr.trim()) {
1015
+ this.wrapRangeAcross(dict, start, end, nodeOrArray => {
1016
+ return filterCb(nodeOrArray, range, substr, index);
1017
+ }, (elemOrRange, rangeStart) => {
1018
+ if (rangeStart) {
1019
+ count++;
1020
+ }
1021
+ eachCb(elemOrRange, range, {
1022
+ matchStart: rangeStart,
1023
+ count: count
1024
+ });
1025
+ });
1026
+ } else {
1027
+ logs.push({ text: 'Skipping whitespace only range: ', obj: range, level });
1028
+ skipped.push(range);
1029
+ }
1030
+ });
1031
+ this.log(`Valid ranges: ${JSON.stringify(array.filter(range => !skipped.includes(range)))}`);
1032
+ endCb(count, logs);
1033
+ }, lines);
1034
+ }
1035
+ unwrapMatches(node) {
1036
+ const parent = node.parentNode,
1037
+ first = node.firstChild;
1038
+ if (node.childNodes.length === 1) {
1039
+ if (first.nodeType === 3) {
1040
+ const previous = node.previousSibling,
1041
+ next = node.nextSibling;
1042
+ if (previous && previous.nodeType === 3) {
1043
+ if (next && next.nodeType === 3) {
1044
+ previous.nodeValue += first.nodeValue + next.nodeValue;
1045
+ parent.removeChild(next);
1046
+ } else {
1047
+ previous.nodeValue += first.nodeValue;
1048
+ }
1049
+ } else if (next && next.nodeType === 3) {
1050
+ next.nodeValue = first.nodeValue + next.nodeValue;
1051
+ } else {
1052
+ parent.replaceChild(node.firstChild, node);
1053
+ return;
1054
+ }
1055
+ parent.removeChild(node);
1056
+ } else {
1057
+ parent.replaceChild(node.firstChild, node);
1058
+ }
1059
+ } else {
1060
+ if ( !first) {
1061
+ parent.removeChild(node);
1062
+ } else {
1063
+ let docFrag = this.opt.window.document.createDocumentFragment();
1064
+ while (node.firstChild) {
1065
+ docFrag.appendChild(node.removeChild(node.firstChild));
1066
+ }
1067
+ parent.replaceChild(docFrag, node);
1068
+ }
1069
+ parent.normalize();
1070
+ }
1071
+ }
1072
+ markRegExp(regexp, opt) {
1073
+ this.opt = opt;
1074
+ let totalMarks = 0,
1075
+ matchesSoFar = 0,
1076
+ across = this.opt.acrossElements,
1077
+ fn = 'processMatches';
1078
+ if (this.opt.separateGroups) {
1079
+ if ( !regexp.hasIndices) {
1080
+ throw new Error('Mark.js: RegExp must have a `d` flag');
1081
+ }
1082
+ fn = across ? 'processGroupsAcross' : 'processGroups';
1083
+ } else if (across) {
1084
+ fn = 'processMatchesAcross';
1085
+ }
1086
+ const info = { count: 0, abort: false };
1087
+ if ( !regexp.global && !regexp.sticky) {
1088
+ let splits = regexp.toString().split('/');
1089
+ regexp = new RegExp(regexp.source, 'g' + splits[splits.length-1]);
1090
+ this.log('RegExp is recompiled - it must have a `g` flag', 'warn');
1091
+ }
1092
+ this.log(`RegExp "${regexp}"`);
1093
+ this[fn](regexp, this.opt.ignoreGroups, info, (nodeOrArray, match, filterInfo) => {
1094
+ return this.opt.filter(nodeOrArray, match, matchesSoFar, filterInfo);
1095
+ }, (elemOrRange, eachInfo) => {
1096
+ matchesSoFar = eachInfo.count;
1097
+ totalMarks++;
1098
+ this.opt.each(elemOrRange, eachInfo);
1099
+ }, (totalMatches) => {
1100
+ if (totalMatches === 0) {
1101
+ this.opt.noMatch(regexp);
1102
+ }
1103
+ this.registerHighlight();
1104
+ this.opt.done(totalMarks, totalMatches);
1105
+ });
1106
+ }
1107
+ mark(sv, opt) {
1108
+ this.opt = opt;
1109
+ const { terms, termStats } = this.getSeachTerms(sv);
1110
+ if ( !terms.length) {
1111
+ this.opt.done(0, 0, termStats);
1112
+ return;
1113
+ }
1114
+ let index = 0,
1115
+ totalMarks = 0,
1116
+ matchesSoFar = 0,
1117
+ term;
1118
+ const across = this.opt.acrossElements,
1119
+ fn = across ? 'processMatchesAcross' : 'processMatches',
1120
+ array = this.getRegExps(terms),
1121
+ info = { count: 0, abort: false };
1122
+ const loop = ({ regex, regTerms }) => {
1123
+ this.log(`RegExp ${regex}`);
1124
+ this[fn](regex, 1, info, (nodeOrArray, _, filterInfo) => {
1125
+ if ( !across || filterInfo.matchStart) {
1126
+ term = this.getCurrentTerm(filterInfo.match, regTerms);
1127
+ }
1128
+ return this.opt.filter(nodeOrArray, term, matchesSoFar, termStats[term], filterInfo);
1129
+ }, (elemOrRange, eachInfo) => {
1130
+ totalMarks++;
1131
+ matchesSoFar = eachInfo.count;
1132
+ if ( !across || eachInfo.matchStart) {
1133
+ termStats[term] += 1;
1134
+ }
1135
+ this.opt.each(elemOrRange, eachInfo);
1136
+ }, (totalMatches) => {
1137
+ const noMatches = regTerms.filter(term => termStats[term] === 0);
1138
+ if (noMatches.length) {
1139
+ this.opt.noMatch(noMatches);
1140
+ }
1141
+ if ( !info.abort && ++index < array.length) {
1142
+ loop(array[index]);
1143
+ } else {
1144
+ this.registerHighlight();
1145
+ this.opt.done(totalMarks, totalMatches, termStats);
1146
+ }
1147
+ });
1148
+ };
1149
+ loop(array[0]);
1150
+ }
1151
+ getCurrentTerm(match, terms) {
1152
+ let i = match.length;
1153
+ while (--i > 2) {
1154
+ if (match[i]) {
1155
+ return terms[i-3];
1156
+ }
1157
+ }
1158
+ return ' ';
1159
+ }
1160
+ getRegExps(terms) {
1161
+ const creator = new RegExpCreator(this.opt),
1162
+ option = this.opt.combineBy || this.opt.combinePatterns,
1163
+ length = terms.length,
1164
+ array = [];
1165
+ let num = 100,
1166
+ value;
1167
+ if (option === Infinity) {
1168
+ num = length;
1169
+ } else if ( !isNaN(+option) && (value = parseInt(option)) > 0) {
1170
+ num = value;
1171
+ }
1172
+ for (let i = 0; i < length; i += num) {
1173
+ const chunk = terms.slice(i, Math.min(i + num, length));
1174
+ array.push({ regex: creator.create(chunk), regTerms: chunk });
1175
+ }
1176
+ return array;
1177
+ }
1178
+ markRanges(ranges, opt) {
1179
+ this.opt = opt;
1180
+ if (Array.isArray(ranges)) {
1181
+ let totalMarks = 0;
1182
+ this.processRanges(ranges, (nodeOrArray, range, match, index) => {
1183
+ return this.opt.filter(nodeOrArray, range, match, index);
1184
+ }, (elemOrRange, range, rangeInfo) => {
1185
+ totalMarks++;
1186
+ this.opt.each(elemOrRange, range, rangeInfo);
1187
+ }, (totalRanges, logs) => {
1188
+ this.report(logs);
1189
+ this.registerHighlight();
1190
+ this.opt.done(totalMarks, totalRanges);
1191
+ });
1192
+ } else {
1193
+ this.report([{ text: 'markRanges() accept an array of objects: ', obj: ranges, level: 'error' }]);
1194
+ this.opt.done(0, 0);
1195
+ }
1196
+ }
1197
+ unmark(opt) {
1198
+ this.opt = opt;
1199
+ const registry = CSS.highlights,
1200
+ exclude = this.opt.exclude && this.opt.exclude.length;
1201
+ if (registry) {
1202
+ let names = this.opt.highlightName,
1203
+ highlight;
1204
+ if (typeof names === 'string') names = [names];
1205
+ names.forEach((name) => {
1206
+ if ((highlight = registry.get(name)) && highlight.size) {
1207
+ registry.delete(name);
1208
+ if (exclude) {
1209
+ highlight.forEach((range) => {
1210
+ let node = range.startContainer;
1211
+ if (node.nodeType === 3) node = node.parentNode;
1212
+ if ( !this.excluded(node)) highlight.delete(range);
1213
+ });
1214
+ } else {
1215
+ highlight.clear();
1216
+ }
1217
+ if (highlight.size) registry.set(name, highlight);
1218
+ }
1219
+ });
1220
+ }
1221
+ if (this.opt.highlight) {
1222
+ this.opt.done();
1223
+ return;
1224
+ }
1225
+ let selector = this.opt.element + '[data-markjs]';
1226
+ if (this.opt.className) {
1227
+ selector += `.${this.opt.className}`;
1228
+ }
1229
+ this.log(`Removal selector "${selector}"`);
1230
+ this.iterator.forEachNode(this.filter.SHOW_ELEMENT, node => {
1231
+ this.unwrapMatches(node);
1232
+ }, node => {
1233
+ return DOMIterator.matches(node, selector) && !(exclude && this.excluded(node));
1234
+ }, this.opt.done);
1235
+ }
1236
+ registerHighlight() {
1237
+ const highlight = this.opt.highlight;
1238
+ if (highlight) {
1239
+ const name = this.opt.highlightName,
1240
+ registry = CSS.highlights;
1241
+ if (this.rangeArray.length) {
1242
+ registry.delete(name);
1243
+ if (highlight.size) {
1244
+ highlight.forEach(range => {
1245
+ this.rangeArray.push(range);
1246
+ });
1247
+ highlight.clear();
1248
+ }
1249
+ this.rangeArray.sort((a, b) => a.absoluteOffset - b.absoluteOffset);
1250
+ this.rangeArray.forEach(range => {
1251
+ highlight.add(range);
1252
+ });
1253
+ this.rangeArray = [];
1254
+ }
1255
+ if (highlight.size) registry.set(name, highlight);
1256
+ }
1257
+ }
1258
+ }
1259
+
1260
+ function Mark(ctx) {
1261
+ const instance = new Mark$1(ctx);
1262
+ this.mark = (sv, opt) => {
1263
+ instance.mark(sv, opt);
1264
+ return this;
1265
+ };
1266
+ this.markRegExp = (sv, opt) => {
1267
+ instance.markRegExp(sv, opt);
1268
+ return this;
1269
+ };
1270
+ this.markRanges = (sv, opt) => {
1271
+ instance.markRanges(sv, opt);
1272
+ return this;
1273
+ };
1274
+ this.unmark = (opt) => {
1275
+ instance.unmark(opt);
1276
+ return this;
1277
+ };
1278
+ this.getVersion = () => {
1279
+ return '3.0.0';
1280
+ };
1281
+ return this;
1282
+ }
1283
+
1284
+ export { Mark as default };