opendoc-theme 2.0.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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +43 -0
  4. data/_includes/directory.html +95 -0
  5. data/_includes/document-title.txt +58 -0
  6. data/_includes/toc.html +107 -0
  7. data/_includes/toolbar.html +53 -0
  8. data/_includes/welcome.html +5 -0
  9. data/_layouts/default.html +147 -0
  10. data/_layouts/home.html +4 -0
  11. data/_layouts/iframe.html +13 -0
  12. data/_layouts/page.html +4 -0
  13. data/_layouts/print.html +27 -0
  14. data/_sass/_base.scss +381 -0
  15. data/_sass/_constants.scss +87 -0
  16. data/_sass/_iframe.scss +7 -0
  17. data/_sass/_layout.scss +419 -0
  18. data/_sass/_nav.scss +592 -0
  19. data/_sass/_print.scss +43 -0
  20. data/_sass/_syntax-highlighting.scss +61 -0
  21. data/_sass/_toolbar.scss +372 -0
  22. data/_sass/_welcome.scss +41 -0
  23. data/assets/export.md +30 -0
  24. data/assets/images/chevron-up-white.svg +1 -0
  25. data/assets/images/chevron-up.svg +1 -0
  26. data/assets/images/close.svg +17 -0
  27. data/assets/images/favicon.ico +0 -0
  28. data/assets/images/feedback-hover.svg +3 -0
  29. data/assets/images/feedback-mobile.svg +1 -0
  30. data/assets/images/feedback.svg +1 -0
  31. data/assets/images/github-hover.svg +3 -0
  32. data/assets/images/github.svg +1 -0
  33. data/assets/images/home.svg +14 -0
  34. data/assets/images/index-img.png +0 -0
  35. data/assets/images/logo.png +0 -0
  36. data/assets/images/menu.svg +1 -0
  37. data/assets/images/opendoc-logo-full.svg +10 -0
  38. data/assets/images/pdf-hover.svg +11 -0
  39. data/assets/images/pdf.svg +9 -0
  40. data/assets/images/search-icon-dark.svg +19 -0
  41. data/assets/images/search-icon-white.svg +12 -0
  42. data/assets/images/share.svg +1 -0
  43. data/assets/images/sidebar-hover.svg +3 -0
  44. data/assets/images/sidebar.svg +1 -0
  45. data/assets/images/vertical-dots.svg +1 -0
  46. data/assets/images/x-mobile.svg +1 -0
  47. data/assets/index.html +5 -0
  48. data/assets/js/banner.js +20 -0
  49. data/assets/js/google_analytics.js +11 -0
  50. data/assets/js/header.js +31 -0
  51. data/assets/js/helpers.js +24 -0
  52. data/assets/js/lunr.min.js +6 -0
  53. data/assets/js/navigation.js +202 -0
  54. data/assets/js/page-index.js +57 -0
  55. data/assets/js/pqueue.js +373 -0
  56. data/assets/js/pre-loader.js +43 -0
  57. data/assets/js/search.js +580 -0
  58. data/assets/js/toolbar.js +130 -0
  59. data/assets/siteIndex.json +56 -0
  60. data/assets/startup/build.sh +18 -0
  61. data/assets/startup/docprint.html +20 -0
  62. data/assets/startup/pdf-gen.js +309 -0
  63. data/assets/startup/prebuild-lunr-index.js +52 -0
  64. data/assets/styles/main.scss +13 -0
  65. data/assets/styles/normalize.css +427 -0
  66. data/assets/vendor/babel-polyfill.min.js +3 -0
  67. data/assets/vendor/dom4.js +2 -0
  68. data/assets/vendor/fetch.umd.js +531 -0
  69. data/assets/vendor/headroom.min.js +7 -0
  70. data/assets/vendor/jump.min.js +2 -0
  71. data/assets/vendor/mark.min.js +7 -0
  72. data/assets/vendor/popper.min.js +5 -0
  73. data/assets/vendor/web-share-shim.bundle.min.js +2 -0
  74. metadata +158 -0
@@ -0,0 +1,580 @@
1
+ ---
2
+ ---
3
+ (function () {
4
+ // Search Box Element
5
+ // =============================================================================
6
+ var siteSearchElement = document.getElementsByClassName('search-box')[0]
7
+ var searchBoxElement = document.getElementById('search-box')
8
+ var clearButton = document.getElementsByClassName('clear-button')[0]
9
+ var main = document.getElementsByTagName('main')[0]
10
+ var searchFilter = document.getElementsByClassName('search-filter')[0]
11
+ var searchResults = document.getElementsByClassName('search-results')[0]
12
+
13
+ searchBoxElement.oninput = function (event) {
14
+ if (searchBoxElement.value && searchBoxElement.value.trim().length > 0) {
15
+ siteSearchElement.classList.add('filled')
16
+ onSearchChangeDebounced()
17
+ } else {
18
+ siteSearchElement.classList.remove('filled')
19
+ onSearchChange()
20
+ }
21
+ }
22
+
23
+ searchBoxElement.onfocus = function () {
24
+ siteSearchElement.classList.add('focused')
25
+ if (siteSearchElement.classList.contains('filled')) {
26
+ searchResults.classList.add('visible')
27
+ }
28
+ }
29
+
30
+ searchBoxElement.onblur = function() {
31
+ siteSearchElement.classList.remove('focused')
32
+ }
33
+
34
+ document.body.addEventListener('click', function (event) {
35
+ var target = event.target
36
+ if (target.id !== 'search-box' && !target.classList.contains('search-btn') && !target.parentNode.classList.contains('search-btn')) {
37
+ searchResults.classList.remove('visible')
38
+ }
39
+ })
40
+
41
+ clearButton.onclick = function () {
42
+ searchBoxElement.value = ''
43
+ searchBoxElement.dispatchEvent(new Event('input', {
44
+ 'bubbles': true,
45
+ 'cancelable': true
46
+ }))
47
+ }
48
+
49
+ // Assign search endpoint based on env config
50
+ // ===========================================================================
51
+ var endpoint = null
52
+ var env = '{{ jekyll.environment }}'
53
+ var elasticSearchIndex = '{{site.github.owner_name}}-{{site.github.repository_name}}'
54
+
55
+ if (env === 'production') {
56
+ endpoint = '{{ site.server_PROD | append: '/' }}' + elasticSearchIndex
57
+ } else {
58
+ // Allow overriding of search index in dev env
59
+ var configElasticSearchIndex = '{{site.elastic_search_index}}'
60
+ if (configElasticSearchIndex) {
61
+ elasticSearchIndex = configElasticSearchIndex
62
+ }
63
+ endpoint = '{{ site.server_DEV | append: '/' }}' + elasticSearchIndex
64
+ }
65
+
66
+ var search_endpoint = endpoint + '/search'
67
+
68
+
69
+ // Global Variables
70
+ // =============================================================================
71
+
72
+ var wordsToHighlight = []
73
+ var sectionIndex = {}
74
+ var minQueryLength = 3
75
+ var lunrIndex = null
76
+ // Begin Lunr Indexing
77
+ // =============================================================================
78
+ function getLunrIndex() {
79
+ return fetch('/assets/lunrIndex.json')
80
+ .then(function (res) {
81
+ return res.json()
82
+ })
83
+ .then(function (json) {
84
+ lunrIndex = lunr.Index.load(json.index)
85
+ lunrIndex.pipeline.remove(lunr.stemmer)
86
+ sectionIndex = json.sectionIndex
87
+ })
88
+ .catch(function (err) {
89
+ console.error('Fetch failed to read the Lunr index: ' + err)
90
+ })
91
+ }
92
+
93
+ // Load Lunr Index if set
94
+ // ============================================================================
95
+ var searchSetOffline = "{{ site.offline_search_only }}" === "true" || false
96
+
97
+ if (searchSetOffline) {
98
+ getLunrIndex()
99
+ }
100
+
101
+ // Search
102
+ // =============================================================================
103
+ // Helper function to translate lunr search results
104
+ // Returns a simple { title, content, link } array
105
+ var snippetSpace = 40
106
+ var maxSnippets = 4
107
+ var maxResults = 10
108
+ var translateLunrResults = function (allLunrResults) {
109
+ var lunrResults = allLunrResults.slice(0, maxResults)
110
+ return lunrResults.map(function (result) {
111
+ var matchedDocument = sectionIndex[result.ref]
112
+ var contentSnippets = []
113
+ var titleSnippets = []
114
+ var snippetsRangesByFields = {}
115
+ // Loop over matching terms
116
+ var rangesByFields = {}
117
+ // Group ranges according to field type(text / title)
118
+ for (var term in result.matchData.metadata) {
119
+ // To highlight the main body later
120
+ wordsToHighlight.push(term)
121
+ var fields = result.matchData.metadata[term]
122
+ for (var field in fields) {
123
+ positions = fields[field].position
124
+ rangesByFields[field] = rangesByFields[field] ? rangesByFields[field].concat(positions) : positions
125
+ }
126
+ }
127
+ var snippetCount = 0
128
+ // Sort according to ascending snippet range
129
+ for (var field in rangesByFields) {
130
+ var ranges = rangesByFields[field]
131
+ .map(function (a) {
132
+ return [a[0] - snippetSpace, a[0] + a[1] + snippetSpace, a[0], a[0] + a[1]]
133
+ })
134
+ .sort(function (a, b) {
135
+ return a[0] - b[0]
136
+ })
137
+ // Merge contiguous ranges
138
+ var startIndex = ranges[0][0]
139
+ var endIndex = ranges[0][1]
140
+ var mergedRanges = []
141
+ var highlightRanges = []
142
+ for (rangeIndex in ranges) {
143
+ var range = ranges[rangeIndex]
144
+ snippetCount++
145
+ if (range[0] <= endIndex) {
146
+ endIndex = Math.max(range[1], endIndex)
147
+ highlightRanges = highlightRanges.concat([range[2], range[3]])
148
+ } else {
149
+ mergedRanges.push([startIndex].concat(highlightRanges).concat([endIndex]))
150
+ startIndex = range[0]
151
+ endIndex = range[1]
152
+ highlightRanges = [range[2], range[3]]
153
+ }
154
+ if (snippetCount >= maxSnippets) {
155
+ mergedRanges.push([startIndex].concat(highlightRanges).concat([endIndex]))
156
+ snippetsRangesByFields[field] = mergedRanges
157
+ break
158
+ }
159
+ if (+rangeIndex === ranges.length - 1) {
160
+ if (snippetCount + 1 < maxSnippets) {
161
+ snippetCount++
162
+ }
163
+ mergedRanges.push([startIndex].concat(highlightRanges).concat([endIndex]))
164
+ snippetsRangesByFields[field] = mergedRanges
165
+ if (snippetCount >= maxSnippets) {
166
+ break
167
+ }
168
+ }
169
+ }
170
+ }
171
+ // Extract snippets and add highlights to search results
172
+ for (var field in snippetsRangesByFields) {
173
+ positions = snippetsRangesByFields[field]
174
+ positions.forEach(function (position) {
175
+ matchedText = matchedDocument[field]
176
+ var snippet = ''
177
+ // If start of matched text dont use ellipsis
178
+ if (position[0] > 0) {
179
+ snippet += '...'
180
+ }
181
+ snippet += matchedText.substring(position[0], position[1])
182
+ for (var i = 1; i <= position.length - 2; i++) {
183
+ if (i % 2 == 1) {
184
+ snippet += '<mark>'
185
+ } else {
186
+ snippet += '</mark>'
187
+ }
188
+ snippet += matchedText.substring(position[i], position[i + 1])
189
+ }
190
+ if (field === 'title') {
191
+ titleSnippets.push(snippet)
192
+ } else {
193
+ snippet += '...'
194
+ contentSnippets.push(snippet)
195
+ }
196
+ })
197
+ }
198
+ var joinHighlights = function (str) {
199
+ if (str) {
200
+ return str.replace(/<\/mark> <mark>/g, ' ')
201
+ }
202
+ }
203
+ // Build a simple flat object per lunr result
204
+ return {
205
+ title: joinHighlights(titleSnippets.length === 0 ? matchedDocument.title: titleSnippets.join(' ')),
206
+ documentTitle: joinHighlights(matchedDocument.documentTitle),
207
+ content: joinHighlights(contentSnippets.join(' ')),
208
+ url: matchedDocument.url
209
+ }
210
+ })
211
+ }
212
+
213
+ // Displays the search results in HTML
214
+ // Takes an array of objects with "title" and "content" properties
215
+ var renderSearchResultsFromLunr = function (searchResults) {
216
+ var container = document.getElementsByClassName('search-results')[0]
217
+ container.scrollTop = 0
218
+ container.innerHTML = ''
219
+ if (!searchResults || searchResults.length === 0) {
220
+ var error = generateErrorHTML()
221
+ container.append(error)
222
+ } else {
223
+ searchResults.forEach(function (result, i) {
224
+ var element = generateResultHTML(result, i)
225
+ container.appendChild(element)
226
+ })
227
+ }
228
+ }
229
+
230
+ var renderSearchResultsFromServer = function (searchResults) {
231
+ var container = document.getElementsByClassName('search-results')[0]
232
+ container.scrollTop = 0
233
+ container.innerHTML = ''
234
+ if (typeof searchResults.hits === 'undefined') {
235
+ var error = document.createElement('p')
236
+ error.classList.add('not-found')
237
+ error.innerHTML = searchResults
238
+ container.appendChild(error)
239
+ // Check if there are hits and max_score is more than 0
240
+ // Max score is checked as well as filter will always return something
241
+ } else if (searchResults.hits.hits.length === 0 || searchResults.hits['max_score'] === 0) {
242
+ var error = generateErrorHTML()
243
+ container.appendChild(error)
244
+ } else {
245
+ searchResults.hits.hits.forEach(function (result, i) {
246
+ if (result._score) {
247
+ var formatted = formatResult(result, i)
248
+ var element = generateResultHTML(formatted)
249
+ container.appendChild(element)
250
+ }
251
+ });
252
+ highlightBody()
253
+ }
254
+ }
255
+
256
+ var generateErrorHTML = function () {
257
+ var error = document.createElement('p')
258
+ error.innerHTML = 'Results matching your query were not found.'
259
+ error.classList.add('not-found')
260
+ return error
261
+ }
262
+
263
+ var generateResultHTML = function (result, i) {
264
+ var element = document.createElement('a')
265
+ element.className = 'search-link nav-link'
266
+ var urlParts = ('{{site.baseurl}}' + result.url).split('/')
267
+ urlParts = urlParts.filter(function (part) {
268
+ return part !== ''
269
+ })
270
+ element.href = '/' + urlParts.join('/')
271
+ var searchResult = document.createElement('div')
272
+ var searchTitle = document.createElement('p')
273
+ searchTitle.className = 'search-title'
274
+ searchTitle.innerHTML = result.documentTitle || '{{ site.title }}'
275
+ searchResult.appendChild(searchTitle)
276
+ var searchSubtitle = document.createElement('p')
277
+ searchSubtitle.className = 'search-subtitle'
278
+ searchSubtitle.innerHTML = result.title
279
+ searchResult.appendChild(searchSubtitle)
280
+ var searchContent = document.createElement('p')
281
+ searchContent.className = 'search-content'
282
+ searchContent.innerHTML = result.content
283
+ searchResult.appendChild(searchContent)
284
+ element.onmouseup = function() {
285
+ searchResults.classList.remove('visible')
286
+ }
287
+ element.appendChild(searchResult)
288
+ return element
289
+ }
290
+
291
+ formatResult = function (result) {
292
+ var content = null
293
+ var title = result._source.title
294
+ var url = result._source.url;
295
+ var documentTitle = result._source.documentTitle;
296
+ var regex = /<mark>(.*?)<\/mark>/g
297
+ var joinHighlights = function (str) {
298
+ if (str) {
299
+ return str.replace(/<\/mark> <mark>/g, ' ')
300
+ }
301
+ }
302
+ if (result.highlight) {
303
+ ['title', 'content'].forEach(function (field) {
304
+ var curr, match, term;
305
+ if (result.highlight[field]) {
306
+ var curr = result.highlight[field].join('...')
307
+ // trimLeft not supported in IE
308
+ var curr = curr.replace(/^\s+/, "")
309
+ var curr = joinHighlights(curr)
310
+ var match = true
311
+ while (match) {
312
+ match = regex.exec(curr)
313
+ if (match) {
314
+ var term = match[1].toLowerCase()
315
+ if ((wordsToHighlight.indexOf(term)) < 0) {
316
+ wordsToHighlight.push(term)
317
+ }
318
+ }
319
+ }
320
+ }
321
+ })
322
+ if (result.highlight.content) {
323
+ content = joinHighlights(result.highlight.content.slice(0, Math.min(3, result.highlight.content.length)).join('...'))
324
+ }
325
+ if (result.highlight.title) {
326
+ title = joinHighlights(result.highlight.title[0])
327
+ }
328
+ }
329
+ return {
330
+ url: url,
331
+ content: content ? '...' + content + '...' : '',
332
+ title: title,
333
+ documentTitle: documentTitle
334
+ }
335
+ }
336
+
337
+ var debounce = function (func, threshold, execAsap) {
338
+ var timeout = null;
339
+ return function () {
340
+ var args = 1 <= arguments.length ? slice.call(arguments, 0) : []
341
+ obj = this
342
+ var delayed = function () {
343
+ if (!execAsap) {
344
+ func.apply(obj, args)
345
+ }
346
+ timeout = null
347
+ }
348
+ if (timeout) {
349
+ clearTimeout(timeout)
350
+ } else if (execAsap) {
351
+ func.apply(obj, args)
352
+ }
353
+ timeout = setTimeout(delayed, threshold || 100)
354
+ }
355
+ }
356
+
357
+
358
+ var createEsQuery = function (queryStr) {
359
+ var source = ['title', 'url', 'documentTitle']
360
+ var title_automcomplete_q = {
361
+ 'match_phrase_prefix': {
362
+ 'title': {
363
+ 'query': queryStr,
364
+ 'max_expansions': 20,
365
+ 'boost': 100,
366
+ 'slop': 10
367
+ }
368
+ }
369
+ }
370
+ var content_automcomplete_q = {
371
+ 'match_phrase_prefix': {
372
+ 'content': {
373
+ 'query': queryStr,
374
+ 'max_expansions': 20,
375
+ 'boost': 60,
376
+ 'slop': 10
377
+ }
378
+ }
379
+ }
380
+ var title_keyword_q = {
381
+ 'match': {
382
+ 'title': {
383
+ 'query': queryStr,
384
+ 'fuzziness': 'AUTO',
385
+ 'max_expansions': 10,
386
+ 'boost': 20,
387
+ 'analyzer': 'stop'
388
+ }
389
+ }
390
+ }
391
+ var content_keyword_q = {
392
+ 'match': {
393
+ 'content': {
394
+ 'query': queryStr,
395
+ 'fuzziness': 'AUTO',
396
+ 'max_expansions': 10,
397
+ 'analyzer': 'stop'
398
+ }
399
+ }
400
+ }
401
+
402
+ var bool_q = {
403
+ 'bool': {
404
+ 'should': [title_automcomplete_q, content_automcomplete_q, title_keyword_q, content_keyword_q],
405
+ }
406
+ }
407
+
408
+ // If document filter is present
409
+ var page = pageIndex[window.location.pathname]
410
+ if (!searchFilter.classList.contains('hidden') && page && page.documentInfo[0]) {
411
+ // documentId is the alphanumeric and lowercase version of document title
412
+ // used as a keyword filter to search within the document
413
+ var documentId = page.documentInfo[0].replace(/[^\w]/g, '').toLowerCase()
414
+ var filter_by_document = {
415
+ 'term': {
416
+ 'documentId': documentId
417
+ }
418
+ }
419
+ bool_q.bool.filter = filter_by_document
420
+ }
421
+
422
+ var highlight = {}
423
+ highlight.require_field_match = false
424
+ highlight.fields = {}
425
+ highlight.fields['content'] = {
426
+ 'fragment_size': 80,
427
+ 'number_of_fragments': 6,
428
+ 'pre_tags': ['<mark>'],
429
+ 'post_tags': ['</mark>']
430
+ }
431
+ highlight.fields['title'] = {
432
+ 'fragment_size': 80,
433
+ 'number_of_fragments': 6,
434
+ 'pre_tags': ['<mark>'],
435
+ 'post_tags': ['</mark>']
436
+ }
437
+ return {
438
+ '_source': source,
439
+ 'query': bool_q,
440
+ 'highlight': highlight
441
+ }
442
+ }
443
+
444
+ // Call the API
445
+ esSearch = function (query) {
446
+ var esQuery = createEsQuery(query)
447
+ fetch(search_endpoint, {
448
+ method: 'POST',
449
+ headers: {
450
+ 'Content-Type': 'application/json'
451
+ },
452
+ body: JSON.stringify(esQuery)
453
+ })
454
+ .then(checkStatus)
455
+ .then(parseJSON)
456
+ .then(function (data) {
457
+ renderSearchResultsFromServer(data.body)
458
+ })
459
+ .catch(function (err) {
460
+ console.error(err)
461
+ renderSearchResultsFromServer('Failed to fetch search results')
462
+ })
463
+ }
464
+
465
+ var lunrSearch = function (query) {
466
+ // Add wildcard before and after
467
+ var queryTerm = refineLunrSearchQuery(query)
468
+ if (lunrIndex !== null) {
469
+ var lunrResults = lunrIndex.search(queryTerm)
470
+ var results = translateLunrResults(lunrResults)
471
+ highlightBody()
472
+ renderSearchResultsFromLunr(results)
473
+ }
474
+ }
475
+
476
+ var refineLunrSearchQuery = function(query) {
477
+ FUZZY_FACTOR = 4 // range: 1 to INF. Lower is fuzzier *relative to term length*.
478
+ var addFuzzyOperator = function(term, fuzziness) {
479
+ return term + '~' +
480
+ Math.floor(term.length / Math.max(1, fuzziness)).toString()
481
+ }
482
+ var stringIsLettersOnly = function(str) {
483
+ return /^[a-zA-Z]+$/.test(str)
484
+ }
485
+
486
+ var terms = query.split(' ')
487
+ terms = terms.map(function(term) {
488
+ if (stringIsLettersOnly(term)) {
489
+ return addFuzzyOperator(term, FUZZY_FACTOR)
490
+ }
491
+ return term
492
+ })
493
+ return terms.join(' ')
494
+ }
495
+
496
+
497
+ var onSearchChange = function () {
498
+ var query = searchBoxElement.value.trim()
499
+ // Clear highlights
500
+ wordsToHighlight = []
501
+ if (query.length < minQueryLength) {
502
+ searchResults.classList.remove('visible')
503
+ highlightBody()
504
+ return
505
+ }
506
+ searchResults.classList.add('visible')
507
+
508
+ if (searchSetOffline) {
509
+ lunrSearch(query)
510
+ } else {
511
+ esSearch(query)
512
+ if (env === 'production' && window.ga) {
513
+ window.ga('send', 'pageview', '/search?query=' + encodeURIComponent(query))
514
+ }
515
+ }
516
+ }
517
+
518
+ var onSearchChangeDebounced = debounce(onSearchChange, 500, false)
519
+
520
+ var isBackspaceFirstPress = true
521
+ var isBackspacePressedOnEmpty = false
522
+ // Detect that backspace is not part of longpress
523
+ searchBoxElement.onkeydown = function (e) {
524
+ searchResults.classList.remove('hidden')
525
+ if (isBackspaceFirstPress && e.keyCode === 8) {
526
+ isBackspaceFirstPress = false
527
+ if (searchBoxElement.value === '') {
528
+ isBackspacePressedOnEmpty = true
529
+ }
530
+ }
531
+ }
532
+
533
+ clearSearchFilter = function () {
534
+ searchFilter.classList.add('hidden')
535
+ }
536
+
537
+ searchFilter.onclick = clearSearchFilter
538
+
539
+ searchBoxElement.onkeyup = function (e) {
540
+ // flash search results on enter
541
+ if (e.keyCode === 13) {
542
+ var container = document.getElementsByClassName('search-results')[0]
543
+ container.style.opacity = 0
544
+ return setTimeout(function () {
545
+ return container.style.opacity = 1
546
+ }, 100)
547
+ }
548
+ // Delete filter on backspace when input is empty and not part of longpress
549
+ if (e.keyCode === 8) {
550
+ isBackspaceFirstPress = true
551
+ if (searchBoxElement.value === '' && isBackspacePressedOnEmpty) {
552
+ clearSearchFilter()
553
+ isBackspacePressedOnEmpty = false
554
+ return
555
+ }
556
+ }
557
+ }
558
+
559
+
560
+ // Highlighting
561
+ // ============================================================================
562
+ window.highlightBody = function () {
563
+ // Check if Mark.js script is already imported
564
+ if (Mark) {
565
+ var instance = new Mark(main)
566
+ instance.unmark()
567
+ if (wordsToHighlight.length > 0) {
568
+ instance.mark(wordsToHighlight, {
569
+ exclude: ['h1'],
570
+ accuracy: {
571
+ value: 'exactly',
572
+ limiters: [',', '.', '(', ')', '-', '\'', '[', ']', '?', '/', '\\', ':', '*', '!', '@', '&']
573
+ },
574
+ separateWordSearch: false
575
+ })
576
+ }
577
+ }
578
+ }
579
+
580
+ })()