govuk_tech_docs 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d445bcd8c1daf9778f0a3e0d8cb352fab848b46c
4
- data.tar.gz: d7fbb83f2f8e7f339033063acb560ad555fae7ce
3
+ metadata.gz: a0b627893fa39ba6cc6484a977b7b9c00639ad28
4
+ data.tar.gz: a45ebcff76937b949bb5c7388359bbd26cbe1d53
5
5
  SHA512:
6
- metadata.gz: 5708cfb64dd99b8741711fcea030bffbcf81c7da49dfaed23a99215fae6140e07200a390760ff0e2334555787ffc9af191c454be96f74a679d74b93cf2723996
7
- data.tar.gz: 42eb4aa9614ae826b2214ebfc4db24aae6c089e1d571986858baf348527382600940b3c7dc80c2fa864477397aca3752a2b8c4972185685f190173fe6ca72988
6
+ metadata.gz: fe4b821226d40bff2fd3d2eff34887862e74eda39c00ef058f512b448f995d1d0181aff90e3448c5493108dbae2eb76d5ee34746a5c7077adb4fede3107c3553
7
+ data.tar.gz: b9e34c88cfc72c46f4cab5e73bd3946e4475e6a1a3a42f2140ef8fb024f48f57ef6f8e57a8f1dc5b47aef41a9ccf7f07bb7ce080d6cb7f81a806da52d5ee8881
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### New feature: Search
6
+
7
+ Adds search functionality. This indexes pages only and is not recommended for single-page sites. To enable write `enable_search: true` in in tech-docs.yml.
8
+
9
+ More info:
10
+ - https://github.com/alphagov/tech-docs-gem/pull/28
11
+
12
+ ### Google Analytics tracking for old headings
13
+
14
+ An event category 'Broken fragment ID' will be pushed to Google Analytics when a user lands on a page with a URL that points to a fragment ID that does not exist on the page.
15
+
16
+ More info:
17
+ - https://github.com/alphagov/tech-docs-gem/pull/30
18
+
3
19
  ## 1.4.0
4
20
 
5
21
  Adds multiple page navigation support and collapsible top level navigation
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in govuk_tech_docs.gemspec
4
4
  gemspec
5
+
6
+ gem 'middleman-search', :git => "git://github.com/alphagov/middleman-search.git"
@@ -28,6 +28,14 @@ Adds a [Google Site Verification code](https://support.google.com/webmasters/ans
28
28
  google_site_verification: TvDTuyvdstyusadrCSDrctyd
29
29
  ```
30
30
 
31
+ ## `enable_search`
32
+
33
+ Enables search functionality. This indexes pages only and is not recommended for single-page sites.
34
+
35
+ ```yaml
36
+ enable_search: true
37
+ ```
38
+
31
39
  ## `header_links`
32
40
 
33
41
  Right hand side navigation.
@@ -33,6 +33,8 @@ prevent_indexing: false
33
33
 
34
34
  google_site_verification: dstbao8TVS^DRVDS&rv76
35
35
 
36
+ enable_search: true
37
+
36
38
  show_contribution_banner: true
37
39
 
38
40
  github_repo: alphagov/example-repo
@@ -29,9 +29,11 @@ Gem::Specification.new do |spec|
29
29
  spec.add_dependency "middleman-livereload"
30
30
  spec.add_dependency "middleman-sprockets", "~> 4.0.0"
31
31
  spec.add_dependency "middleman-syntax", "~> 3.0.0"
32
+ spec.add_dependency "middleman-search"
32
33
  spec.add_dependency "nokogiri"
33
34
  spec.add_dependency "redcarpet", "~> 3.3.2"
34
35
 
36
+
35
37
  spec.add_development_dependency "bundler", "~> 1.15"
36
38
  spec.add_development_dependency "rake", "~> 10.0"
37
39
  spec.add_development_dependency "capybara", "~> 2.18.0"
@@ -19,6 +19,20 @@
19
19
  };
20
20
  };
21
21
 
22
+ function catchBrokenFragmentLinks() {
23
+ var fragment = window.location.hash;
24
+ var $target = $(fragment);
25
+ if(!$target.get(0)) {
26
+ ga(
27
+ 'send',
28
+ 'event',
29
+ 'Broken fragment ID', // Event Category
30
+ 'pageview', // Event Action
31
+ window.location.pathname + fragment // Event Label
32
+ );
33
+ }
34
+ }
35
+
22
36
  $(document).on('ready', function() {
23
37
  if (typeof ga === 'undefined') {
24
38
  return;
@@ -27,5 +41,6 @@
27
41
  $('.technical-documentation a').on('click', linkTrackingEventHandler('inTextClick'));
28
42
  $('.header a').on('click', linkTrackingEventHandler('topNavigationClick'));
29
43
  $('.toc a').on('click', linkTrackingEventHandler('tableOfContentsNavigationClick'));
44
+ catchBrokenFragmentLinks();
30
45
  });
31
46
  })(jQuery);
@@ -0,0 +1,198 @@
1
+ //= require lunr.min
2
+ //= require _vendor/jquery.mark.js
3
+ (function($, Modules) {
4
+ 'use strict';
5
+
6
+ Modules.Search = function Search() {
7
+ var s = this;
8
+ var $html = $('html');
9
+ s.lunrIndex;
10
+ s.lunrData;
11
+ var $searchForm;
12
+ var $searchLabel;
13
+ var $searchInput;
14
+ var $searchResults;
15
+ var $searchResultsTitle;
16
+ var $searchResultsWrapper;
17
+ var $searchResultsClose;
18
+ var results;
19
+ var maxSearchEntries = 10;
20
+
21
+ this.start = function start($element) {
22
+ $searchForm = $element.find('form');
23
+ $searchInput = $element.find('#search');
24
+ $searchLabel = $element.find('.search__label');
25
+ $searchResultsWrapper = $element.find('.search-results')
26
+ $searchResults = $searchResultsWrapper.find('.search-results__content');
27
+ $searchResultsTitle = $searchResultsWrapper.find('.search-results__title');
28
+ $searchResultsClose = $searchResultsWrapper.find('.search-results__close');
29
+ s.downloadSearchIndex();
30
+ attach();
31
+ changeSearchLabel();
32
+ };
33
+
34
+ this.downloadSearchIndex = function downloadSearchIndex() {
35
+ updateTitle('Loading search index')
36
+ $.ajax({
37
+ url: '/search.json',
38
+ cache: true,
39
+ method: 'GET',
40
+ success: function(data) {
41
+ s.lunrData = data;
42
+ s.lunrIndex = lunr.Index.load(s.lunrData.index);
43
+ $(document).trigger('lunrIndexLoaded');
44
+ }
45
+ });
46
+ }
47
+
48
+ function attach() {
49
+ // Search functionality on search text input
50
+ $searchInput.on('input', function (e) {
51
+ e.preventDefault();
52
+ var query = $(this).val();
53
+ s.search(query, function(r) {
54
+ results = r;
55
+ renderResults(query);
56
+ updateTitle();
57
+ });
58
+ });
59
+
60
+ // Set focus on the first search result instead of submiting the search
61
+ // form to Google
62
+ $searchForm.on('submit', function(e) {
63
+ e.preventDefault();
64
+ showResults();
65
+ $searchResults.find('.search-result__title a').first().focus();
66
+ });
67
+
68
+ // Closing the search results, move focus back to the search input
69
+ $searchResultsClose.on('click', function(e) {
70
+ e.preventDefault();
71
+ $searchInput.focus();
72
+ hideResults();
73
+ });
74
+ }
75
+
76
+ function changeSearchLabel() {
77
+ $searchLabel.text('Search');
78
+ }
79
+
80
+ function getResults(query) {
81
+ var results = [];
82
+ s.lunrIndex.search(query).forEach( function (item, index) {
83
+ if ( index < maxSearchEntries ) {
84
+ results.push(s.lunrData.docs[item.ref]);
85
+ }
86
+ });
87
+
88
+ return results;
89
+ }
90
+
91
+ this.search = function search(query, callback) {
92
+ if(query === '') {
93
+ hideResults();
94
+ return;
95
+ }
96
+ showResults();
97
+ // The index has not been downloaded yet, exit early and wait.
98
+ if(!s.lunrIndex) {
99
+ $(document).on('lunrIndexLoaded', function() {
100
+ s.search(query, callback);
101
+ });
102
+ return;
103
+ }
104
+ callback(getResults(query));
105
+ }
106
+
107
+ function renderResults(query) {
108
+ var output = '';
109
+ if (results.length == 0) {
110
+ output += '<p>Nothing found</p>';
111
+ }
112
+ output += '<ul>';
113
+ for(var index in results) {
114
+ var result = results[index];
115
+ var content = s.processContent(result.content, query);
116
+ output += '<li class="search-result">';
117
+ output += '<h3 class="search-result__title">';
118
+ output += '<a href="' + result.url + '">';
119
+ output += result.title;
120
+ output += '</a>';
121
+ output += '</h3>';
122
+ if(typeof content !== 'undefined') {
123
+ output += '<p>' + content + '</p>';
124
+ }
125
+ output += '</li>';
126
+ }
127
+ output += '</ul>';
128
+
129
+ $searchResults.html( output );
130
+ }
131
+
132
+ this.processContent = function processContent(content, query) {
133
+ var output;
134
+ content = '<div>'+ content + '</div>';
135
+ content = $(content).mark(query);
136
+
137
+ // Split content by sentence.
138
+ var sentences = content.html().replace(/(\.+|\:|\!|\?|\r|\n)(\"*|\'*|\)*|}*|]*)/gm, "|").split("|");
139
+
140
+ // Select the first five sentences that contain a <mark>
141
+ var selectedSentences = [];
142
+ for (var i = 0; i < sentences.length; i++) {
143
+ if(selectedSentences.length === 5) {
144
+ break;
145
+ }
146
+
147
+ var containsMark = sentences[i].includes('mark>');
148
+ if (containsMark) {
149
+ selectedSentences.push(sentences[i].trim());
150
+ }
151
+ }
152
+ if(selectedSentences.length > 0) {
153
+ output = ' … ' + selectedSentences.join(' … ') + ' … ';
154
+ }
155
+ return output;
156
+ }
157
+
158
+ // Default text is to display the number of search results
159
+ function updateTitle(text) {
160
+ if(typeof text == "undefined") {
161
+ var count = results.length;
162
+ var text = count + ' results';
163
+ }
164
+ $searchResultsTitle.text(text);
165
+ }
166
+
167
+ function showResults() {
168
+ $searchResultsWrapper.addClass('is-open')
169
+ .attr('aria-hidden', 'false');
170
+ $html.addClass('has-search-results-open');
171
+ }
172
+
173
+ function hideResults() {
174
+ $searchResultsWrapper.removeClass('is-open')
175
+ .attr('aria-hidden', 'true');
176
+ $html.removeClass('has-search-results-open');
177
+ }
178
+ };
179
+
180
+ // Polyfill includes
181
+ if (!String.prototype.includes) {
182
+ String.prototype.includes = function(search, start) {
183
+ 'use strict';
184
+ if (typeof start !== 'number') {
185
+ start = 0;
186
+ }
187
+
188
+ if (start + search.length > this.length) {
189
+ return false;
190
+ } else {
191
+ return this.indexOf(search, start) !== -1;
192
+ }
193
+ };
194
+ }
195
+ })(jQuery, window.GOVUK.Modules);
196
+
197
+
198
+
@@ -4,8 +4,10 @@
4
4
  //= require _modules/navigation
5
5
  //= require _modules/page-expiry
6
6
  //= require _modules/table-of-contents
7
+ //= require _modules/search
7
8
  //= require _modules/collapsible-navigation
8
9
 
10
+
9
11
  $(document).ready(function() {
10
12
  GOVUK.modules.start();
11
13
  });
@@ -0,0 +1,1081 @@
1
+ /*!***************************************************
2
+ * mark.js v8.11.1
3
+ * https://markjs.io/
4
+ * Copyright (c) 2014–2018, Julian Kühnel
5
+ * Released under the MIT license https://git.io/vwTVl
6
+ *****************************************************/
7
+
8
+ (function (global, factory) {
9
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :
10
+ typeof define === 'function' && define.amd ? define(['jquery'], factory) :
11
+ (global.Mark = factory(global.jQuery));
12
+ }(this, (function ($) { 'use strict';
13
+
14
+ $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
15
+
16
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
17
+ return typeof obj;
18
+ } : function (obj) {
19
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
20
+ };
21
+
22
+ var classCallCheck = function (instance, Constructor) {
23
+ if (!(instance instanceof Constructor)) {
24
+ throw new TypeError("Cannot call a class as a function");
25
+ }
26
+ };
27
+
28
+ var createClass = function () {
29
+ function defineProperties(target, props) {
30
+ for (var i = 0; i < props.length; i++) {
31
+ var descriptor = props[i];
32
+ descriptor.enumerable = descriptor.enumerable || false;
33
+ descriptor.configurable = true;
34
+ if ("value" in descriptor) descriptor.writable = true;
35
+ Object.defineProperty(target, descriptor.key, descriptor);
36
+ }
37
+ }
38
+
39
+ return function (Constructor, protoProps, staticProps) {
40
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
41
+ if (staticProps) defineProperties(Constructor, staticProps);
42
+ return Constructor;
43
+ };
44
+ }();
45
+
46
+ var _extends = Object.assign || function (target) {
47
+ for (var i = 1; i < arguments.length; i++) {
48
+ var source = arguments[i];
49
+
50
+ for (var key in source) {
51
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
52
+ target[key] = source[key];
53
+ }
54
+ }
55
+ }
56
+
57
+ return target;
58
+ };
59
+
60
+ var DOMIterator = function () {
61
+ function DOMIterator(ctx) {
62
+ var iframes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
63
+ var exclude = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
64
+ var iframesTimeout = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 5000;
65
+ classCallCheck(this, DOMIterator);
66
+
67
+ this.ctx = ctx;
68
+ this.iframes = iframes;
69
+ this.exclude = exclude;
70
+ this.iframesTimeout = iframesTimeout;
71
+ }
72
+
73
+ createClass(DOMIterator, [{
74
+ key: 'getContexts',
75
+ value: function getContexts() {
76
+ var ctx = void 0,
77
+ filteredCtx = [];
78
+ if (typeof this.ctx === 'undefined' || !this.ctx) {
79
+ ctx = [];
80
+ } else if (NodeList.prototype.isPrototypeOf(this.ctx)) {
81
+ ctx = Array.prototype.slice.call(this.ctx);
82
+ } else if (Array.isArray(this.ctx)) {
83
+ ctx = this.ctx;
84
+ } else if (typeof this.ctx === 'string') {
85
+ ctx = Array.prototype.slice.call(document.querySelectorAll(this.ctx));
86
+ } else {
87
+ ctx = [this.ctx];
88
+ }
89
+ ctx.forEach(function (ctx) {
90
+ var isDescendant = filteredCtx.filter(function (contexts) {
91
+ return contexts.contains(ctx);
92
+ }).length > 0;
93
+ if (filteredCtx.indexOf(ctx) === -1 && !isDescendant) {
94
+ filteredCtx.push(ctx);
95
+ }
96
+ });
97
+ return filteredCtx;
98
+ }
99
+ }, {
100
+ key: 'getIframeContents',
101
+ value: function getIframeContents(ifr, successFn) {
102
+ var errorFn = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {};
103
+
104
+ var doc = void 0;
105
+ try {
106
+ var ifrWin = ifr.contentWindow;
107
+ doc = ifrWin.document;
108
+ if (!ifrWin || !doc) {
109
+ throw new Error('iframe inaccessible');
110
+ }
111
+ } catch (e) {
112
+ errorFn();
113
+ }
114
+ if (doc) {
115
+ successFn(doc);
116
+ }
117
+ }
118
+ }, {
119
+ key: 'isIframeBlank',
120
+ value: function isIframeBlank(ifr) {
121
+ var bl = 'about:blank',
122
+ src = ifr.getAttribute('src').trim(),
123
+ href = ifr.contentWindow.location.href;
124
+ return href === bl && src !== bl && src;
125
+ }
126
+ }, {
127
+ key: 'observeIframeLoad',
128
+ value: function observeIframeLoad(ifr, successFn, errorFn) {
129
+ var _this = this;
130
+
131
+ var called = false,
132
+ tout = null;
133
+ var listener = function listener() {
134
+ if (called) {
135
+ return;
136
+ }
137
+ called = true;
138
+ clearTimeout(tout);
139
+ try {
140
+ if (!_this.isIframeBlank(ifr)) {
141
+ ifr.removeEventListener('load', listener);
142
+ _this.getIframeContents(ifr, successFn, errorFn);
143
+ }
144
+ } catch (e) {
145
+ errorFn();
146
+ }
147
+ };
148
+ ifr.addEventListener('load', listener);
149
+ tout = setTimeout(listener, this.iframesTimeout);
150
+ }
151
+ }, {
152
+ key: 'onIframeReady',
153
+ value: function onIframeReady(ifr, successFn, errorFn) {
154
+ try {
155
+ if (ifr.contentWindow.document.readyState === 'complete') {
156
+ if (this.isIframeBlank(ifr)) {
157
+ this.observeIframeLoad(ifr, successFn, errorFn);
158
+ } else {
159
+ this.getIframeContents(ifr, successFn, errorFn);
160
+ }
161
+ } else {
162
+ this.observeIframeLoad(ifr, successFn, errorFn);
163
+ }
164
+ } catch (e) {
165
+ errorFn();
166
+ }
167
+ }
168
+ }, {
169
+ key: 'waitForIframes',
170
+ value: function waitForIframes(ctx, done) {
171
+ var _this2 = this;
172
+
173
+ var eachCalled = 0;
174
+ this.forEachIframe(ctx, function () {
175
+ return true;
176
+ }, function (ifr) {
177
+ eachCalled++;
178
+ _this2.waitForIframes(ifr.querySelector('html'), function () {
179
+ if (! --eachCalled) {
180
+ done();
181
+ }
182
+ });
183
+ }, function (handled) {
184
+ if (!handled) {
185
+ done();
186
+ }
187
+ });
188
+ }
189
+ }, {
190
+ key: 'forEachIframe',
191
+ value: function forEachIframe(ctx, filter, each) {
192
+ var _this3 = this;
193
+
194
+ var end = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {};
195
+
196
+ var ifr = ctx.querySelectorAll('iframe'),
197
+ open = ifr.length,
198
+ handled = 0;
199
+ ifr = Array.prototype.slice.call(ifr);
200
+ var checkEnd = function checkEnd() {
201
+ if (--open <= 0) {
202
+ end(handled);
203
+ }
204
+ };
205
+ if (!open) {
206
+ checkEnd();
207
+ }
208
+ ifr.forEach(function (ifr) {
209
+ if (DOMIterator.matches(ifr, _this3.exclude)) {
210
+ checkEnd();
211
+ } else {
212
+ _this3.onIframeReady(ifr, function (con) {
213
+ if (filter(ifr)) {
214
+ handled++;
215
+ each(con);
216
+ }
217
+ checkEnd();
218
+ }, checkEnd);
219
+ }
220
+ });
221
+ }
222
+ }, {
223
+ key: 'createIterator',
224
+ value: function createIterator(ctx, whatToShow, filter) {
225
+ return document.createNodeIterator(ctx, whatToShow, filter, false);
226
+ }
227
+ }, {
228
+ key: 'createInstanceOnIframe',
229
+ value: function createInstanceOnIframe(contents) {
230
+ return new DOMIterator(contents.querySelector('html'), this.iframes);
231
+ }
232
+ }, {
233
+ key: 'compareNodeIframe',
234
+ value: function compareNodeIframe(node, prevNode, ifr) {
235
+ var compCurr = node.compareDocumentPosition(ifr),
236
+ prev = Node.DOCUMENT_POSITION_PRECEDING;
237
+ if (compCurr & prev) {
238
+ if (prevNode !== null) {
239
+ var compPrev = prevNode.compareDocumentPosition(ifr),
240
+ after = Node.DOCUMENT_POSITION_FOLLOWING;
241
+ if (compPrev & after) {
242
+ return true;
243
+ }
244
+ } else {
245
+ return true;
246
+ }
247
+ }
248
+ return false;
249
+ }
250
+ }, {
251
+ key: 'getIteratorNode',
252
+ value: function getIteratorNode(itr) {
253
+ var prevNode = itr.previousNode();
254
+ var node = void 0;
255
+ if (prevNode === null) {
256
+ node = itr.nextNode();
257
+ } else {
258
+ node = itr.nextNode() && itr.nextNode();
259
+ }
260
+ return {
261
+ prevNode: prevNode,
262
+ node: node
263
+ };
264
+ }
265
+ }, {
266
+ key: 'checkIframeFilter',
267
+ value: function checkIframeFilter(node, prevNode, currIfr, ifr) {
268
+ var key = false,
269
+ handled = false;
270
+ ifr.forEach(function (ifrDict, i) {
271
+ if (ifrDict.val === currIfr) {
272
+ key = i;
273
+ handled = ifrDict.handled;
274
+ }
275
+ });
276
+ if (this.compareNodeIframe(node, prevNode, currIfr)) {
277
+ if (key === false && !handled) {
278
+ ifr.push({
279
+ val: currIfr,
280
+ handled: true
281
+ });
282
+ } else if (key !== false && !handled) {
283
+ ifr[key].handled = true;
284
+ }
285
+ return true;
286
+ }
287
+ if (key === false) {
288
+ ifr.push({
289
+ val: currIfr,
290
+ handled: false
291
+ });
292
+ }
293
+ return false;
294
+ }
295
+ }, {
296
+ key: 'handleOpenIframes',
297
+ value: function handleOpenIframes(ifr, whatToShow, eCb, fCb) {
298
+ var _this4 = this;
299
+
300
+ ifr.forEach(function (ifrDict) {
301
+ if (!ifrDict.handled) {
302
+ _this4.getIframeContents(ifrDict.val, function (con) {
303
+ _this4.createInstanceOnIframe(con).forEachNode(whatToShow, eCb, fCb);
304
+ });
305
+ }
306
+ });
307
+ }
308
+ }, {
309
+ key: 'iterateThroughNodes',
310
+ value: function iterateThroughNodes(whatToShow, ctx, eachCb, filterCb, doneCb) {
311
+ var _this5 = this;
312
+
313
+ var itr = this.createIterator(ctx, whatToShow, filterCb);
314
+ var ifr = [],
315
+ elements = [],
316
+ node = void 0,
317
+ prevNode = void 0,
318
+ retrieveNodes = function retrieveNodes() {
319
+ var _getIteratorNode = _this5.getIteratorNode(itr);
320
+
321
+ prevNode = _getIteratorNode.prevNode;
322
+ node = _getIteratorNode.node;
323
+
324
+ return node;
325
+ };
326
+ while (retrieveNodes()) {
327
+ if (this.iframes) {
328
+ this.forEachIframe(ctx, function (currIfr) {
329
+ return _this5.checkIframeFilter(node, prevNode, currIfr, ifr);
330
+ }, function (con) {
331
+ _this5.createInstanceOnIframe(con).forEachNode(whatToShow, function (ifrNode) {
332
+ return elements.push(ifrNode);
333
+ }, filterCb);
334
+ });
335
+ }
336
+ elements.push(node);
337
+ }
338
+ elements.forEach(function (node) {
339
+ eachCb(node);
340
+ });
341
+ if (this.iframes) {
342
+ this.handleOpenIframes(ifr, whatToShow, eachCb, filterCb);
343
+ }
344
+ doneCb();
345
+ }
346
+ }, {
347
+ key: 'forEachNode',
348
+ value: function forEachNode(whatToShow, each, filter) {
349
+ var _this6 = this;
350
+
351
+ var done = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {};
352
+
353
+ var contexts = this.getContexts();
354
+ var open = contexts.length;
355
+ if (!open) {
356
+ done();
357
+ }
358
+ contexts.forEach(function (ctx) {
359
+ var ready = function ready() {
360
+ _this6.iterateThroughNodes(whatToShow, ctx, each, filter, function () {
361
+ if (--open <= 0) {
362
+ done();
363
+ }
364
+ });
365
+ };
366
+ if (_this6.iframes) {
367
+ _this6.waitForIframes(ctx, ready);
368
+ } else {
369
+ ready();
370
+ }
371
+ });
372
+ }
373
+ }], [{
374
+ key: 'matches',
375
+ value: function matches(element, selector) {
376
+ var selectors = typeof selector === 'string' ? [selector] : selector,
377
+ fn = element.matches || element.matchesSelector || element.msMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.webkitMatchesSelector;
378
+ if (fn) {
379
+ var match = false;
380
+ selectors.every(function (sel) {
381
+ if (fn.call(element, sel)) {
382
+ match = true;
383
+ return false;
384
+ }
385
+ return true;
386
+ });
387
+ return match;
388
+ } else {
389
+ return false;
390
+ }
391
+ }
392
+ }]);
393
+ return DOMIterator;
394
+ }();
395
+
396
+ var RegExpCreator = function () {
397
+ function RegExpCreator(options) {
398
+ classCallCheck(this, RegExpCreator);
399
+
400
+ this.opt = _extends({}, {
401
+ 'diacritics': true,
402
+ 'synonyms': {},
403
+ 'accuracy': 'partially',
404
+ 'caseSensitive': false,
405
+ 'ignoreJoiners': false,
406
+ 'ignorePunctuation': [],
407
+ 'wildcards': 'disabled'
408
+ }, options);
409
+ }
410
+
411
+ createClass(RegExpCreator, [{
412
+ key: 'create',
413
+ value: function create(str) {
414
+ if (this.opt.wildcards !== 'disabled') {
415
+ str = this.setupWildcardsRegExp(str);
416
+ }
417
+ str = this.escapeStr(str);
418
+ if (Object.keys(this.opt.synonyms).length) {
419
+ str = this.createSynonymsRegExp(str);
420
+ }
421
+ if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) {
422
+ str = this.setupIgnoreJoinersRegExp(str);
423
+ }
424
+ if (this.opt.diacritics) {
425
+ str = this.createDiacriticsRegExp(str);
426
+ }
427
+ str = this.createMergedBlanksRegExp(str);
428
+ if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) {
429
+ str = this.createJoinersRegExp(str);
430
+ }
431
+ if (this.opt.wildcards !== 'disabled') {
432
+ str = this.createWildcardsRegExp(str);
433
+ }
434
+ str = this.createAccuracyRegExp(str);
435
+ return new RegExp(str, 'gm' + (this.opt.caseSensitive ? '' : 'i'));
436
+ }
437
+ }, {
438
+ key: 'escapeStr',
439
+ value: function escapeStr(str) {
440
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
441
+ }
442
+ }, {
443
+ key: 'createSynonymsRegExp',
444
+ value: function createSynonymsRegExp(str) {
445
+ var syn = this.opt.synonyms,
446
+ sens = this.opt.caseSensitive ? '' : 'i',
447
+ joinerPlaceholder = this.opt.ignoreJoiners || this.opt.ignorePunctuation.length ? '\0' : '';
448
+ for (var index in syn) {
449
+ if (syn.hasOwnProperty(index)) {
450
+ var value = syn[index],
451
+ k1 = this.opt.wildcards !== 'disabled' ? this.setupWildcardsRegExp(index) : this.escapeStr(index),
452
+ k2 = this.opt.wildcards !== 'disabled' ? this.setupWildcardsRegExp(value) : this.escapeStr(value);
453
+ if (k1 !== '' && k2 !== '') {
454
+ str = str.replace(new RegExp('(' + this.escapeStr(k1) + '|' + this.escapeStr(k2) + ')', 'gm' + sens), joinerPlaceholder + ('(' + this.processSynonyms(k1) + '|') + (this.processSynonyms(k2) + ')') + joinerPlaceholder);
455
+ }
456
+ }
457
+ }
458
+ return str;
459
+ }
460
+ }, {
461
+ key: 'processSynonyms',
462
+ value: function processSynonyms(str) {
463
+ if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) {
464
+ str = this.setupIgnoreJoinersRegExp(str);
465
+ }
466
+ return str;
467
+ }
468
+ }, {
469
+ key: 'setupWildcardsRegExp',
470
+ value: function setupWildcardsRegExp(str) {
471
+ str = str.replace(/(?:\\)*\?/g, function (val) {
472
+ return val.charAt(0) === '\\' ? '?' : '\x01';
473
+ });
474
+ return str.replace(/(?:\\)*\*/g, function (val) {
475
+ return val.charAt(0) === '\\' ? '*' : '\x02';
476
+ });
477
+ }
478
+ }, {
479
+ key: 'createWildcardsRegExp',
480
+ value: function createWildcardsRegExp(str) {
481
+ var spaces = this.opt.wildcards === 'withSpaces';
482
+ return str.replace(/\u0001/g, spaces ? '[\\S\\s]?' : '\\S?').replace(/\u0002/g, spaces ? '[\\S\\s]*?' : '\\S*');
483
+ }
484
+ }, {
485
+ key: 'setupIgnoreJoinersRegExp',
486
+ value: function setupIgnoreJoinersRegExp(str) {
487
+ return str.replace(/[^(|)\\]/g, function (val, indx, original) {
488
+ var nextChar = original.charAt(indx + 1);
489
+ if (/[(|)\\]/.test(nextChar) || nextChar === '') {
490
+ return val;
491
+ } else {
492
+ return val + '\0';
493
+ }
494
+ });
495
+ }
496
+ }, {
497
+ key: 'createJoinersRegExp',
498
+ value: function createJoinersRegExp(str) {
499
+ var joiner = [];
500
+ var ignorePunctuation = this.opt.ignorePunctuation;
501
+ if (Array.isArray(ignorePunctuation) && ignorePunctuation.length) {
502
+ joiner.push(this.escapeStr(ignorePunctuation.join('')));
503
+ }
504
+ if (this.opt.ignoreJoiners) {
505
+ joiner.push('\\u00ad\\u200b\\u200c\\u200d');
506
+ }
507
+ return joiner.length ? str.split(/\u0000+/).join('[' + joiner.join('') + ']*') : str;
508
+ }
509
+ }, {
510
+ key: 'createDiacriticsRegExp',
511
+ value: function createDiacriticsRegExp(str) {
512
+ var sens = this.opt.caseSensitive ? '' : 'i',
513
+ 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ŽŻŹ'];
514
+ var handled = [];
515
+ str.split('').forEach(function (ch) {
516
+ dct.every(function (dct) {
517
+ if (dct.indexOf(ch) !== -1) {
518
+ if (handled.indexOf(dct) > -1) {
519
+ return false;
520
+ }
521
+ str = str.replace(new RegExp('[' + dct + ']', 'gm' + sens), '[' + dct + ']');
522
+ handled.push(dct);
523
+ }
524
+ return true;
525
+ });
526
+ });
527
+ return str;
528
+ }
529
+ }, {
530
+ key: 'createMergedBlanksRegExp',
531
+ value: function createMergedBlanksRegExp(str) {
532
+ return str.replace(/[\s]+/gmi, '[\\s]+');
533
+ }
534
+ }, {
535
+ key: 'createAccuracyRegExp',
536
+ value: function createAccuracyRegExp(str) {
537
+ var _this = this;
538
+
539
+ var chars = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~¡¿';
540
+ var acc = this.opt.accuracy,
541
+ val = typeof acc === 'string' ? acc : acc.value,
542
+ ls = typeof acc === 'string' ? [] : acc.limiters,
543
+ lsJoin = '';
544
+ ls.forEach(function (limiter) {
545
+ lsJoin += '|' + _this.escapeStr(limiter);
546
+ });
547
+ switch (val) {
548
+ case 'partially':
549
+ default:
550
+ return '()(' + str + ')';
551
+ case 'complementary':
552
+ lsJoin = '\\s' + (lsJoin ? lsJoin : this.escapeStr(chars));
553
+ return '()([^' + lsJoin + ']*' + str + '[^' + lsJoin + ']*)';
554
+ case 'exactly':
555
+ return '(^|\\s' + lsJoin + ')(' + str + ')(?=$|\\s' + lsJoin + ')';
556
+ }
557
+ }
558
+ }]);
559
+ return RegExpCreator;
560
+ }();
561
+
562
+ var Mark = function () {
563
+ function Mark(ctx) {
564
+ classCallCheck(this, Mark);
565
+
566
+ this.ctx = ctx;
567
+ this.ie = false;
568
+ var ua = window.navigator.userAgent;
569
+ if (ua.indexOf('MSIE') > -1 || ua.indexOf('Trident') > -1) {
570
+ this.ie = true;
571
+ }
572
+ }
573
+
574
+ createClass(Mark, [{
575
+ key: 'log',
576
+ value: function log(msg) {
577
+ var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'debug';
578
+
579
+ var log = this.opt.log;
580
+ if (!this.opt.debug) {
581
+ return;
582
+ }
583
+ if ((typeof log === 'undefined' ? 'undefined' : _typeof(log)) === 'object' && typeof log[level] === 'function') {
584
+ log[level]('mark.js: ' + msg);
585
+ }
586
+ }
587
+ }, {
588
+ key: 'getSeparatedKeywords',
589
+ value: function getSeparatedKeywords(sv) {
590
+ var _this = this;
591
+
592
+ var stack = [];
593
+ sv.forEach(function (kw) {
594
+ if (!_this.opt.separateWordSearch) {
595
+ if (kw.trim() && stack.indexOf(kw) === -1) {
596
+ stack.push(kw);
597
+ }
598
+ } else {
599
+ kw.split(' ').forEach(function (kwSplitted) {
600
+ if (kwSplitted.trim() && stack.indexOf(kwSplitted) === -1) {
601
+ stack.push(kwSplitted);
602
+ }
603
+ });
604
+ }
605
+ });
606
+ return {
607
+ 'keywords': stack.sort(function (a, b) {
608
+ return b.length - a.length;
609
+ }),
610
+ 'length': stack.length
611
+ };
612
+ }
613
+ }, {
614
+ key: 'isNumeric',
615
+ value: function isNumeric(value) {
616
+ return Number(parseFloat(value)) == value;
617
+ }
618
+ }, {
619
+ key: 'checkRanges',
620
+ value: function checkRanges(array) {
621
+ var _this2 = this;
622
+
623
+ if (!Array.isArray(array) || Object.prototype.toString.call(array[0]) !== '[object Object]') {
624
+ this.log('markRanges() will only accept an array of objects');
625
+ this.opt.noMatch(array);
626
+ return [];
627
+ }
628
+ var stack = [];
629
+ var last = 0;
630
+ array.sort(function (a, b) {
631
+ return a.start - b.start;
632
+ }).forEach(function (item) {
633
+ var _callNoMatchOnInvalid = _this2.callNoMatchOnInvalidRanges(item, last),
634
+ start = _callNoMatchOnInvalid.start,
635
+ end = _callNoMatchOnInvalid.end,
636
+ valid = _callNoMatchOnInvalid.valid;
637
+
638
+ if (valid) {
639
+ item.start = start;
640
+ item.length = end - start;
641
+ stack.push(item);
642
+ last = end;
643
+ }
644
+ });
645
+ return stack;
646
+ }
647
+ }, {
648
+ key: 'callNoMatchOnInvalidRanges',
649
+ value: function callNoMatchOnInvalidRanges(range, last) {
650
+ var start = void 0,
651
+ end = void 0,
652
+ valid = false;
653
+ if (range && typeof range.start !== 'undefined') {
654
+ start = parseInt(range.start, 10);
655
+ end = start + parseInt(range.length, 10);
656
+ if (this.isNumeric(range.start) && this.isNumeric(range.length) && end - last > 0 && end - start > 0) {
657
+ valid = true;
658
+ } else {
659
+ this.log('Ignoring invalid or overlapping range: ' + ('' + JSON.stringify(range)));
660
+ this.opt.noMatch(range);
661
+ }
662
+ } else {
663
+ this.log('Ignoring invalid range: ' + JSON.stringify(range));
664
+ this.opt.noMatch(range);
665
+ }
666
+ return {
667
+ start: start,
668
+ end: end,
669
+ valid: valid
670
+ };
671
+ }
672
+ }, {
673
+ key: 'checkWhitespaceRanges',
674
+ value: function checkWhitespaceRanges(range, originalLength, string) {
675
+ var end = void 0,
676
+ valid = true,
677
+ max = string.length,
678
+ offset = originalLength - max,
679
+ start = parseInt(range.start, 10) - offset;
680
+ start = start > max ? max : start;
681
+ end = start + parseInt(range.length, 10);
682
+ if (end > max) {
683
+ end = max;
684
+ this.log('End range automatically set to the max value of ' + max);
685
+ }
686
+ if (start < 0 || end - start < 0 || start > max || end > max) {
687
+ valid = false;
688
+ this.log('Invalid range: ' + JSON.stringify(range));
689
+ this.opt.noMatch(range);
690
+ } else if (string.substring(start, end).replace(/\s+/g, '') === '') {
691
+ valid = false;
692
+ this.log('Skipping whitespace only range: ' + JSON.stringify(range));
693
+ this.opt.noMatch(range);
694
+ }
695
+ return {
696
+ start: start,
697
+ end: end,
698
+ valid: valid
699
+ };
700
+ }
701
+ }, {
702
+ key: 'getTextNodes',
703
+ value: function getTextNodes(cb) {
704
+ var _this3 = this;
705
+
706
+ var val = '',
707
+ nodes = [];
708
+ this.iterator.forEachNode(NodeFilter.SHOW_TEXT, function (node) {
709
+ nodes.push({
710
+ start: val.length,
711
+ end: (val += node.textContent).length,
712
+ node: node
713
+ });
714
+ }, function (node) {
715
+ if (_this3.matchesExclude(node.parentNode)) {
716
+ return NodeFilter.FILTER_REJECT;
717
+ } else {
718
+ return NodeFilter.FILTER_ACCEPT;
719
+ }
720
+ }, function () {
721
+ cb({
722
+ value: val,
723
+ nodes: nodes
724
+ });
725
+ });
726
+ }
727
+ }, {
728
+ key: 'matchesExclude',
729
+ value: function matchesExclude(el) {
730
+ return DOMIterator.matches(el, this.opt.exclude.concat(['script', 'style', 'title', 'head', 'html']));
731
+ }
732
+ }, {
733
+ key: 'wrapRangeInTextNode',
734
+ value: function wrapRangeInTextNode(node, start, end) {
735
+ var hEl = !this.opt.element ? 'mark' : this.opt.element,
736
+ startNode = node.splitText(start),
737
+ ret = startNode.splitText(end - start);
738
+ var repl = document.createElement(hEl);
739
+ repl.setAttribute('data-markjs', 'true');
740
+ if (this.opt.className) {
741
+ repl.setAttribute('class', this.opt.className);
742
+ }
743
+ repl.textContent = startNode.textContent;
744
+ startNode.parentNode.replaceChild(repl, startNode);
745
+ return ret;
746
+ }
747
+ }, {
748
+ key: 'wrapRangeInMappedTextNode',
749
+ value: function wrapRangeInMappedTextNode(dict, start, end, filterCb, eachCb) {
750
+ var _this4 = this;
751
+
752
+ dict.nodes.every(function (n, i) {
753
+ var sibl = dict.nodes[i + 1];
754
+ if (typeof sibl === 'undefined' || sibl.start > start) {
755
+ if (!filterCb(n.node)) {
756
+ return false;
757
+ }
758
+ var s = start - n.start,
759
+ e = (end > n.end ? n.end : end) - n.start,
760
+ startStr = dict.value.substr(0, n.start),
761
+ endStr = dict.value.substr(e + n.start);
762
+ n.node = _this4.wrapRangeInTextNode(n.node, s, e);
763
+ dict.value = startStr + endStr;
764
+ dict.nodes.forEach(function (k, j) {
765
+ if (j >= i) {
766
+ if (dict.nodes[j].start > 0 && j !== i) {
767
+ dict.nodes[j].start -= e;
768
+ }
769
+ dict.nodes[j].end -= e;
770
+ }
771
+ });
772
+ end -= e;
773
+ eachCb(n.node.previousSibling, n.start);
774
+ if (end > n.end) {
775
+ start = n.end;
776
+ } else {
777
+ return false;
778
+ }
779
+ }
780
+ return true;
781
+ });
782
+ }
783
+ }, {
784
+ key: 'wrapGroups',
785
+ value: function wrapGroups(node, pos, len, eachCb) {
786
+ node = this.wrapRangeInTextNode(node, pos, pos + len);
787
+ eachCb(node.previousSibling);
788
+ return node;
789
+ }
790
+ }, {
791
+ key: 'separateGroups',
792
+ value: function separateGroups(node, match, matchIdx, filterCb, eachCb) {
793
+ var matchLen = match.length;
794
+ for (var i = 1; i < matchLen; i++) {
795
+ var pos = node.textContent.indexOf(match[i]);
796
+ if (match[i] && pos > -1 && filterCb(match[i], node)) {
797
+ node = this.wrapGroups(node, pos, match[i].length, eachCb);
798
+ }
799
+ }
800
+ return node;
801
+ }
802
+ }, {
803
+ key: 'wrapMatches',
804
+ value: function wrapMatches(regex, ignoreGroups, filterCb, eachCb, endCb) {
805
+ var _this5 = this;
806
+
807
+ var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1;
808
+ this.getTextNodes(function (dict) {
809
+ dict.nodes.forEach(function (node) {
810
+ node = node.node;
811
+ var match = void 0;
812
+ while ((match = regex.exec(node.textContent)) !== null && match[matchIdx] !== '') {
813
+ if (_this5.opt.separateGroups) {
814
+ node = _this5.separateGroups(node, match, matchIdx, filterCb, eachCb);
815
+ } else {
816
+ if (!filterCb(match[matchIdx], node)) {
817
+ continue;
818
+ }
819
+ var pos = match.index;
820
+ if (matchIdx !== 0) {
821
+ for (var i = 1; i < matchIdx; i++) {
822
+ pos += match[i].length;
823
+ }
824
+ }
825
+ node = _this5.wrapGroups(node, pos, match[matchIdx].length, eachCb);
826
+ }
827
+ regex.lastIndex = 0;
828
+ }
829
+ });
830
+ endCb();
831
+ });
832
+ }
833
+ }, {
834
+ key: 'wrapMatchesAcrossElements',
835
+ value: function wrapMatchesAcrossElements(regex, ignoreGroups, filterCb, eachCb, endCb) {
836
+ var _this6 = this;
837
+
838
+ var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1;
839
+ this.getTextNodes(function (dict) {
840
+ var match = void 0;
841
+ while ((match = regex.exec(dict.value)) !== null && match[matchIdx] !== '') {
842
+ var start = match.index;
843
+ if (matchIdx !== 0) {
844
+ for (var i = 1; i < matchIdx; i++) {
845
+ start += match[i].length;
846
+ }
847
+ }
848
+ var end = start + match[matchIdx].length;
849
+ _this6.wrapRangeInMappedTextNode(dict, start, end, function (node) {
850
+ return filterCb(match[matchIdx], node);
851
+ }, function (node, lastIndex) {
852
+ regex.lastIndex = lastIndex;
853
+ eachCb(node);
854
+ });
855
+ }
856
+ endCb();
857
+ });
858
+ }
859
+ }, {
860
+ key: 'wrapRangeFromIndex',
861
+ value: function wrapRangeFromIndex(ranges, filterCb, eachCb, endCb) {
862
+ var _this7 = this;
863
+
864
+ this.getTextNodes(function (dict) {
865
+ var originalLength = dict.value.length;
866
+ ranges.forEach(function (range, counter) {
867
+ var _checkWhitespaceRange = _this7.checkWhitespaceRanges(range, originalLength, dict.value),
868
+ start = _checkWhitespaceRange.start,
869
+ end = _checkWhitespaceRange.end,
870
+ valid = _checkWhitespaceRange.valid;
871
+
872
+ if (valid) {
873
+ _this7.wrapRangeInMappedTextNode(dict, start, end, function (node) {
874
+ return filterCb(node, range, dict.value.substring(start, end), counter);
875
+ }, function (node) {
876
+ eachCb(node, range);
877
+ });
878
+ }
879
+ });
880
+ endCb();
881
+ });
882
+ }
883
+ }, {
884
+ key: 'unwrapMatches',
885
+ value: function unwrapMatches(node) {
886
+ var parent = node.parentNode;
887
+ var docFrag = document.createDocumentFragment();
888
+ while (node.firstChild) {
889
+ docFrag.appendChild(node.removeChild(node.firstChild));
890
+ }
891
+ parent.replaceChild(docFrag, node);
892
+ if (!this.ie) {
893
+ parent.normalize();
894
+ } else {
895
+ this.normalizeTextNode(parent);
896
+ }
897
+ }
898
+ }, {
899
+ key: 'normalizeTextNode',
900
+ value: function normalizeTextNode(node) {
901
+ if (!node) {
902
+ return;
903
+ }
904
+ if (node.nodeType === 3) {
905
+ while (node.nextSibling && node.nextSibling.nodeType === 3) {
906
+ node.nodeValue += node.nextSibling.nodeValue;
907
+ node.parentNode.removeChild(node.nextSibling);
908
+ }
909
+ } else {
910
+ this.normalizeTextNode(node.firstChild);
911
+ }
912
+ this.normalizeTextNode(node.nextSibling);
913
+ }
914
+ }, {
915
+ key: 'markRegExp',
916
+ value: function markRegExp(regexp, opt) {
917
+ var _this8 = this;
918
+
919
+ this.opt = opt;
920
+ this.log('Searching with expression "' + regexp + '"');
921
+ var totalMatches = 0,
922
+ fn = 'wrapMatches';
923
+ var eachCb = function eachCb(element) {
924
+ totalMatches++;
925
+ _this8.opt.each(element);
926
+ };
927
+ if (this.opt.acrossElements) {
928
+ fn = 'wrapMatchesAcrossElements';
929
+ }
930
+ this[fn](regexp, this.opt.ignoreGroups, function (match, node) {
931
+ return _this8.opt.filter(node, match, totalMatches);
932
+ }, eachCb, function () {
933
+ if (totalMatches === 0) {
934
+ _this8.opt.noMatch(regexp);
935
+ }
936
+ _this8.opt.done(totalMatches);
937
+ });
938
+ }
939
+ }, {
940
+ key: 'mark',
941
+ value: function mark(sv, opt) {
942
+ var _this9 = this;
943
+
944
+ this.opt = opt;
945
+ var totalMatches = 0,
946
+ fn = 'wrapMatches';
947
+
948
+ var _getSeparatedKeywords = this.getSeparatedKeywords(typeof sv === 'string' ? [sv] : sv),
949
+ kwArr = _getSeparatedKeywords.keywords,
950
+ kwArrLen = _getSeparatedKeywords.length,
951
+ handler = function handler(kw) {
952
+ var regex = new RegExpCreator(_this9.opt).create(kw);
953
+ var matches = 0;
954
+ _this9.log('Searching with expression "' + regex + '"');
955
+ _this9[fn](regex, 1, function (term, node) {
956
+ return _this9.opt.filter(node, kw, totalMatches, matches);
957
+ }, function (element) {
958
+ matches++;
959
+ totalMatches++;
960
+ _this9.opt.each(element);
961
+ }, function () {
962
+ if (matches === 0) {
963
+ _this9.opt.noMatch(kw);
964
+ }
965
+ if (kwArr[kwArrLen - 1] === kw) {
966
+ _this9.opt.done(totalMatches);
967
+ } else {
968
+ handler(kwArr[kwArr.indexOf(kw) + 1]);
969
+ }
970
+ });
971
+ };
972
+
973
+ if (this.opt.acrossElements) {
974
+ fn = 'wrapMatchesAcrossElements';
975
+ }
976
+ if (kwArrLen === 0) {
977
+ this.opt.done(totalMatches);
978
+ } else {
979
+ handler(kwArr[0]);
980
+ }
981
+ }
982
+ }, {
983
+ key: 'markRanges',
984
+ value: function markRanges(rawRanges, opt) {
985
+ var _this10 = this;
986
+
987
+ this.opt = opt;
988
+ var totalMatches = 0,
989
+ ranges = this.checkRanges(rawRanges);
990
+ if (ranges && ranges.length) {
991
+ this.log('Starting to mark with the following ranges: ' + JSON.stringify(ranges));
992
+ this.wrapRangeFromIndex(ranges, function (node, range, match, counter) {
993
+ return _this10.opt.filter(node, range, match, counter);
994
+ }, function (element, range) {
995
+ totalMatches++;
996
+ _this10.opt.each(element, range);
997
+ }, function () {
998
+ _this10.opt.done(totalMatches);
999
+ });
1000
+ } else {
1001
+ this.opt.done(totalMatches);
1002
+ }
1003
+ }
1004
+ }, {
1005
+ key: 'unmark',
1006
+ value: function unmark(opt) {
1007
+ var _this11 = this;
1008
+
1009
+ this.opt = opt;
1010
+ var sel = this.opt.element ? this.opt.element : '*';
1011
+ sel += '[data-markjs]';
1012
+ if (this.opt.className) {
1013
+ sel += '.' + this.opt.className;
1014
+ }
1015
+ this.log('Removal selector "' + sel + '"');
1016
+ this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT, function (node) {
1017
+ _this11.unwrapMatches(node);
1018
+ }, function (node) {
1019
+ var matchesSel = DOMIterator.matches(node, sel),
1020
+ matchesExclude = _this11.matchesExclude(node);
1021
+ if (!matchesSel || matchesExclude) {
1022
+ return NodeFilter.FILTER_REJECT;
1023
+ } else {
1024
+ return NodeFilter.FILTER_ACCEPT;
1025
+ }
1026
+ }, this.opt.done);
1027
+ }
1028
+ }, {
1029
+ key: 'opt',
1030
+ set: function set$$1(val) {
1031
+ this._opt = _extends({}, {
1032
+ 'element': '',
1033
+ 'className': '',
1034
+ 'exclude': [],
1035
+ 'iframes': false,
1036
+ 'iframesTimeout': 5000,
1037
+ 'separateWordSearch': true,
1038
+ 'acrossElements': false,
1039
+ 'ignoreGroups': 0,
1040
+ 'each': function each() {},
1041
+ 'noMatch': function noMatch() {},
1042
+ 'filter': function filter() {
1043
+ return true;
1044
+ },
1045
+ 'done': function done() {},
1046
+ 'debug': false,
1047
+ 'log': window.console
1048
+ }, val);
1049
+ },
1050
+ get: function get$$1() {
1051
+ return this._opt;
1052
+ }
1053
+ }, {
1054
+ key: 'iterator',
1055
+ get: function get$$1() {
1056
+ return new DOMIterator(this.ctx, this.opt.iframes, this.opt.exclude, this.opt.iframesTimeout);
1057
+ }
1058
+ }]);
1059
+ return Mark;
1060
+ }();
1061
+
1062
+ $.fn.mark = function (sv, opt) {
1063
+ new Mark(this.get()).mark(sv, opt);
1064
+ return this;
1065
+ };
1066
+ $.fn.markRegExp = function (regexp, opt) {
1067
+ new Mark(this.get()).markRegExp(regexp, opt);
1068
+ return this;
1069
+ };
1070
+ $.fn.markRanges = function (ranges, opt) {
1071
+ new Mark(this.get()).markRanges(ranges, opt);
1072
+ return this;
1073
+ };
1074
+ $.fn.unmark = function (opt) {
1075
+ new Mark(this.get()).unmark(opt);
1076
+ return this;
1077
+ };
1078
+
1079
+ return $;
1080
+
1081
+ })));