| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| (function (global, factory) { |
| typeof exports === 'object' && typeof module !== 'undefined' |
| ? (module.exports = factory()) |
| : typeof define === 'function' && define.amd |
| ? define(factory) |
| : (global.Mark = factory()); |
| })(this, function () { |
| 'use strict'; |
|
|
| function _typeof(obj) { |
| if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { |
| _typeof = function (obj) { |
| return typeof obj; |
| }; |
| } else { |
| _typeof = function (obj) { |
| return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype |
| ? 'symbol' |
| : typeof obj; |
| }; |
| } |
|
|
| return _typeof(obj); |
| } |
|
|
| function _classCallCheck(instance, Constructor) { |
| if (!(instance instanceof Constructor)) { |
| throw new TypeError('Cannot call a class as a function'); |
| } |
| } |
|
|
| 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); |
| } |
| } |
|
|
| function _createClass(Constructor, protoProps, staticProps) { |
| if (protoProps) _defineProperties(Constructor.prototype, protoProps); |
| if (staticProps) _defineProperties(Constructor, staticProps); |
| return Constructor; |
| } |
|
|
| function _extends() { |
| _extends = |
| Object.assign || |
| function (target) { |
| for (var i = 1; i < arguments.length; i++) { |
| var source = arguments[i]; |
|
|
| for (var key in source) { |
| if (Object.prototype.hasOwnProperty.call(source, key)) { |
| target[key] = source[key]; |
| } |
| } |
| } |
|
|
| return target; |
| }; |
|
|
| return _extends.apply(this, arguments); |
| } |
|
|
| var DOMIterator = |
| |
| (function () { |
| function DOMIterator(ctx) { |
| var iframes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; |
| var exclude = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; |
| var iframesTimeout = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 5000; |
|
|
| _classCallCheck(this, DOMIterator); |
|
|
| this.ctx = ctx; |
| this.iframes = iframes; |
| this.exclude = exclude; |
| this.iframesTimeout = iframesTimeout; |
| } |
|
|
| _createClass( |
| DOMIterator, |
| [ |
| { |
| key: 'getContexts', |
| value: function getContexts() { |
| var ctx, |
| filteredCtx = []; |
|
|
| if (typeof this.ctx === 'undefined' || !this.ctx) { |
| ctx = []; |
| } else if (NodeList.prototype.isPrototypeOf(this.ctx)) { |
| ctx = Array.prototype.slice.call(this.ctx); |
| } else if (Array.isArray(this.ctx)) { |
| ctx = this.ctx; |
| } else if (typeof this.ctx === 'string') { |
| ctx = Array.prototype.slice.call(document.querySelectorAll(this.ctx)); |
| } else { |
| ctx = [this.ctx]; |
| } |
|
|
| ctx.forEach(function (ctx) { |
| var isDescendant = |
| filteredCtx.filter(function (contexts) { |
| return contexts.contains(ctx); |
| }).length > 0; |
|
|
| if (filteredCtx.indexOf(ctx) === -1 && !isDescendant) { |
| filteredCtx.push(ctx); |
| } |
| }); |
| return filteredCtx; |
| }, |
| }, |
| { |
| key: 'getIframeContents', |
| value: function getIframeContents(ifr, successFn) { |
| var errorFn = |
| arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; |
| var doc; |
|
|
| try { |
| var ifrWin = ifr.contentWindow; |
| doc = ifrWin.document; |
|
|
| if (!ifrWin || !doc) { |
| throw new Error('iframe inaccessible'); |
| } |
| } catch (e) { |
| errorFn(); |
| } |
|
|
| if (doc) { |
| successFn(doc); |
| } |
| }, |
| }, |
| { |
| key: 'isIframeBlank', |
| value: function isIframeBlank(ifr) { |
| var bl = 'about:blank', |
| src = ifr.getAttribute('src').trim(), |
| href = ifr.contentWindow.location.href; |
| return href === bl && src !== bl && src; |
| }, |
| }, |
| { |
| key: 'observeIframeLoad', |
| value: function observeIframeLoad(ifr, successFn, errorFn) { |
| var _this = this; |
|
|
| var called = false, |
| tout = null; |
|
|
| var listener = function listener() { |
| if (called) { |
| return; |
| } |
|
|
| called = true; |
| clearTimeout(tout); |
|
|
| try { |
| if (!_this.isIframeBlank(ifr)) { |
| ifr.removeEventListener('load', listener); |
|
|
| _this.getIframeContents(ifr, successFn, errorFn); |
| } |
| } catch (e) { |
| errorFn(); |
| } |
| }; |
|
|
| ifr.addEventListener('load', listener); |
| tout = setTimeout(listener, this.iframesTimeout); |
| }, |
| }, |
| { |
| key: 'onIframeReady', |
| value: function onIframeReady(ifr, successFn, errorFn) { |
| try { |
| if (ifr.contentWindow.document.readyState === 'complete') { |
| if (this.isIframeBlank(ifr)) { |
| this.observeIframeLoad(ifr, successFn, errorFn); |
| } else { |
| this.getIframeContents(ifr, successFn, errorFn); |
| } |
| } else { |
| this.observeIframeLoad(ifr, successFn, errorFn); |
| } |
| } catch (e) { |
| errorFn(); |
| } |
| }, |
| }, |
| { |
| key: 'waitForIframes', |
| value: function waitForIframes(ctx, done) { |
| var _this2 = this; |
|
|
| var eachCalled = 0; |
| this.forEachIframe( |
| ctx, |
| function () { |
| return true; |
| }, |
| function (ifr) { |
| eachCalled++; |
|
|
| _this2.waitForIframes(ifr.querySelector('html'), function () { |
| if (!--eachCalled) { |
| done(); |
| } |
| }); |
| }, |
| function (handled) { |
| if (!handled) { |
| done(); |
| } |
| } |
| ); |
| }, |
| }, |
| { |
| key: 'forEachIframe', |
| value: function forEachIframe(ctx, filter, each) { |
| var _this3 = this; |
|
|
| var end = |
| arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {}; |
| var ifr = ctx.querySelectorAll('iframe'), |
| open = ifr.length, |
| handled = 0; |
| ifr = Array.prototype.slice.call(ifr); |
|
|
| var checkEnd = function checkEnd() { |
| if (--open <= 0) { |
| end(handled); |
| } |
| }; |
|
|
| if (!open) { |
| checkEnd(); |
| } |
|
|
| ifr.forEach(function (ifr) { |
| if (DOMIterator.matches(ifr, _this3.exclude)) { |
| checkEnd(); |
| } else { |
| _this3.onIframeReady( |
| ifr, |
| function (con) { |
| if (filter(ifr)) { |
| handled++; |
| each(con); |
| } |
|
|
| checkEnd(); |
| }, |
| checkEnd |
| ); |
| } |
| }); |
| }, |
| }, |
| { |
| key: 'createIterator', |
| value: function createIterator(ctx, whatToShow, filter) { |
| return document.createNodeIterator(ctx, whatToShow, filter, false); |
| }, |
| }, |
| { |
| key: 'createInstanceOnIframe', |
| value: function createInstanceOnIframe(contents) { |
| return new DOMIterator(contents.querySelector('html'), this.iframes); |
| }, |
| }, |
| { |
| key: 'compareNodeIframe', |
| value: function compareNodeIframe(node, prevNode, ifr) { |
| var compCurr = node.compareDocumentPosition(ifr), |
| prev = Node.DOCUMENT_POSITION_PRECEDING; |
|
|
| if (compCurr & prev) { |
| if (prevNode !== null) { |
| var compPrev = prevNode.compareDocumentPosition(ifr), |
| after = Node.DOCUMENT_POSITION_FOLLOWING; |
|
|
| if (compPrev & after) { |
| return true; |
| } |
| } else { |
| return true; |
| } |
| } |
|
|
| return false; |
| }, |
| }, |
| { |
| key: 'getIteratorNode', |
| value: function getIteratorNode(itr) { |
| var prevNode = itr.previousNode(); |
| var node; |
|
|
| if (prevNode === null) { |
| node = itr.nextNode(); |
| } else { |
| node = itr.nextNode() && itr.nextNode(); |
| } |
|
|
| return { |
| prevNode: prevNode, |
| node: node, |
| }; |
| }, |
| }, |
| { |
| key: 'checkIframeFilter', |
| value: function checkIframeFilter(node, prevNode, currIfr, ifr) { |
| var key = false, |
| handled = false; |
| ifr.forEach(function (ifrDict, i) { |
| if (ifrDict.val === currIfr) { |
| key = i; |
| handled = ifrDict.handled; |
| } |
| }); |
|
|
| if (this.compareNodeIframe(node, prevNode, currIfr)) { |
| if (key === false && !handled) { |
| ifr.push({ |
| val: currIfr, |
| handled: true, |
| }); |
| } else if (key !== false && !handled) { |
| ifr[key].handled = true; |
| } |
|
|
| return true; |
| } |
|
|
| if (key === false) { |
| ifr.push({ |
| val: currIfr, |
| handled: false, |
| }); |
| } |
|
|
| return false; |
| }, |
| }, |
| { |
| key: 'handleOpenIframes', |
| value: function handleOpenIframes(ifr, whatToShow, eCb, fCb) { |
| var _this4 = this; |
|
|
| ifr.forEach(function (ifrDict) { |
| if (!ifrDict.handled) { |
| _this4.getIframeContents(ifrDict.val, function (con) { |
| _this4.createInstanceOnIframe(con).forEachNode(whatToShow, eCb, fCb); |
| }); |
| } |
| }); |
| }, |
| }, |
| { |
| key: 'iterateThroughNodes', |
| value: function iterateThroughNodes(whatToShow, ctx, eachCb, filterCb, doneCb) { |
| var _this5 = this; |
|
|
| var itr = this.createIterator(ctx, whatToShow, filterCb); |
|
|
| var ifr = [], |
| elements = [], |
| node, |
| prevNode, |
| retrieveNodes = function retrieveNodes() { |
| var _this5$getIteratorNod = _this5.getIteratorNode(itr); |
|
|
| prevNode = _this5$getIteratorNod.prevNode; |
| node = _this5$getIteratorNod.node; |
| return node; |
| }; |
|
|
| while (retrieveNodes()) { |
| if (this.iframes) { |
| this.forEachIframe( |
| ctx, |
| function (currIfr) { |
| return _this5.checkIframeFilter(node, prevNode, currIfr, ifr); |
| }, |
| function (con) { |
| _this5.createInstanceOnIframe(con).forEachNode( |
| whatToShow, |
| function (ifrNode) { |
| return elements.push(ifrNode); |
| }, |
| filterCb |
| ); |
| } |
| ); |
| } |
|
|
| elements.push(node); |
| } |
|
|
| elements.forEach(function (node) { |
| eachCb(node); |
| }); |
|
|
| if (this.iframes) { |
| this.handleOpenIframes(ifr, whatToShow, eachCb, filterCb); |
| } |
|
|
| doneCb(); |
| }, |
| }, |
| { |
| key: 'forEachNode', |
| value: function forEachNode(whatToShow, each, filter) { |
| var _this6 = this; |
|
|
| var done = |
| arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {}; |
| var contexts = this.getContexts(); |
| var open = contexts.length; |
|
|
| if (!open) { |
| done(); |
| } |
|
|
| contexts.forEach(function (ctx) { |
| var ready = function ready() { |
| _this6.iterateThroughNodes(whatToShow, ctx, each, filter, function () { |
| if (--open <= 0) { |
| done(); |
| } |
| }); |
| }; |
|
|
| if (_this6.iframes) { |
| _this6.waitForIframes(ctx, ready); |
| } else { |
| ready(); |
| } |
| }); |
| }, |
| }, |
| ], |
| [ |
| { |
| key: 'matches', |
| value: function matches(element, selector) { |
| var selectors = typeof selector === 'string' ? [selector] : selector, |
| fn = |
| element.matches || |
| element.matchesSelector || |
| element.msMatchesSelector || |
| element.mozMatchesSelector || |
| element.oMatchesSelector || |
| element.webkitMatchesSelector; |
|
|
| if (fn) { |
| var match = false; |
| selectors.every(function (sel) { |
| if (fn.call(element, sel)) { |
| match = true; |
| return false; |
| } |
|
|
| return true; |
| }); |
| return match; |
| } else { |
| return false; |
| } |
| }, |
| }, |
| ] |
| ); |
|
|
| return DOMIterator; |
| })(); |
|
|
| var RegExpCreator = |
| |
| (function () { |
| function RegExpCreator(options) { |
| _classCallCheck(this, RegExpCreator); |
|
|
| this.opt = _extends( |
| {}, |
| { |
| diacritics: true, |
| synonyms: {}, |
| accuracy: 'partially', |
| caseSensitive: false, |
| ignoreJoiners: false, |
| ignorePunctuation: [], |
| wildcards: 'disabled', |
| }, |
| options |
| ); |
| } |
|
|
| _createClass(RegExpCreator, [ |
| { |
| key: 'create', |
| value: function create(str) { |
| if (this.opt.wildcards !== 'disabled') { |
| str = this.setupWildcardsRegExp(str); |
| } |
|
|
| str = this.escapeStr(str); |
|
|
| if (Object.keys(this.opt.synonyms).length) { |
| str = this.createSynonymsRegExp(str); |
| } |
|
|
| if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { |
| str = this.setupIgnoreJoinersRegExp(str); |
| } |
|
|
| if (this.opt.diacritics) { |
| str = this.createDiacriticsRegExp(str); |
| } |
|
|
| str = this.createMergedBlanksRegExp(str); |
|
|
| if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { |
| str = this.createJoinersRegExp(str); |
| } |
|
|
| if (this.opt.wildcards !== 'disabled') { |
| str = this.createWildcardsRegExp(str); |
| } |
|
|
| str = this.createAccuracyRegExp(str); |
| return new RegExp(str, 'gm'.concat(this.opt.caseSensitive ? '' : 'i')); |
| }, |
| }, |
| { |
| key: 'sortByLength', |
| value: function sortByLength(arry) { |
| return arry.sort(function (a, b) { |
| return a.length === b.length ? (a > b ? 1 : -1) : b.length - a.length; |
| }); |
| }, |
| }, |
| { |
| key: 'escapeStr', |
| value: function escapeStr(str) { |
| return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); |
| }, |
| }, |
| { |
| key: 'createSynonymsRegExp', |
| value: function createSynonymsRegExp(str) { |
| var _this = this; |
|
|
| var syn = this.opt.synonyms, |
| sens = this.opt.caseSensitive ? '' : 'i', |
| joinerPlaceholder = this.opt.ignoreJoiners || this.opt.ignorePunctuation.length ? '\0' : ''; |
|
|
| for (var index in syn) { |
| if (syn.hasOwnProperty(index)) { |
| var keys = Array.isArray(syn[index]) ? syn[index] : [syn[index]]; |
| keys.unshift(index); |
| keys = this.sortByLength(keys) |
| .map(function (key) { |
| if (_this.opt.wildcards !== 'disabled') { |
| key = _this.setupWildcardsRegExp(key); |
| } |
|
|
| key = _this.escapeStr(key); |
| return key; |
| }) |
| .filter(function (k) { |
| return k !== ''; |
| }); |
|
|
| if (keys.length > 1) { |
| str = str.replace( |
| new RegExp( |
| '('.concat( |
| keys |
| .map(function (k) { |
| return _this.escapeStr(k); |
| }) |
| .join('|'), |
| ')' |
| ), |
| 'gm'.concat(sens) |
| ), |
| joinerPlaceholder + |
| '('.concat( |
| keys |
| .map(function (k) { |
| return _this.processSynonyms(k); |
| }) |
| .join('|'), |
| ')' |
| ) + |
| joinerPlaceholder |
| ); |
| } |
| } |
| } |
|
|
| return str; |
| }, |
| }, |
| { |
| key: 'processSynonyms', |
| value: function processSynonyms(str) { |
| if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { |
| str = this.setupIgnoreJoinersRegExp(str); |
| } |
|
|
| return str; |
| }, |
| }, |
| { |
| key: 'setupWildcardsRegExp', |
| value: function setupWildcardsRegExp(str) { |
| str = str.replace(/(?:\\)*\?/g, function (val) { |
| return val.charAt(0) === '\\' ? '?' : '\x01'; |
| }); |
| return str.replace(/(?:\\)*\*/g, function (val) { |
| return val.charAt(0) === '\\' ? '*' : '\x02'; |
| }); |
| }, |
| }, |
| { |
| key: 'createWildcardsRegExp', |
| value: function createWildcardsRegExp(str) { |
| var spaces = this.opt.wildcards === 'withSpaces'; |
| return str |
| .replace(/\u0001/g, spaces ? '[\\S\\s]?' : '\\S?') |
| .replace(/\u0002/g, spaces ? '[\\S\\s]*?' : '\\S*'); |
| }, |
| }, |
| { |
| key: 'setupIgnoreJoinersRegExp', |
| value: function setupIgnoreJoinersRegExp(str) { |
| return str.replace(/[^(|)\\]/g, function (val, indx, original) { |
| var nextChar = original.charAt(indx + 1); |
|
|
| if (/[(|)\\]/.test(nextChar) || nextChar === '') { |
| return val; |
| } else { |
| return val + '\0'; |
| } |
| }); |
| }, |
| }, |
| { |
| key: 'createJoinersRegExp', |
| value: function createJoinersRegExp(str) { |
| var joiner = []; |
| var ignorePunctuation = this.opt.ignorePunctuation; |
|
|
| if (Array.isArray(ignorePunctuation) && ignorePunctuation.length) { |
| joiner.push(this.escapeStr(ignorePunctuation.join(''))); |
| } |
|
|
| if (this.opt.ignoreJoiners) { |
| joiner.push('\\u00ad\\u200b\\u200c\\u200d'); |
| } |
|
|
| return joiner.length ? str.split(/\u0000+/).join('['.concat(joiner.join(''), ']*')) : str; |
| }, |
| }, |
| { |
| key: 'createDiacriticsRegExp', |
| value: function createDiacriticsRegExp(str) { |
| var sens = this.opt.caseSensitive ? '' : 'i', |
| dct = this.opt.caseSensitive |
| ? [ |
| 'aàáảãạăằắẳẵặâầấẩẫậäåāą', |
| 'AÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ', |
| 'cçćč', |
| 'CÇĆČ', |
| 'dđď', |
| 'DĐĎ', |
| 'eèéẻẽẹêềếểễệëěēę', |
| 'EÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ', |
| 'iìíỉĩịîïī', |
| 'IÌÍỈĨỊÎÏĪ', |
| 'lł', |
| 'LŁ', |
| 'nñňń', |
| 'NÑŇŃ', |
| 'oòóỏõọôồốổỗộơởỡớờợöøō', |
| 'OÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ', |
| 'rř', |
| 'RŘ', |
| 'sšśșş', |
| 'SŠŚȘŞ', |
| 'tťțţ', |
| 'TŤȚŢ', |
| 'uùúủũụưừứửữựûüůū', |
| 'UÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ', |
| 'yýỳỷỹỵÿ', |
| 'YÝỲỶỸỴŸ', |
| 'zžżź', |
| 'ZŽŻŹ', |
| ] |
| : [ |
| 'aàáảãạăằắẳẵặâầấẩẫậäåāąAÀÁẢÃẠĂẰẮẲẴẶÂẦẤẨẪẬÄÅĀĄ', |
| 'cçćčCÇĆČ', |
| 'dđďDĐĎ', |
| 'eèéẻẽẹêềếểễệëěēęEÈÉẺẼẸÊỀẾỂỄỆËĚĒĘ', |
| 'iìíỉĩịîïīIÌÍỈĨỊÎÏĪ', |
| 'lłLŁ', |
| 'nñňńNÑŇŃ', |
| 'oòóỏõọôồốổỗộơởỡớờợöøōOÒÓỎÕỌÔỒỐỔỖỘƠỞỠỚỜỢÖØŌ', |
| 'rřRŘ', |
| 'sšśșşSŠŚȘŞ', |
| 'tťțţTŤȚŢ', |
| 'uùúủũụưừứửữựûüůūUÙÚỦŨỤƯỪỨỬỮỰÛÜŮŪ', |
| 'yýỳỷỹỵÿYÝỲỶỸỴŸ', |
| 'zžżźZŽŻŹ', |
| ]; |
| var handled = []; |
| str.split('').forEach(function (ch) { |
| dct.every(function (dct) { |
| if (dct.indexOf(ch) !== -1) { |
| if (handled.indexOf(dct) > -1) { |
| return false; |
| } |
|
|
| str = str.replace( |
| new RegExp('['.concat(dct, ']'), 'gm'.concat(sens)), |
| '['.concat(dct, ']') |
| ); |
| handled.push(dct); |
| } |
|
|
| return true; |
| }); |
| }); |
| return str; |
| }, |
| }, |
| { |
| key: 'createMergedBlanksRegExp', |
| value: function createMergedBlanksRegExp(str) { |
| return str.replace(/[\s]+/gim, '[\\s]+'); |
| }, |
| }, |
| { |
| key: 'createAccuracyRegExp', |
| value: function createAccuracyRegExp(str) { |
| var _this2 = this; |
|
|
| var chars = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~¡¿'; |
| var acc = this.opt.accuracy, |
| val = typeof acc === 'string' ? acc : acc.value, |
| ls = typeof acc === 'string' ? [] : acc.limiters, |
| lsJoin = ''; |
| ls.forEach(function (limiter) { |
| lsJoin += '|'.concat(_this2.escapeStr(limiter)); |
| }); |
|
|
| switch (val) { |
| case 'partially': |
| default: |
| return '()('.concat(str, ')'); |
|
|
| case 'complementary': |
| lsJoin = '\\s' + (lsJoin ? lsJoin : this.escapeStr(chars)); |
| return '()([^'.concat(lsJoin, ']*').concat(str, '[^').concat(lsJoin, ']*)'); |
|
|
| case 'exactly': |
| return '(^|\\s'.concat(lsJoin, ')(').concat(str, ')(?=$|\\s').concat(lsJoin, ')'); |
| } |
| }, |
| }, |
| ]); |
|
|
| return RegExpCreator; |
| })(); |
|
|
| var Mark = |
| |
| (function () { |
| function Mark(ctx) { |
| _classCallCheck(this, Mark); |
|
|
| this.ctx = ctx; |
| this.ie = false; |
| var ua = window.navigator.userAgent; |
|
|
| if (ua.indexOf('MSIE') > -1 || ua.indexOf('Trident') > -1) { |
| this.ie = true; |
| } |
| } |
|
|
| _createClass(Mark, [ |
| { |
| key: 'log', |
| value: function log(msg) { |
| var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'debug'; |
| var log = this.opt.log; |
|
|
| if (!this.opt.debug) { |
| return; |
| } |
|
|
| if (_typeof(log) === 'object' && typeof log[level] === 'function') { |
| log[level]('mark.js: '.concat(msg)); |
| } |
| }, |
| }, |
| { |
| key: 'getSeparatedKeywords', |
| value: function getSeparatedKeywords(sv) { |
| var _this = this; |
|
|
| var stack = []; |
| sv.forEach(function (kw) { |
| if (!_this.opt.separateWordSearch) { |
| if (kw.trim() && stack.indexOf(kw) === -1) { |
| stack.push(kw); |
| } |
| } else { |
| kw.split(' ').forEach(function (kwSplitted) { |
| if (kwSplitted.trim() && stack.indexOf(kwSplitted) === -1) { |
| stack.push(kwSplitted); |
| } |
| }); |
| } |
| }); |
| return { |
| keywords: stack.sort(function (a, b) { |
| return b.length - a.length; |
| }), |
| length: stack.length, |
| }; |
| }, |
| }, |
| { |
| key: 'isNumeric', |
| value: function isNumeric(value) { |
| return Number(parseFloat(value)) == value; |
| }, |
| }, |
| { |
| key: 'checkRanges', |
| value: function checkRanges(array) { |
| var _this2 = this; |
|
|
| if (!Array.isArray(array) || Object.prototype.toString.call(array[0]) !== '[object Object]') { |
| this.log('markRanges() will only accept an array of objects'); |
| this.opt.noMatch(array); |
| return []; |
| } |
|
|
| var stack = []; |
| var last = 0; |
| array |
| .sort(function (a, b) { |
| return a.start - b.start; |
| }) |
| .forEach(function (item) { |
| var _this2$callNoMatchOnI = _this2.callNoMatchOnInvalidRanges(item, last), |
| start = _this2$callNoMatchOnI.start, |
| end = _this2$callNoMatchOnI.end, |
| valid = _this2$callNoMatchOnI.valid; |
|
|
| if (valid) { |
| item.start = start; |
| item.length = end - start; |
| stack.push(item); |
| last = end; |
| } |
| }); |
| return stack; |
| }, |
| }, |
| { |
| key: 'callNoMatchOnInvalidRanges', |
| value: function callNoMatchOnInvalidRanges(range, last) { |
| var start, |
| end, |
| valid = false; |
|
|
| if (range && typeof range.start !== 'undefined') { |
| start = parseInt(range.start, 10); |
| end = start + parseInt(range.length, 10); |
|
|
| if ( |
| this.isNumeric(range.start) && |
| this.isNumeric(range.length) && |
| end - last > 0 && |
| end - start > 0 |
| ) { |
| valid = true; |
| } else { |
| this.log('Ignoring invalid or overlapping range: ' + ''.concat(JSON.stringify(range))); |
| this.opt.noMatch(range); |
| } |
| } else { |
| this.log('Ignoring invalid range: '.concat(JSON.stringify(range))); |
| this.opt.noMatch(range); |
| } |
|
|
| return { |
| start: start, |
| end: end, |
| valid: valid, |
| }; |
| }, |
| }, |
| { |
| key: 'checkWhitespaceRanges', |
| value: function checkWhitespaceRanges(range, originalLength, string) { |
| var end, |
| valid = true, |
| max = string.length, |
| offset = originalLength - max, |
| start = parseInt(range.start, 10) - offset; |
| start = start > max ? max : start; |
| end = start + parseInt(range.length, 10); |
|
|
| if (end > max) { |
| end = max; |
| this.log('End range automatically set to the max value of '.concat(max)); |
| } |
|
|
| if (start < 0 || end - start < 0 || start > max || end > max) { |
| valid = false; |
| this.log('Invalid range: '.concat(JSON.stringify(range))); |
| this.opt.noMatch(range); |
| } else if (string.substring(start, end).replace(/\s+/g, '') === '') { |
| valid = false; |
| this.log('Skipping whitespace only range: ' + JSON.stringify(range)); |
| this.opt.noMatch(range); |
| } |
|
|
| return { |
| start: start, |
| end: end, |
| valid: valid, |
| }; |
| }, |
| }, |
| { |
| key: 'getTextNodes', |
| value: function getTextNodes(cb) { |
| var _this3 = this; |
|
|
| var val = '', |
| nodes = []; |
| this.iterator.forEachNode( |
| NodeFilter.SHOW_TEXT, |
| function (node) { |
| nodes.push({ |
| start: val.length, |
| end: (val += node.textContent).length, |
| node: node, |
| }); |
| }, |
| function (node) { |
| if (_this3.matchesExclude(node.parentNode)) { |
| return NodeFilter.FILTER_REJECT; |
| } else { |
| return NodeFilter.FILTER_ACCEPT; |
| } |
| }, |
| function () { |
| cb({ |
| value: val, |
| nodes: nodes, |
| }); |
| } |
| ); |
| }, |
| }, |
| { |
| key: 'matchesExclude', |
| value: function matchesExclude(el) { |
| return DOMIterator.matches( |
| el, |
| this.opt.exclude.concat(['script', 'style', 'title', 'head', 'html']) |
| ); |
| }, |
| }, |
| { |
| key: 'wrapRangeInTextNode', |
| value: function wrapRangeInTextNode(node, start, end) { |
| var hEl = !this.opt.element ? 'mark' : this.opt.element, |
| startNode = node.splitText(start), |
| ret = startNode.splitText(end - start); |
| var repl = document.createElement(hEl); |
| repl.setAttribute('data-markjs', 'true'); |
|
|
| if (this.opt.className) { |
| repl.setAttribute('class', this.opt.className); |
| } |
|
|
| repl.textContent = startNode.textContent; |
| startNode.parentNode.replaceChild(repl, startNode); |
| return ret; |
| }, |
| }, |
| { |
| key: 'wrapRangeInMappedTextNode', |
| value: function wrapRangeInMappedTextNode(dict, start, end, filterCb, eachCb) { |
| var _this4 = this; |
|
|
| dict.nodes.every(function (n, i) { |
| var sibl = dict.nodes[i + 1]; |
|
|
| if (typeof sibl === 'undefined' || sibl.start > start) { |
| if (!filterCb(n.node)) { |
| return false; |
| } |
|
|
| var s = start - n.start, |
| e = (end > n.end ? n.end : end) - n.start, |
| startStr = dict.value.substr(0, n.start), |
| endStr = dict.value.substr(e + n.start); |
| n.node = _this4.wrapRangeInTextNode(n.node, s, e); |
| dict.value = startStr + endStr; |
| dict.nodes.forEach(function (k, j) { |
| if (j >= i) { |
| if (dict.nodes[j].start > 0 && j !== i) { |
| dict.nodes[j].start -= e; |
| } |
|
|
| dict.nodes[j].end -= e; |
| } |
| }); |
| end -= e; |
| eachCb(n.node.previousSibling, n.start); |
|
|
| if (end > n.end) { |
| start = n.end; |
| } else { |
| return false; |
| } |
| } |
|
|
| return true; |
| }); |
| }, |
| }, |
| { |
| key: 'wrapGroups', |
| value: function wrapGroups(node, pos, len, eachCb) { |
| node = this.wrapRangeInTextNode(node, pos, pos + len); |
| eachCb(node.previousSibling); |
| return node; |
| }, |
| }, |
| { |
| key: 'separateGroups', |
| value: function separateGroups(node, match, matchIdx, filterCb, eachCb) { |
| var matchLen = match.length; |
|
|
| for (var i = 1; i < matchLen; i++) { |
| var pos = node.textContent.indexOf(match[i]); |
|
|
| if (match[i] && pos > -1 && filterCb(match[i], node)) { |
| node = this.wrapGroups(node, pos, match[i].length, eachCb); |
| } |
| } |
|
|
| return node; |
| }, |
| }, |
| { |
| key: 'wrapMatches', |
| value: function wrapMatches(regex, ignoreGroups, filterCb, eachCb, endCb) { |
| var _this5 = this; |
|
|
| var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; |
| this.getTextNodes(function (dict) { |
| dict.nodes.forEach(function (node) { |
| node = node.node; |
| var match; |
|
|
| while ((match = regex.exec(node.textContent)) !== null && match[matchIdx] !== '') { |
| if (_this5.opt.separateGroups) { |
| node = _this5.separateGroups(node, match, matchIdx, filterCb, eachCb); |
| } else { |
| if (!filterCb(match[matchIdx], node)) { |
| continue; |
| } |
|
|
| var pos = match.index; |
|
|
| if (matchIdx !== 0) { |
| for (var i = 1; i < matchIdx; i++) { |
| pos += match[i].length; |
| } |
| } |
|
|
| node = _this5.wrapGroups(node, pos, match[matchIdx].length, eachCb); |
| } |
|
|
| regex.lastIndex = 0; |
| } |
| }); |
| endCb(); |
| }); |
| }, |
| }, |
| { |
| key: 'wrapMatchesAcrossElements', |
| value: function wrapMatchesAcrossElements(regex, ignoreGroups, filterCb, eachCb, endCb) { |
| var _this6 = this; |
|
|
| var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; |
| this.getTextNodes(function (dict) { |
| var match; |
|
|
| while ((match = regex.exec(dict.value)) !== null && match[matchIdx] !== '') { |
| var start = match.index; |
|
|
| if (matchIdx !== 0) { |
| for (var i = 1; i < matchIdx; i++) { |
| start += match[i].length; |
| } |
| } |
|
|
| var end = start + match[matchIdx].length; |
|
|
| _this6.wrapRangeInMappedTextNode( |
| dict, |
| start, |
| end, |
| function (node) { |
| return filterCb(match[matchIdx], node); |
| }, |
| function (node, lastIndex) { |
| regex.lastIndex = lastIndex; |
| eachCb(node); |
| } |
| ); |
| } |
|
|
| endCb(); |
| }); |
| }, |
| }, |
| { |
| key: 'wrapRangeFromIndex', |
| value: function wrapRangeFromIndex(ranges, filterCb, eachCb, endCb) { |
| var _this7 = this; |
|
|
| this.getTextNodes(function (dict) { |
| var originalLength = dict.value.length; |
| ranges.forEach(function (range, counter) { |
| var _this7$checkWhitespac = _this7.checkWhitespaceRanges( |
| range, |
| originalLength, |
| dict.value |
| ), |
| start = _this7$checkWhitespac.start, |
| end = _this7$checkWhitespac.end, |
| valid = _this7$checkWhitespac.valid; |
|
|
| if (valid) { |
| _this7.wrapRangeInMappedTextNode( |
| dict, |
| start, |
| end, |
| function (node) { |
| return filterCb(node, range, dict.value.substring(start, end), counter); |
| }, |
| function (node) { |
| eachCb(node, range); |
| } |
| ); |
| } |
| }); |
| endCb(); |
| }); |
| }, |
| }, |
| { |
| key: 'unwrapMatches', |
| value: function unwrapMatches(node) { |
| var parent = node.parentNode; |
| var docFrag = document.createDocumentFragment(); |
|
|
| while (node.firstChild) { |
| docFrag.appendChild(node.removeChild(node.firstChild)); |
| } |
|
|
| parent.replaceChild(docFrag, node); |
|
|
| if (!this.ie) { |
| parent.normalize(); |
| } else { |
| this.normalizeTextNode(parent); |
| } |
| }, |
| }, |
| { |
| key: 'normalizeTextNode', |
| value: function normalizeTextNode(node) { |
| if (!node) { |
| return; |
| } |
|
|
| if (node.nodeType === 3) { |
| while (node.nextSibling && node.nextSibling.nodeType === 3) { |
| node.nodeValue += node.nextSibling.nodeValue; |
| node.parentNode.removeChild(node.nextSibling); |
| } |
| } else { |
| this.normalizeTextNode(node.firstChild); |
| } |
|
|
| this.normalizeTextNode(node.nextSibling); |
| }, |
| }, |
| { |
| key: 'markRegExp', |
| value: function markRegExp(regexp, opt) { |
| var _this8 = this; |
|
|
| this.opt = opt; |
| this.log('Searching with expression "'.concat(regexp, '"')); |
| var totalMatches = 0, |
| fn = 'wrapMatches'; |
|
|
| var eachCb = function eachCb(element) { |
| totalMatches++; |
|
|
| _this8.opt.each(element); |
| }; |
|
|
| if (this.opt.acrossElements) { |
| fn = 'wrapMatchesAcrossElements'; |
| } |
|
|
| this[fn]( |
| regexp, |
| this.opt.ignoreGroups, |
| function (match, node) { |
| return _this8.opt.filter(node, match, totalMatches); |
| }, |
| eachCb, |
| function () { |
| if (totalMatches === 0) { |
| _this8.opt.noMatch(regexp); |
| } |
|
|
| _this8.opt.done(totalMatches); |
| } |
| ); |
| }, |
| }, |
| { |
| key: 'mark', |
| value: function mark(sv, opt) { |
| var _this9 = this; |
|
|
| this.opt = opt; |
| var totalMatches = 0, |
| fn = 'wrapMatches'; |
|
|
| var _this$getSeparatedKey = this.getSeparatedKeywords(typeof sv === 'string' ? [sv] : sv), |
| kwArr = _this$getSeparatedKey.keywords, |
| kwArrLen = _this$getSeparatedKey.length, |
| handler = function handler(kw) { |
| var regex = new RegExpCreator(_this9.opt).create(kw); |
| var matches = 0; |
|
|
| _this9.log('Searching with expression "'.concat(regex, '"')); |
|
|
| _this9[fn]( |
| regex, |
| 1, |
| function (term, node) { |
| return _this9.opt.filter(node, kw, totalMatches, matches); |
| }, |
| function (element) { |
| matches++; |
| totalMatches++; |
|
|
| _this9.opt.each(element); |
| }, |
| function () { |
| if (matches === 0) { |
| _this9.opt.noMatch(kw); |
| } |
|
|
| if (kwArr[kwArrLen - 1] === kw) { |
| _this9.opt.done(totalMatches); |
| } else { |
| handler(kwArr[kwArr.indexOf(kw) + 1]); |
| } |
| } |
| ); |
| }; |
|
|
| if (this.opt.acrossElements) { |
| fn = 'wrapMatchesAcrossElements'; |
| } |
|
|
| if (kwArrLen === 0) { |
| this.opt.done(totalMatches); |
| } else { |
| handler(kwArr[0]); |
| } |
| }, |
| }, |
| { |
| key: 'markRanges', |
| value: function markRanges(rawRanges, opt) { |
| var _this10 = this; |
|
|
| this.opt = opt; |
| var totalMatches = 0, |
| ranges = this.checkRanges(rawRanges); |
|
|
| if (ranges && ranges.length) { |
| this.log('Starting to mark with the following ranges: ' + JSON.stringify(ranges)); |
| this.wrapRangeFromIndex( |
| ranges, |
| function (node, range, match, counter) { |
| return _this10.opt.filter(node, range, match, counter); |
| }, |
| function (element, range) { |
| totalMatches++; |
|
|
| _this10.opt.each(element, range); |
| }, |
| function () { |
| _this10.opt.done(totalMatches); |
| } |
| ); |
| } else { |
| this.opt.done(totalMatches); |
| } |
| }, |
| }, |
| { |
| key: 'unmark', |
| value: function unmark(opt) { |
| var _this11 = this; |
|
|
| this.opt = opt; |
| var sel = this.opt.element ? this.opt.element : '*'; |
| sel += '[data-markjs]'; |
|
|
| if (this.opt.className) { |
| sel += '.'.concat(this.opt.className); |
| } |
|
|
| this.log('Removal selector "'.concat(sel, '"')); |
| this.iterator.forEachNode( |
| NodeFilter.SHOW_ELEMENT, |
| function (node) { |
| _this11.unwrapMatches(node); |
| }, |
| function (node) { |
| var matchesSel = DOMIterator.matches(node, sel), |
| matchesExclude = _this11.matchesExclude(node); |
|
|
| if (!matchesSel || matchesExclude) { |
| return NodeFilter.FILTER_REJECT; |
| } else { |
| return NodeFilter.FILTER_ACCEPT; |
| } |
| }, |
| this.opt.done |
| ); |
| }, |
| }, |
| { |
| key: 'opt', |
| set: function set(val) { |
| this._opt = _extends( |
| {}, |
| { |
| element: '', |
| className: '', |
| exclude: [], |
| iframes: false, |
| iframesTimeout: 5000, |
| separateWordSearch: true, |
| acrossElements: false, |
| ignoreGroups: 0, |
| each: function each() {}, |
| noMatch: function noMatch() {}, |
| filter: function filter() { |
| return true; |
| }, |
| done: function done() {}, |
| debug: false, |
| log: window.console, |
| }, |
| val |
| ); |
| }, |
| get: function get() { |
| return this._opt; |
| }, |
| }, |
| { |
| key: 'iterator', |
| get: function get() { |
| return new DOMIterator(this.ctx, this.opt.iframes, this.opt.exclude, this.opt.iframesTimeout); |
| }, |
| }, |
| ]); |
|
|
| return Mark; |
| })(); |
|
|
| function Mark$1(ctx) { |
| var _this = this; |
|
|
| var instance = new Mark(ctx); |
|
|
| this.mark = function (sv, opt) { |
| instance.mark(sv, opt); |
| return _this; |
| }; |
|
|
| this.markRegExp = function (sv, opt) { |
| instance.markRegExp(sv, opt); |
| return _this; |
| }; |
|
|
| this.markRanges = function (sv, opt) { |
| instance.markRanges(sv, opt); |
| return _this; |
| }; |
|
|
| this.unmark = function (opt) { |
| instance.unmark(opt); |
| return _this; |
| }; |
|
|
| return this; |
| } |
|
|
| return Mark$1; |
| }); |
|
|