starterlog-theme 1.1.0 → 1.1.1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +153 -0
  3. data/README.md +107 -0
  4. data/_includes/footer.html +52 -0
  5. data/_includes/head.html +19 -0
  6. data/_includes/header.html +52 -0
  7. data/_layouts/default.html +22 -0
  8. data/_layouts/page.html +5 -0
  9. data/_layouts/post.html +5 -0
  10. data/_pages/about/index.html +84 -0
  11. data/_pages/features/index.html +88 -0
  12. data/_pages/portfolio/index.html +142 -0
  13. data/_pages/profile/index.html +37 -0
  14. data/_pages/project/index.html +85 -0
  15. data/_pages/projects/index.html +60 -0
  16. data/_pages/search/index.html +29 -0
  17. data/_pages/start/index.html +136 -0
  18. data/_pages/theme/index.html +1194 -0
  19. data/assets/fonts/FontAwesome.otf +0 -0
  20. data/assets/fonts/fontawesome-webfont.eot +0 -0
  21. data/assets/fonts/fontawesome-webfont.svg +685 -0
  22. data/assets/fonts/fontawesome-webfont.ttf +0 -0
  23. data/assets/fonts/fontawesome-webfont.woff +0 -0
  24. data/assets/fonts/fontawesome-webfont.woff2 +0 -0
  25. data/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  26. data/assets/fonts/glyphicons-halflings-regular.svg +288 -0
  27. data/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  28. data/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  29. data/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
  30. data/assets/scripts/bootstrap.js +2380 -0
  31. data/assets/scripts/fullscreensearch.js +13 -0
  32. data/assets/scripts/jquery.js +10074 -0
  33. data/assets/scripts/lunr.js +2053 -0
  34. data/assets/scripts/search.js +61 -0
  35. data/assets/styles/custom.css +118 -0
  36. data/assets/styles/font-awesome.css +2199 -0
  37. data/assets/styles/theme.css +5769 -0
  38. metadata +37 -1
@@ -0,0 +1,2053 @@
1
+ /**
2
+ * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 0.7.1
3
+ * Copyright (C) 2016 Oliver Nightingale
4
+ * @license MIT
5
+ */
6
+
7
+ ;(function(){
8
+
9
+ /**
10
+ * Convenience function for instantiating a new lunr index and configuring it
11
+ * with the default pipeline functions and the passed config function.
12
+ *
13
+ * When using this convenience function a new index will be created with the
14
+ * following functions already in the pipeline:
15
+ *
16
+ * lunr.StopWordFilter - filters out any stop words before they enter the
17
+ * index
18
+ *
19
+ * lunr.stemmer - stems the tokens before entering the index.
20
+ *
21
+ * Example:
22
+ *
23
+ * var idx = lunr(function () {
24
+ * this.field('title', 10)
25
+ * this.field('tags', 100)
26
+ * this.field('body')
27
+ *
28
+ * this.ref('cid')
29
+ *
30
+ * this.pipeline.add(function () {
31
+ * // some custom pipeline function
32
+ * })
33
+ *
34
+ * })
35
+ *
36
+ * @param {Function} config A function that will be called with the new instance
37
+ * of the lunr.Index as both its context and first parameter. It can be used to
38
+ * customize the instance of new lunr.Index.
39
+ * @namespace
40
+ * @module
41
+ * @returns {lunr.Index}
42
+ *
43
+ */
44
+ var lunr = function (config) {
45
+ var idx = new lunr.Index
46
+
47
+ idx.pipeline.add(
48
+ lunr.trimmer,
49
+ lunr.stopWordFilter,
50
+ lunr.stemmer
51
+ )
52
+
53
+ if (config) config.call(idx, idx)
54
+
55
+ return idx
56
+ }
57
+
58
+ lunr.version = "0.7.1"
59
+ /*!
60
+ * lunr.utils
61
+ * Copyright (C) 2016 Oliver Nightingale
62
+ */
63
+
64
+ /**
65
+ * A namespace containing utils for the rest of the lunr library
66
+ */
67
+ lunr.utils = {}
68
+
69
+ /**
70
+ * Print a warning message to the console.
71
+ *
72
+ * @param {String} message The message to be printed.
73
+ * @memberOf Utils
74
+ */
75
+ lunr.utils.warn = (function (global) {
76
+ return function (message) {
77
+ if (global.console && console.warn) {
78
+ console.warn(message)
79
+ }
80
+ }
81
+ })(this)
82
+
83
+ /**
84
+ * Convert an object to a string.
85
+ *
86
+ * In the case of `null` and `undefined` the function returns
87
+ * the empty string, in all other cases the result of calling
88
+ * `toString` on the passed object is returned.
89
+ *
90
+ * @param {Any} obj The object to convert to a string.
91
+ * @return {String} string representation of the passed object.
92
+ * @memberOf Utils
93
+ */
94
+ lunr.utils.asString = function (obj) {
95
+ if (obj === void 0 || obj === null) {
96
+ return ""
97
+ } else {
98
+ return obj.toString()
99
+ }
100
+ }
101
+ /*!
102
+ * lunr.EventEmitter
103
+ * Copyright (C) 2016 Oliver Nightingale
104
+ */
105
+
106
+ /**
107
+ * lunr.EventEmitter is an event emitter for lunr. It manages adding and removing event handlers and triggering events and their handlers.
108
+ *
109
+ * @constructor
110
+ */
111
+ lunr.EventEmitter = function () {
112
+ this.events = {}
113
+ }
114
+
115
+ /**
116
+ * Binds a handler function to a specific event(s).
117
+ *
118
+ * Can bind a single function to many different events in one call.
119
+ *
120
+ * @param {String} [eventName] The name(s) of events to bind this function to.
121
+ * @param {Function} fn The function to call when an event is fired.
122
+ * @memberOf EventEmitter
123
+ */
124
+ lunr.EventEmitter.prototype.addListener = function () {
125
+ var args = Array.prototype.slice.call(arguments),
126
+ fn = args.pop(),
127
+ names = args
128
+
129
+ if (typeof fn !== "function") throw new TypeError ("last argument must be a function")
130
+
131
+ names.forEach(function (name) {
132
+ if (!this.hasHandler(name)) this.events[name] = []
133
+ this.events[name].push(fn)
134
+ }, this)
135
+ }
136
+
137
+ /**
138
+ * Removes a handler function from a specific event.
139
+ *
140
+ * @param {String} eventName The name of the event to remove this function from.
141
+ * @param {Function} fn The function to remove from an event.
142
+ * @memberOf EventEmitter
143
+ */
144
+ lunr.EventEmitter.prototype.removeListener = function (name, fn) {
145
+ if (!this.hasHandler(name)) return
146
+
147
+ var fnIndex = this.events[name].indexOf(fn)
148
+ this.events[name].splice(fnIndex, 1)
149
+
150
+ if (!this.events[name].length) delete this.events[name]
151
+ }
152
+
153
+ /**
154
+ * Calls all functions bound to the given event.
155
+ *
156
+ * Additional data can be passed to the event handler as arguments to `emit`
157
+ * after the event name.
158
+ *
159
+ * @param {String} eventName The name of the event to emit.
160
+ * @memberOf EventEmitter
161
+ */
162
+ lunr.EventEmitter.prototype.emit = function (name) {
163
+ if (!this.hasHandler(name)) return
164
+
165
+ var args = Array.prototype.slice.call(arguments, 1)
166
+
167
+ this.events[name].forEach(function (fn) {
168
+ fn.apply(undefined, args)
169
+ })
170
+ }
171
+
172
+ /**
173
+ * Checks whether a handler has ever been stored against an event.
174
+ *
175
+ * @param {String} eventName The name of the event to check.
176
+ * @private
177
+ * @memberOf EventEmitter
178
+ */
179
+ lunr.EventEmitter.prototype.hasHandler = function (name) {
180
+ return name in this.events
181
+ }
182
+
183
+ /*!
184
+ * lunr.tokenizer
185
+ * Copyright (C) 2016 Oliver Nightingale
186
+ */
187
+
188
+ /**
189
+ * A function for splitting a string into tokens ready to be inserted into
190
+ * the search index. Uses `lunr.tokenizer.seperator` to split strings, change
191
+ * the value of this property to change how strings are split into tokens.
192
+ *
193
+ * @module
194
+ * @param {String} obj The string to convert into tokens
195
+ * @see lunr.tokenizer.seperator
196
+ * @returns {Array}
197
+ */
198
+ lunr.tokenizer = function (obj) {
199
+ if (!arguments.length || obj == null || obj == undefined) return []
200
+ if (Array.isArray(obj)) return obj.map(function (t) { return lunr.utils.asString(t).toLowerCase() })
201
+
202
+ return obj.toString().trim().toLowerCase().split(lunr.tokenizer.seperator)
203
+ }
204
+
205
+ /**
206
+ * The sperator used to split a string into tokens. Override this property to change the behaviour of
207
+ * `lunr.tokenizer` behaviour when tokenizing strings. By default this splits on whitespace and hyphens.
208
+ *
209
+ * @static
210
+ * @see lunr.tokenizer
211
+ */
212
+ lunr.tokenizer.seperator = /[\s\-]+/
213
+
214
+ /**
215
+ * Loads a previously serialised tokenizer.
216
+ *
217
+ * A tokenizer function to be loaded must already be registered with lunr.tokenizer.
218
+ * If the serialised tokenizer has not been registered then an error will be thrown.
219
+ *
220
+ * @param {String} label The label of the serialised tokenizer.
221
+ * @returns {Function}
222
+ * @memberOf tokenizer
223
+ */
224
+ lunr.tokenizer.load = function (label) {
225
+ var fn = this.registeredFunctions[label]
226
+
227
+ if (!fn) {
228
+ throw new Error('Cannot load un-registered function: ' + label)
229
+ }
230
+
231
+ return fn
232
+ }
233
+
234
+ lunr.tokenizer.label = 'default'
235
+
236
+ lunr.tokenizer.registeredFunctions = {
237
+ 'default': lunr.tokenizer
238
+ }
239
+
240
+ /**
241
+ * Register a tokenizer function.
242
+ *
243
+ * Functions that are used as tokenizers should be registered if they are to be used with a serialised index.
244
+ *
245
+ * Registering a function does not add it to an index, functions must still be associated with a specific index for them to be used when indexing and searching documents.
246
+ *
247
+ * @param {Function} fn The function to register.
248
+ * @param {String} label The label to register this function with
249
+ * @memberOf tokenizer
250
+ */
251
+ lunr.tokenizer.registerFunction = function (fn, label) {
252
+ if (label in this.registeredFunctions) {
253
+ lunr.utils.warn('Overwriting existing tokenizer: ' + label)
254
+ }
255
+
256
+ fn.label = label
257
+ this.registeredFunctions[label] = fn
258
+ }
259
+ /*!
260
+ * lunr.Pipeline
261
+ * Copyright (C) 2016 Oliver Nightingale
262
+ */
263
+
264
+ /**
265
+ * lunr.Pipelines maintain an ordered list of functions to be applied to all
266
+ * tokens in documents entering the search index and queries being ran against
267
+ * the index.
268
+ *
269
+ * An instance of lunr.Index created with the lunr shortcut will contain a
270
+ * pipeline with a stop word filter and an English language stemmer. Extra
271
+ * functions can be added before or after either of these functions or these
272
+ * default functions can be removed.
273
+ *
274
+ * When run the pipeline will call each function in turn, passing a token, the
275
+ * index of that token in the original list of all tokens and finally a list of
276
+ * all the original tokens.
277
+ *
278
+ * The output of functions in the pipeline will be passed to the next function
279
+ * in the pipeline. To exclude a token from entering the index the function
280
+ * should return undefined, the rest of the pipeline will not be called with
281
+ * this token.
282
+ *
283
+ * For serialisation of pipelines to work, all functions used in an instance of
284
+ * a pipeline should be registered with lunr.Pipeline. Registered functions can
285
+ * then be loaded. If trying to load a serialised pipeline that uses functions
286
+ * that are not registered an error will be thrown.
287
+ *
288
+ * If not planning on serialising the pipeline then registering pipeline functions
289
+ * is not necessary.
290
+ *
291
+ * @constructor
292
+ */
293
+ lunr.Pipeline = function () {
294
+ this._stack = []
295
+ }
296
+
297
+ lunr.Pipeline.registeredFunctions = {}
298
+
299
+ /**
300
+ * Register a function with the pipeline.
301
+ *
302
+ * Functions that are used in the pipeline should be registered if the pipeline
303
+ * needs to be serialised, or a serialised pipeline needs to be loaded.
304
+ *
305
+ * Registering a function does not add it to a pipeline, functions must still be
306
+ * added to instances of the pipeline for them to be used when running a pipeline.
307
+ *
308
+ * @param {Function} fn The function to check for.
309
+ * @param {String} label The label to register this function with
310
+ * @memberOf Pipeline
311
+ */
312
+ lunr.Pipeline.registerFunction = function (fn, label) {
313
+ if (label in this.registeredFunctions) {
314
+ lunr.utils.warn('Overwriting existing registered function: ' + label)
315
+ }
316
+
317
+ fn.label = label
318
+ lunr.Pipeline.registeredFunctions[fn.label] = fn
319
+ }
320
+
321
+ /**
322
+ * Warns if the function is not registered as a Pipeline function.
323
+ *
324
+ * @param {Function} fn The function to check for.
325
+ * @private
326
+ * @memberOf Pipeline
327
+ */
328
+ lunr.Pipeline.warnIfFunctionNotRegistered = function (fn) {
329
+ var isRegistered = fn.label && (fn.label in this.registeredFunctions)
330
+
331
+ if (!isRegistered) {
332
+ lunr.utils.warn('Function is not registered with pipeline. This may cause problems when serialising the index.\n', fn)
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Loads a previously serialised pipeline.
338
+ *
339
+ * All functions to be loaded must already be registered with lunr.Pipeline.
340
+ * If any function from the serialised data has not been registered then an
341
+ * error will be thrown.
342
+ *
343
+ * @param {Object} serialised The serialised pipeline to load.
344
+ * @returns {lunr.Pipeline}
345
+ * @memberOf Pipeline
346
+ */
347
+ lunr.Pipeline.load = function (serialised) {
348
+ var pipeline = new lunr.Pipeline
349
+
350
+ serialised.forEach(function (fnName) {
351
+ var fn = lunr.Pipeline.registeredFunctions[fnName]
352
+
353
+ if (fn) {
354
+ pipeline.add(fn)
355
+ } else {
356
+ throw new Error('Cannot load un-registered function: ' + fnName)
357
+ }
358
+ })
359
+
360
+ return pipeline
361
+ }
362
+
363
+ /**
364
+ * Adds new functions to the end of the pipeline.
365
+ *
366
+ * Logs a warning if the function has not been registered.
367
+ *
368
+ * @param {Function} functions Any number of functions to add to the pipeline.
369
+ * @memberOf Pipeline
370
+ */
371
+ lunr.Pipeline.prototype.add = function () {
372
+ var fns = Array.prototype.slice.call(arguments)
373
+
374
+ fns.forEach(function (fn) {
375
+ lunr.Pipeline.warnIfFunctionNotRegistered(fn)
376
+ this._stack.push(fn)
377
+ }, this)
378
+ }
379
+
380
+ /**
381
+ * Adds a single function after a function that already exists in the
382
+ * pipeline.
383
+ *
384
+ * Logs a warning if the function has not been registered.
385
+ *
386
+ * @param {Function} existingFn A function that already exists in the pipeline.
387
+ * @param {Function} newFn The new function to add to the pipeline.
388
+ * @memberOf Pipeline
389
+ */
390
+ lunr.Pipeline.prototype.after = function (existingFn, newFn) {
391
+ lunr.Pipeline.warnIfFunctionNotRegistered(newFn)
392
+
393
+ var pos = this._stack.indexOf(existingFn)
394
+ if (pos == -1) {
395
+ throw new Error('Cannot find existingFn')
396
+ }
397
+
398
+ pos = pos + 1
399
+ this._stack.splice(pos, 0, newFn)
400
+ }
401
+
402
+ /**
403
+ * Adds a single function before a function that already exists in the
404
+ * pipeline.
405
+ *
406
+ * Logs a warning if the function has not been registered.
407
+ *
408
+ * @param {Function} existingFn A function that already exists in the pipeline.
409
+ * @param {Function} newFn The new function to add to the pipeline.
410
+ * @memberOf Pipeline
411
+ */
412
+ lunr.Pipeline.prototype.before = function (existingFn, newFn) {
413
+ lunr.Pipeline.warnIfFunctionNotRegistered(newFn)
414
+
415
+ var pos = this._stack.indexOf(existingFn)
416
+ if (pos == -1) {
417
+ throw new Error('Cannot find existingFn')
418
+ }
419
+
420
+ this._stack.splice(pos, 0, newFn)
421
+ }
422
+
423
+ /**
424
+ * Removes a function from the pipeline.
425
+ *
426
+ * @param {Function} fn The function to remove from the pipeline.
427
+ * @memberOf Pipeline
428
+ */
429
+ lunr.Pipeline.prototype.remove = function (fn) {
430
+ var pos = this._stack.indexOf(fn)
431
+ if (pos == -1) {
432
+ return
433
+ }
434
+
435
+ this._stack.splice(pos, 1)
436
+ }
437
+
438
+ /**
439
+ * Runs the current list of functions that make up the pipeline against the
440
+ * passed tokens.
441
+ *
442
+ * @param {Array} tokens The tokens to run through the pipeline.
443
+ * @returns {Array}
444
+ * @memberOf Pipeline
445
+ */
446
+ lunr.Pipeline.prototype.run = function (tokens) {
447
+ var out = [],
448
+ tokenLength = tokens.length,
449
+ stackLength = this._stack.length
450
+
451
+ for (var i = 0; i < tokenLength; i++) {
452
+ var token = tokens[i]
453
+
454
+ for (var j = 0; j < stackLength; j++) {
455
+ token = this._stack[j](token, i, tokens)
456
+ if (token === void 0 || token === '') break
457
+ };
458
+
459
+ if (token !== void 0 && token !== '') out.push(token)
460
+ };
461
+
462
+ return out
463
+ }
464
+
465
+ /**
466
+ * Resets the pipeline by removing any existing processors.
467
+ *
468
+ * @memberOf Pipeline
469
+ */
470
+ lunr.Pipeline.prototype.reset = function () {
471
+ this._stack = []
472
+ }
473
+
474
+ /**
475
+ * Returns a representation of the pipeline ready for serialisation.
476
+ *
477
+ * Logs a warning if the function has not been registered.
478
+ *
479
+ * @returns {Array}
480
+ * @memberOf Pipeline
481
+ */
482
+ lunr.Pipeline.prototype.toJSON = function () {
483
+ return this._stack.map(function (fn) {
484
+ lunr.Pipeline.warnIfFunctionNotRegistered(fn)
485
+
486
+ return fn.label
487
+ })
488
+ }
489
+ /*!
490
+ * lunr.Vector
491
+ * Copyright (C) 2016 Oliver Nightingale
492
+ */
493
+
494
+ /**
495
+ * lunr.Vectors implement vector related operations for
496
+ * a series of elements.
497
+ *
498
+ * @constructor
499
+ */
500
+ lunr.Vector = function () {
501
+ this._magnitude = null
502
+ this.list = undefined
503
+ this.length = 0
504
+ }
505
+
506
+ /**
507
+ * lunr.Vector.Node is a simple struct for each node
508
+ * in a lunr.Vector.
509
+ *
510
+ * @private
511
+ * @param {Number} The index of the node in the vector.
512
+ * @param {Object} The data at this node in the vector.
513
+ * @param {lunr.Vector.Node} The node directly after this node in the vector.
514
+ * @constructor
515
+ * @memberOf Vector
516
+ */
517
+ lunr.Vector.Node = function (idx, val, next) {
518
+ this.idx = idx
519
+ this.val = val
520
+ this.next = next
521
+ }
522
+
523
+ /**
524
+ * Inserts a new value at a position in a vector.
525
+ *
526
+ * @param {Number} The index at which to insert a value.
527
+ * @param {Object} The object to insert in the vector.
528
+ * @memberOf Vector.
529
+ */
530
+ lunr.Vector.prototype.insert = function (idx, val) {
531
+ this._magnitude = undefined;
532
+ var list = this.list
533
+
534
+ if (!list) {
535
+ this.list = new lunr.Vector.Node (idx, val, list)
536
+ return this.length++
537
+ }
538
+
539
+ if (idx < list.idx) {
540
+ this.list = new lunr.Vector.Node (idx, val, list)
541
+ return this.length++
542
+ }
543
+
544
+ var prev = list,
545
+ next = list.next
546
+
547
+ while (next != undefined) {
548
+ if (idx < next.idx) {
549
+ prev.next = new lunr.Vector.Node (idx, val, next)
550
+ return this.length++
551
+ }
552
+
553
+ prev = next, next = next.next
554
+ }
555
+
556
+ prev.next = new lunr.Vector.Node (idx, val, next)
557
+ return this.length++
558
+ }
559
+
560
+ /**
561
+ * Calculates the magnitude of this vector.
562
+ *
563
+ * @returns {Number}
564
+ * @memberOf Vector
565
+ */
566
+ lunr.Vector.prototype.magnitude = function () {
567
+ if (this._magnitude) return this._magnitude
568
+ var node = this.list,
569
+ sumOfSquares = 0,
570
+ val
571
+
572
+ while (node) {
573
+ val = node.val
574
+ sumOfSquares += val * val
575
+ node = node.next
576
+ }
577
+
578
+ return this._magnitude = Math.sqrt(sumOfSquares)
579
+ }
580
+
581
+ /**
582
+ * Calculates the dot product of this vector and another vector.
583
+ *
584
+ * @param {lunr.Vector} otherVector The vector to compute the dot product with.
585
+ * @returns {Number}
586
+ * @memberOf Vector
587
+ */
588
+ lunr.Vector.prototype.dot = function (otherVector) {
589
+ var node = this.list,
590
+ otherNode = otherVector.list,
591
+ dotProduct = 0
592
+
593
+ while (node && otherNode) {
594
+ if (node.idx < otherNode.idx) {
595
+ node = node.next
596
+ } else if (node.idx > otherNode.idx) {
597
+ otherNode = otherNode.next
598
+ } else {
599
+ dotProduct += node.val * otherNode.val
600
+ node = node.next
601
+ otherNode = otherNode.next
602
+ }
603
+ }
604
+
605
+ return dotProduct
606
+ }
607
+
608
+ /**
609
+ * Calculates the cosine similarity between this vector and another
610
+ * vector.
611
+ *
612
+ * @param {lunr.Vector} otherVector The other vector to calculate the
613
+ * similarity with.
614
+ * @returns {Number}
615
+ * @memberOf Vector
616
+ */
617
+ lunr.Vector.prototype.similarity = function (otherVector) {
618
+ return this.dot(otherVector) / (this.magnitude() * otherVector.magnitude())
619
+ }
620
+ /*!
621
+ * lunr.SortedSet
622
+ * Copyright (C) 2016 Oliver Nightingale
623
+ */
624
+
625
+ /**
626
+ * lunr.SortedSets are used to maintain an array of uniq values in a sorted
627
+ * order.
628
+ *
629
+ * @constructor
630
+ */
631
+ lunr.SortedSet = function () {
632
+ this.length = 0
633
+ this.elements = []
634
+ }
635
+
636
+ /**
637
+ * Loads a previously serialised sorted set.
638
+ *
639
+ * @param {Array} serialisedData The serialised set to load.
640
+ * @returns {lunr.SortedSet}
641
+ * @memberOf SortedSet
642
+ */
643
+ lunr.SortedSet.load = function (serialisedData) {
644
+ var set = new this
645
+
646
+ set.elements = serialisedData
647
+ set.length = serialisedData.length
648
+
649
+ return set
650
+ }
651
+
652
+ /**
653
+ * Inserts new items into the set in the correct position to maintain the
654
+ * order.
655
+ *
656
+ * @param {Object} The objects to add to this set.
657
+ * @memberOf SortedSet
658
+ */
659
+ lunr.SortedSet.prototype.add = function () {
660
+ var i, element
661
+
662
+ for (i = 0; i < arguments.length; i++) {
663
+ element = arguments[i]
664
+ if (~this.indexOf(element)) continue
665
+ this.elements.splice(this.locationFor(element), 0, element)
666
+ }
667
+
668
+ this.length = this.elements.length
669
+ }
670
+
671
+ /**
672
+ * Converts this sorted set into an array.
673
+ *
674
+ * @returns {Array}
675
+ * @memberOf SortedSet
676
+ */
677
+ lunr.SortedSet.prototype.toArray = function () {
678
+ return this.elements.slice()
679
+ }
680
+
681
+ /**
682
+ * Creates a new array with the results of calling a provided function on every
683
+ * element in this sorted set.
684
+ *
685
+ * Delegates to Array.prototype.map and has the same signature.
686
+ *
687
+ * @param {Function} fn The function that is called on each element of the
688
+ * set.
689
+ * @param {Object} ctx An optional object that can be used as the context
690
+ * for the function fn.
691
+ * @returns {Array}
692
+ * @memberOf SortedSet
693
+ */
694
+ lunr.SortedSet.prototype.map = function (fn, ctx) {
695
+ return this.elements.map(fn, ctx)
696
+ }
697
+
698
+ /**
699
+ * Executes a provided function once per sorted set element.
700
+ *
701
+ * Delegates to Array.prototype.forEach and has the same signature.
702
+ *
703
+ * @param {Function} fn The function that is called on each element of the
704
+ * set.
705
+ * @param {Object} ctx An optional object that can be used as the context
706
+ * @memberOf SortedSet
707
+ * for the function fn.
708
+ */
709
+ lunr.SortedSet.prototype.forEach = function (fn, ctx) {
710
+ return this.elements.forEach(fn, ctx)
711
+ }
712
+
713
+ /**
714
+ * Returns the index at which a given element can be found in the
715
+ * sorted set, or -1 if it is not present.
716
+ *
717
+ * @param {Object} elem The object to locate in the sorted set.
718
+ * @returns {Number}
719
+ * @memberOf SortedSet
720
+ */
721
+ lunr.SortedSet.prototype.indexOf = function (elem) {
722
+ var start = 0,
723
+ end = this.elements.length,
724
+ sectionLength = end - start,
725
+ pivot = start + Math.floor(sectionLength / 2),
726
+ pivotElem = this.elements[pivot]
727
+
728
+ while (sectionLength > 1) {
729
+ if (pivotElem === elem) return pivot
730
+
731
+ if (pivotElem < elem) start = pivot
732
+ if (pivotElem > elem) end = pivot
733
+
734
+ sectionLength = end - start
735
+ pivot = start + Math.floor(sectionLength / 2)
736
+ pivotElem = this.elements[pivot]
737
+ }
738
+
739
+ if (pivotElem === elem) return pivot
740
+
741
+ return -1
742
+ }
743
+
744
+ /**
745
+ * Returns the position within the sorted set that an element should be
746
+ * inserted at to maintain the current order of the set.
747
+ *
748
+ * This function assumes that the element to search for does not already exist
749
+ * in the sorted set.
750
+ *
751
+ * @param {Object} elem The elem to find the position for in the set
752
+ * @returns {Number}
753
+ * @memberOf SortedSet
754
+ */
755
+ lunr.SortedSet.prototype.locationFor = function (elem) {
756
+ var start = 0,
757
+ end = this.elements.length,
758
+ sectionLength = end - start,
759
+ pivot = start + Math.floor(sectionLength / 2),
760
+ pivotElem = this.elements[pivot]
761
+
762
+ while (sectionLength > 1) {
763
+ if (pivotElem < elem) start = pivot
764
+ if (pivotElem > elem) end = pivot
765
+
766
+ sectionLength = end - start
767
+ pivot = start + Math.floor(sectionLength / 2)
768
+ pivotElem = this.elements[pivot]
769
+ }
770
+
771
+ if (pivotElem > elem) return pivot
772
+ if (pivotElem < elem) return pivot + 1
773
+ }
774
+
775
+ /**
776
+ * Creates a new lunr.SortedSet that contains the elements in the intersection
777
+ * of this set and the passed set.
778
+ *
779
+ * @param {lunr.SortedSet} otherSet The set to intersect with this set.
780
+ * @returns {lunr.SortedSet}
781
+ * @memberOf SortedSet
782
+ */
783
+ lunr.SortedSet.prototype.intersect = function (otherSet) {
784
+ var intersectSet = new lunr.SortedSet,
785
+ i = 0, j = 0,
786
+ a_len = this.length, b_len = otherSet.length,
787
+ a = this.elements, b = otherSet.elements
788
+
789
+ while (true) {
790
+ if (i > a_len - 1 || j > b_len - 1) break
791
+
792
+ if (a[i] === b[j]) {
793
+ intersectSet.add(a[i])
794
+ i++, j++
795
+ continue
796
+ }
797
+
798
+ if (a[i] < b[j]) {
799
+ i++
800
+ continue
801
+ }
802
+
803
+ if (a[i] > b[j]) {
804
+ j++
805
+ continue
806
+ }
807
+ };
808
+
809
+ return intersectSet
810
+ }
811
+
812
+ /**
813
+ * Makes a copy of this set
814
+ *
815
+ * @returns {lunr.SortedSet}
816
+ * @memberOf SortedSet
817
+ */
818
+ lunr.SortedSet.prototype.clone = function () {
819
+ var clone = new lunr.SortedSet
820
+
821
+ clone.elements = this.toArray()
822
+ clone.length = clone.elements.length
823
+
824
+ return clone
825
+ }
826
+
827
+ /**
828
+ * Creates a new lunr.SortedSet that contains the elements in the union
829
+ * of this set and the passed set.
830
+ *
831
+ * @param {lunr.SortedSet} otherSet The set to union with this set.
832
+ * @returns {lunr.SortedSet}
833
+ * @memberOf SortedSet
834
+ */
835
+ lunr.SortedSet.prototype.union = function (otherSet) {
836
+ var longSet, shortSet, unionSet
837
+
838
+ if (this.length >= otherSet.length) {
839
+ longSet = this, shortSet = otherSet
840
+ } else {
841
+ longSet = otherSet, shortSet = this
842
+ }
843
+
844
+ unionSet = longSet.clone()
845
+
846
+ for(var i = 0, shortSetElements = shortSet.toArray(); i < shortSetElements.length; i++){
847
+ unionSet.add(shortSetElements[i])
848
+ }
849
+
850
+ return unionSet
851
+ }
852
+
853
+ /**
854
+ * Returns a representation of the sorted set ready for serialisation.
855
+ *
856
+ * @returns {Array}
857
+ * @memberOf SortedSet
858
+ */
859
+ lunr.SortedSet.prototype.toJSON = function () {
860
+ return this.toArray()
861
+ }
862
+ /*!
863
+ * lunr.Index
864
+ * Copyright (C) 2016 Oliver Nightingale
865
+ */
866
+
867
+ /**
868
+ * lunr.Index is object that manages a search index. It contains the indexes
869
+ * and stores all the tokens and document lookups. It also provides the main
870
+ * user facing API for the library.
871
+ *
872
+ * @constructor
873
+ */
874
+ lunr.Index = function () {
875
+ this._fields = []
876
+ this._ref = 'id'
877
+ this.pipeline = new lunr.Pipeline
878
+ this.documentStore = new lunr.Store
879
+ this.tokenStore = new lunr.TokenStore
880
+ this.corpusTokens = new lunr.SortedSet
881
+ this.eventEmitter = new lunr.EventEmitter
882
+ this.tokenizerFn = lunr.tokenizer
883
+
884
+ this._idfCache = {}
885
+
886
+ this.on('add', 'remove', 'update', (function () {
887
+ this._idfCache = {}
888
+ }).bind(this))
889
+ }
890
+
891
+ /**
892
+ * Bind a handler to events being emitted by the index.
893
+ *
894
+ * The handler can be bound to many events at the same time.
895
+ *
896
+ * @param {String} [eventName] The name(s) of events to bind the function to.
897
+ * @param {Function} fn The serialised set to load.
898
+ * @memberOf Index
899
+ */
900
+ lunr.Index.prototype.on = function () {
901
+ var args = Array.prototype.slice.call(arguments)
902
+ return this.eventEmitter.addListener.apply(this.eventEmitter, args)
903
+ }
904
+
905
+ /**
906
+ * Removes a handler from an event being emitted by the index.
907
+ *
908
+ * @param {String} eventName The name of events to remove the function from.
909
+ * @param {Function} fn The serialised set to load.
910
+ * @memberOf Index
911
+ */
912
+ lunr.Index.prototype.off = function (name, fn) {
913
+ return this.eventEmitter.removeListener(name, fn)
914
+ }
915
+
916
+ /**
917
+ * Loads a previously serialised index.
918
+ *
919
+ * Issues a warning if the index being imported was serialised
920
+ * by a different version of lunr.
921
+ *
922
+ * @param {Object} serialisedData The serialised set to load.
923
+ * @returns {lunr.Index}
924
+ * @memberOf Index
925
+ */
926
+ lunr.Index.load = function (serialisedData) {
927
+ if (serialisedData.version !== lunr.version) {
928
+ lunr.utils.warn('version mismatch: current ' + lunr.version + ' importing ' + serialisedData.version)
929
+ }
930
+
931
+ var idx = new this
932
+
933
+ idx._fields = serialisedData.fields
934
+ idx._ref = serialisedData.ref
935
+
936
+ idx.tokenizer = lunr.tokenizer.load(serialisedData.tokenizer)
937
+ idx.documentStore = lunr.Store.load(serialisedData.documentStore)
938
+ idx.tokenStore = lunr.TokenStore.load(serialisedData.tokenStore)
939
+ idx.corpusTokens = lunr.SortedSet.load(serialisedData.corpusTokens)
940
+ idx.pipeline = lunr.Pipeline.load(serialisedData.pipeline)
941
+
942
+ return idx
943
+ }
944
+
945
+ /**
946
+ * Adds a field to the list of fields that will be searchable within documents
947
+ * in the index.
948
+ *
949
+ * An optional boost param can be passed to affect how much tokens in this field
950
+ * rank in search results, by default the boost value is 1.
951
+ *
952
+ * Fields should be added before any documents are added to the index, fields
953
+ * that are added after documents are added to the index will only apply to new
954
+ * documents added to the index.
955
+ *
956
+ * @param {String} fieldName The name of the field within the document that
957
+ * should be indexed
958
+ * @param {Number} boost An optional boost that can be applied to terms in this
959
+ * field.
960
+ * @returns {lunr.Index}
961
+ * @memberOf Index
962
+ */
963
+ lunr.Index.prototype.field = function (fieldName, opts) {
964
+ var opts = opts || {},
965
+ field = { name: fieldName, boost: opts.boost || 1 }
966
+
967
+ this._fields.push(field)
968
+ return this
969
+ }
970
+
971
+ /**
972
+ * Sets the property used to uniquely identify documents added to the index,
973
+ * by default this property is 'id'.
974
+ *
975
+ * This should only be changed before adding documents to the index, changing
976
+ * the ref property without resetting the index can lead to unexpected results.
977
+ *
978
+ * The value of ref can be of any type but it _must_ be stably comparable and
979
+ * orderable.
980
+ *
981
+ * @param {String} refName The property to use to uniquely identify the
982
+ * documents in the index.
983
+ * @param {Boolean} emitEvent Whether to emit add events, defaults to true
984
+ * @returns {lunr.Index}
985
+ * @memberOf Index
986
+ */
987
+ lunr.Index.prototype.ref = function (refName) {
988
+ this._ref = refName
989
+ return this
990
+ }
991
+
992
+ /**
993
+ * Sets the tokenizer used for this index.
994
+ *
995
+ * By default the index will use the default tokenizer, lunr.tokenizer. The tokenizer
996
+ * should only be changed before adding documents to the index. Changing the tokenizer
997
+ * without re-building the index can lead to unexpected results.
998
+ *
999
+ * @param {Function} fn The function to use as a tokenizer.
1000
+ * @returns {lunr.Index}
1001
+ * @memberOf Index
1002
+ */
1003
+ lunr.Index.prototype.tokenizer = function (fn) {
1004
+ var isRegistered = fn.label && (fn.label in lunr.tokenizer.registeredFunctions)
1005
+
1006
+ if (!isRegistered) {
1007
+ lunr.utils.warn('Function is not a registered tokenizer. This may cause problems when serialising the index')
1008
+ }
1009
+
1010
+ this.tokenizerFn = fn
1011
+ return this
1012
+ }
1013
+
1014
+ /**
1015
+ * Add a document to the index.
1016
+ *
1017
+ * This is the way new documents enter the index, this function will run the
1018
+ * fields from the document through the index's pipeline and then add it to
1019
+ * the index, it will then show up in search results.
1020
+ *
1021
+ * An 'add' event is emitted with the document that has been added and the index
1022
+ * the document has been added to. This event can be silenced by passing false
1023
+ * as the second argument to add.
1024
+ *
1025
+ * @param {Object} doc The document to add to the index.
1026
+ * @param {Boolean} emitEvent Whether or not to emit events, default true.
1027
+ * @memberOf Index
1028
+ */
1029
+ lunr.Index.prototype.add = function (doc, emitEvent) {
1030
+ var docTokens = {},
1031
+ allDocumentTokens = new lunr.SortedSet,
1032
+ docRef = doc[this._ref],
1033
+ emitEvent = emitEvent === undefined ? true : emitEvent
1034
+
1035
+ this._fields.forEach(function (field) {
1036
+ var fieldTokens = this.pipeline.run(this.tokenizerFn(doc[field.name]))
1037
+
1038
+ docTokens[field.name] = fieldTokens
1039
+
1040
+ for (var i = 0; i < fieldTokens.length; i++) {
1041
+ var token = fieldTokens[i]
1042
+ allDocumentTokens.add(token)
1043
+ this.corpusTokens.add(token)
1044
+ }
1045
+ }, this)
1046
+
1047
+ this.documentStore.set(docRef, allDocumentTokens)
1048
+
1049
+ for (var i = 0; i < allDocumentTokens.length; i++) {
1050
+ var token = allDocumentTokens.elements[i]
1051
+ var tf = 0;
1052
+
1053
+ for (var j = 0; j < this._fields.length; j++){
1054
+ var field = this._fields[j]
1055
+ var fieldTokens = docTokens[field.name]
1056
+ var fieldLength = fieldTokens.length
1057
+
1058
+ if (!fieldLength) continue
1059
+
1060
+ var tokenCount = 0
1061
+ for (var k = 0; k < fieldLength; k++){
1062
+ if (fieldTokens[k] === token){
1063
+ tokenCount++
1064
+ }
1065
+ }
1066
+
1067
+ tf += (tokenCount / fieldLength * field.boost)
1068
+ }
1069
+
1070
+ this.tokenStore.add(token, { ref: docRef, tf: tf })
1071
+ };
1072
+
1073
+ if (emitEvent) this.eventEmitter.emit('add', doc, this)
1074
+ }
1075
+
1076
+ /**
1077
+ * Removes a document from the index.
1078
+ *
1079
+ * To make sure documents no longer show up in search results they can be
1080
+ * removed from the index using this method.
1081
+ *
1082
+ * The document passed only needs to have the same ref property value as the
1083
+ * document that was added to the index, they could be completely different
1084
+ * objects.
1085
+ *
1086
+ * A 'remove' event is emitted with the document that has been removed and the index
1087
+ * the document has been removed from. This event can be silenced by passing false
1088
+ * as the second argument to remove.
1089
+ *
1090
+ * @param {Object} doc The document to remove from the index.
1091
+ * @param {Boolean} emitEvent Whether to emit remove events, defaults to true
1092
+ * @memberOf Index
1093
+ */
1094
+ lunr.Index.prototype.remove = function (doc, emitEvent) {
1095
+ var docRef = doc[this._ref],
1096
+ emitEvent = emitEvent === undefined ? true : emitEvent
1097
+
1098
+ if (!this.documentStore.has(docRef)) return
1099
+
1100
+ var docTokens = this.documentStore.get(docRef)
1101
+
1102
+ this.documentStore.remove(docRef)
1103
+
1104
+ docTokens.forEach(function (token) {
1105
+ this.tokenStore.remove(token, docRef)
1106
+ }, this)
1107
+
1108
+ if (emitEvent) this.eventEmitter.emit('remove', doc, this)
1109
+ }
1110
+
1111
+ /**
1112
+ * Updates a document in the index.
1113
+ *
1114
+ * When a document contained within the index gets updated, fields changed,
1115
+ * added or removed, to make sure it correctly matched against search queries,
1116
+ * it should be updated in the index.
1117
+ *
1118
+ * This method is just a wrapper around `remove` and `add`
1119
+ *
1120
+ * An 'update' event is emitted with the document that has been updated and the index.
1121
+ * This event can be silenced by passing false as the second argument to update. Only
1122
+ * an update event will be fired, the 'add' and 'remove' events of the underlying calls
1123
+ * are silenced.
1124
+ *
1125
+ * @param {Object} doc The document to update in the index.
1126
+ * @param {Boolean} emitEvent Whether to emit update events, defaults to true
1127
+ * @see Index.prototype.remove
1128
+ * @see Index.prototype.add
1129
+ * @memberOf Index
1130
+ */
1131
+ lunr.Index.prototype.update = function (doc, emitEvent) {
1132
+ var emitEvent = emitEvent === undefined ? true : emitEvent
1133
+
1134
+ this.remove(doc, false)
1135
+ this.add(doc, false)
1136
+
1137
+ if (emitEvent) this.eventEmitter.emit('update', doc, this)
1138
+ }
1139
+
1140
+ /**
1141
+ * Calculates the inverse document frequency for a token within the index.
1142
+ *
1143
+ * @param {String} token The token to calculate the idf of.
1144
+ * @see Index.prototype.idf
1145
+ * @private
1146
+ * @memberOf Index
1147
+ */
1148
+ lunr.Index.prototype.idf = function (term) {
1149
+ var cacheKey = "@" + term
1150
+ if (Object.prototype.hasOwnProperty.call(this._idfCache, cacheKey)) return this._idfCache[cacheKey]
1151
+
1152
+ var documentFrequency = this.tokenStore.count(term),
1153
+ idf = 1
1154
+
1155
+ if (documentFrequency > 0) {
1156
+ idf = 1 + Math.log(this.documentStore.length / documentFrequency)
1157
+ }
1158
+
1159
+ return this._idfCache[cacheKey] = idf
1160
+ }
1161
+
1162
+ /**
1163
+ * Searches the index using the passed query.
1164
+ *
1165
+ * Queries should be a string, multiple words are allowed and will lead to an
1166
+ * AND based query, e.g. `idx.search('foo bar')` will run a search for
1167
+ * documents containing both 'foo' and 'bar'.
1168
+ *
1169
+ * All query tokens are passed through the same pipeline that document tokens
1170
+ * are passed through, so any language processing involved will be run on every
1171
+ * query term.
1172
+ *
1173
+ * Each query term is expanded, so that the term 'he' might be expanded to
1174
+ * 'hello' and 'help' if those terms were already included in the index.
1175
+ *
1176
+ * Matching documents are returned as an array of objects, each object contains
1177
+ * the matching document ref, as set for this index, and the similarity score
1178
+ * for this document against the query.
1179
+ *
1180
+ * @param {String} query The query to search the index with.
1181
+ * @returns {Object}
1182
+ * @see Index.prototype.idf
1183
+ * @see Index.prototype.documentVector
1184
+ * @memberOf Index
1185
+ */
1186
+ lunr.Index.prototype.search = function (query) {
1187
+ var queryTokens = this.pipeline.run(this.tokenizerFn(query)),
1188
+ queryVector = new lunr.Vector,
1189
+ documentSets = [],
1190
+ fieldBoosts = this._fields.reduce(function (memo, f) { return memo + f.boost }, 0)
1191
+
1192
+ var hasSomeToken = queryTokens.some(function (token) {
1193
+ return this.tokenStore.has(token)
1194
+ }, this)
1195
+
1196
+ if (!hasSomeToken) return []
1197
+
1198
+ queryTokens
1199
+ .forEach(function (token, i, tokens) {
1200
+ var tf = 1 / tokens.length * this._fields.length * fieldBoosts,
1201
+ self = this
1202
+
1203
+ var set = this.tokenStore.expand(token).reduce(function (memo, key) {
1204
+ var pos = self.corpusTokens.indexOf(key),
1205
+ idf = self.idf(key),
1206
+ similarityBoost = 1,
1207
+ set = new lunr.SortedSet
1208
+
1209
+ // if the expanded key is not an exact match to the token then
1210
+ // penalise the score for this key by how different the key is
1211
+ // to the token.
1212
+ if (key !== token) {
1213
+ var diff = Math.max(3, key.length - token.length)
1214
+ similarityBoost = 1 / Math.log(diff)
1215
+ }
1216
+
1217
+ // calculate the query tf-idf score for this token
1218
+ // applying an similarityBoost to ensure exact matches
1219
+ // these rank higher than expanded terms
1220
+ if (pos > -1) queryVector.insert(pos, tf * idf * similarityBoost)
1221
+
1222
+ // add all the documents that have this key into a set
1223
+ // ensuring that the type of key is preserved
1224
+ var matchingDocuments = self.tokenStore.get(key),
1225
+ refs = Object.keys(matchingDocuments),
1226
+ refsLen = refs.length
1227
+
1228
+ for (var i = 0; i < refsLen; i++) {
1229
+ set.add(matchingDocuments[refs[i]].ref)
1230
+ }
1231
+
1232
+ return memo.union(set)
1233
+ }, new lunr.SortedSet)
1234
+
1235
+ documentSets.push(set)
1236
+ }, this)
1237
+
1238
+ var documentSet = documentSets.reduce(function (memo, set) {
1239
+ return memo.intersect(set)
1240
+ })
1241
+
1242
+ return documentSet
1243
+ .map(function (ref) {
1244
+ return { ref: ref, score: queryVector.similarity(this.documentVector(ref)) }
1245
+ }, this)
1246
+ .sort(function (a, b) {
1247
+ return b.score - a.score
1248
+ })
1249
+ }
1250
+
1251
+ /**
1252
+ * Generates a vector containing all the tokens in the document matching the
1253
+ * passed documentRef.
1254
+ *
1255
+ * The vector contains the tf-idf score for each token contained in the
1256
+ * document with the passed documentRef. The vector will contain an element
1257
+ * for every token in the indexes corpus, if the document does not contain that
1258
+ * token the element will be 0.
1259
+ *
1260
+ * @param {Object} documentRef The ref to find the document with.
1261
+ * @returns {lunr.Vector}
1262
+ * @private
1263
+ * @memberOf Index
1264
+ */
1265
+ lunr.Index.prototype.documentVector = function (documentRef) {
1266
+ var documentTokens = this.documentStore.get(documentRef),
1267
+ documentTokensLength = documentTokens.length,
1268
+ documentVector = new lunr.Vector
1269
+
1270
+ for (var i = 0; i < documentTokensLength; i++) {
1271
+ var token = documentTokens.elements[i],
1272
+ tf = this.tokenStore.get(token)[documentRef].tf,
1273
+ idf = this.idf(token)
1274
+
1275
+ documentVector.insert(this.corpusTokens.indexOf(token), tf * idf)
1276
+ };
1277
+
1278
+ return documentVector
1279
+ }
1280
+
1281
+ /**
1282
+ * Returns a representation of the index ready for serialisation.
1283
+ *
1284
+ * @returns {Object}
1285
+ * @memberOf Index
1286
+ */
1287
+ lunr.Index.prototype.toJSON = function () {
1288
+ return {
1289
+ version: lunr.version,
1290
+ fields: this._fields,
1291
+ ref: this._ref,
1292
+ tokenizer: this.tokenizerFn.label,
1293
+ documentStore: this.documentStore.toJSON(),
1294
+ tokenStore: this.tokenStore.toJSON(),
1295
+ corpusTokens: this.corpusTokens.toJSON(),
1296
+ pipeline: this.pipeline.toJSON()
1297
+ }
1298
+ }
1299
+
1300
+ /**
1301
+ * Applies a plugin to the current index.
1302
+ *
1303
+ * A plugin is a function that is called with the index as its context.
1304
+ * Plugins can be used to customise or extend the behaviour the index
1305
+ * in some way. A plugin is just a function, that encapsulated the custom
1306
+ * behaviour that should be applied to the index.
1307
+ *
1308
+ * The plugin function will be called with the index as its argument, additional
1309
+ * arguments can also be passed when calling use. The function will be called
1310
+ * with the index as its context.
1311
+ *
1312
+ * Example:
1313
+ *
1314
+ * var myPlugin = function (idx, arg1, arg2) {
1315
+ * // `this` is the index to be extended
1316
+ * // apply any extensions etc here.
1317
+ * }
1318
+ *
1319
+ * var idx = lunr(function () {
1320
+ * this.use(myPlugin, 'arg1', 'arg2')
1321
+ * })
1322
+ *
1323
+ * @param {Function} plugin The plugin to apply.
1324
+ * @memberOf Index
1325
+ */
1326
+ lunr.Index.prototype.use = function (plugin) {
1327
+ var args = Array.prototype.slice.call(arguments, 1)
1328
+ args.unshift(this)
1329
+ plugin.apply(this, args)
1330
+ }
1331
+ /*!
1332
+ * lunr.Store
1333
+ * Copyright (C) 2016 Oliver Nightingale
1334
+ */
1335
+
1336
+ /**
1337
+ * lunr.Store is a simple key-value store used for storing sets of tokens for
1338
+ * documents stored in index.
1339
+ *
1340
+ * @constructor
1341
+ * @module
1342
+ */
1343
+ lunr.Store = function () {
1344
+ this.store = {}
1345
+ this.length = 0
1346
+ }
1347
+
1348
+ /**
1349
+ * Loads a previously serialised store
1350
+ *
1351
+ * @param {Object} serialisedData The serialised store to load.
1352
+ * @returns {lunr.Store}
1353
+ * @memberOf Store
1354
+ */
1355
+ lunr.Store.load = function (serialisedData) {
1356
+ var store = new this
1357
+
1358
+ store.length = serialisedData.length
1359
+ store.store = Object.keys(serialisedData.store).reduce(function (memo, key) {
1360
+ memo[key] = lunr.SortedSet.load(serialisedData.store[key])
1361
+ return memo
1362
+ }, {})
1363
+
1364
+ return store
1365
+ }
1366
+
1367
+ /**
1368
+ * Stores the given tokens in the store against the given id.
1369
+ *
1370
+ * @param {Object} id The key used to store the tokens against.
1371
+ * @param {Object} tokens The tokens to store against the key.
1372
+ * @memberOf Store
1373
+ */
1374
+ lunr.Store.prototype.set = function (id, tokens) {
1375
+ if (!this.has(id)) this.length++
1376
+ this.store[id] = tokens
1377
+ }
1378
+
1379
+ /**
1380
+ * Retrieves the tokens from the store for a given key.
1381
+ *
1382
+ * @param {Object} id The key to lookup and retrieve from the store.
1383
+ * @returns {Object}
1384
+ * @memberOf Store
1385
+ */
1386
+ lunr.Store.prototype.get = function (id) {
1387
+ return this.store[id]
1388
+ }
1389
+
1390
+ /**
1391
+ * Checks whether the store contains a key.
1392
+ *
1393
+ * @param {Object} id The id to look up in the store.
1394
+ * @returns {Boolean}
1395
+ * @memberOf Store
1396
+ */
1397
+ lunr.Store.prototype.has = function (id) {
1398
+ return id in this.store
1399
+ }
1400
+
1401
+ /**
1402
+ * Removes the value for a key in the store.
1403
+ *
1404
+ * @param {Object} id The id to remove from the store.
1405
+ * @memberOf Store
1406
+ */
1407
+ lunr.Store.prototype.remove = function (id) {
1408
+ if (!this.has(id)) return
1409
+
1410
+ delete this.store[id]
1411
+ this.length--
1412
+ }
1413
+
1414
+ /**
1415
+ * Returns a representation of the store ready for serialisation.
1416
+ *
1417
+ * @returns {Object}
1418
+ * @memberOf Store
1419
+ */
1420
+ lunr.Store.prototype.toJSON = function () {
1421
+ return {
1422
+ store: this.store,
1423
+ length: this.length
1424
+ }
1425
+ }
1426
+
1427
+ /*!
1428
+ * lunr.stemmer
1429
+ * Copyright (C) 2016 Oliver Nightingale
1430
+ * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
1431
+ */
1432
+
1433
+ /**
1434
+ * lunr.stemmer is an english language stemmer, this is a JavaScript
1435
+ * implementation of the PorterStemmer taken from http://tartarus.org/~martin
1436
+ *
1437
+ * @module
1438
+ * @param {String} str The string to stem
1439
+ * @returns {String}
1440
+ * @see lunr.Pipeline
1441
+ */
1442
+ lunr.stemmer = (function(){
1443
+ var step2list = {
1444
+ "ational" : "ate",
1445
+ "tional" : "tion",
1446
+ "enci" : "ence",
1447
+ "anci" : "ance",
1448
+ "izer" : "ize",
1449
+ "bli" : "ble",
1450
+ "alli" : "al",
1451
+ "entli" : "ent",
1452
+ "eli" : "e",
1453
+ "ousli" : "ous",
1454
+ "ization" : "ize",
1455
+ "ation" : "ate",
1456
+ "ator" : "ate",
1457
+ "alism" : "al",
1458
+ "iveness" : "ive",
1459
+ "fulness" : "ful",
1460
+ "ousness" : "ous",
1461
+ "aliti" : "al",
1462
+ "iviti" : "ive",
1463
+ "biliti" : "ble",
1464
+ "logi" : "log"
1465
+ },
1466
+
1467
+ step3list = {
1468
+ "icate" : "ic",
1469
+ "ative" : "",
1470
+ "alize" : "al",
1471
+ "iciti" : "ic",
1472
+ "ical" : "ic",
1473
+ "ful" : "",
1474
+ "ness" : ""
1475
+ },
1476
+
1477
+ c = "[^aeiou]", // consonant
1478
+ v = "[aeiouy]", // vowel
1479
+ C = c + "[^aeiouy]*", // consonant sequence
1480
+ V = v + "[aeiou]*", // vowel sequence
1481
+
1482
+ mgr0 = "^(" + C + ")?" + V + C, // [C]VC... is m>0
1483
+ meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$", // [C]VC[V] is m=1
1484
+ mgr1 = "^(" + C + ")?" + V + C + V + C, // [C]VCVC... is m>1
1485
+ s_v = "^(" + C + ")?" + v; // vowel in stem
1486
+
1487
+ var re_mgr0 = new RegExp(mgr0);
1488
+ var re_mgr1 = new RegExp(mgr1);
1489
+ var re_meq1 = new RegExp(meq1);
1490
+ var re_s_v = new RegExp(s_v);
1491
+
1492
+ var re_1a = /^(.+?)(ss|i)es$/;
1493
+ var re2_1a = /^(.+?)([^s])s$/;
1494
+ var re_1b = /^(.+?)eed$/;
1495
+ var re2_1b = /^(.+?)(ed|ing)$/;
1496
+ var re_1b_2 = /.$/;
1497
+ var re2_1b_2 = /(at|bl|iz)$/;
1498
+ var re3_1b_2 = new RegExp("([^aeiouylsz])\\1$");
1499
+ var re4_1b_2 = new RegExp("^" + C + v + "[^aeiouwxy]$");
1500
+
1501
+ var re_1c = /^(.+?[^aeiou])y$/;
1502
+ var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
1503
+
1504
+ var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
1505
+
1506
+ var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
1507
+ var re2_4 = /^(.+?)(s|t)(ion)$/;
1508
+
1509
+ var re_5 = /^(.+?)e$/;
1510
+ var re_5_1 = /ll$/;
1511
+ var re3_5 = new RegExp("^" + C + v + "[^aeiouwxy]$");
1512
+
1513
+ var porterStemmer = function porterStemmer(w) {
1514
+ var stem,
1515
+ suffix,
1516
+ firstch,
1517
+ re,
1518
+ re2,
1519
+ re3,
1520
+ re4;
1521
+
1522
+ if (w.length < 3) { return w; }
1523
+
1524
+ firstch = w.substr(0,1);
1525
+ if (firstch == "y") {
1526
+ w = firstch.toUpperCase() + w.substr(1);
1527
+ }
1528
+
1529
+ // Step 1a
1530
+ re = re_1a
1531
+ re2 = re2_1a;
1532
+
1533
+ if (re.test(w)) { w = w.replace(re,"$1$2"); }
1534
+ else if (re2.test(w)) { w = w.replace(re2,"$1$2"); }
1535
+
1536
+ // Step 1b
1537
+ re = re_1b;
1538
+ re2 = re2_1b;
1539
+ if (re.test(w)) {
1540
+ var fp = re.exec(w);
1541
+ re = re_mgr0;
1542
+ if (re.test(fp[1])) {
1543
+ re = re_1b_2;
1544
+ w = w.replace(re,"");
1545
+ }
1546
+ } else if (re2.test(w)) {
1547
+ var fp = re2.exec(w);
1548
+ stem = fp[1];
1549
+ re2 = re_s_v;
1550
+ if (re2.test(stem)) {
1551
+ w = stem;
1552
+ re2 = re2_1b_2;
1553
+ re3 = re3_1b_2;
1554
+ re4 = re4_1b_2;
1555
+ if (re2.test(w)) { w = w + "e"; }
1556
+ else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,""); }
1557
+ else if (re4.test(w)) { w = w + "e"; }
1558
+ }
1559
+ }
1560
+
1561
+ // Step 1c - replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say)
1562
+ re = re_1c;
1563
+ if (re.test(w)) {
1564
+ var fp = re.exec(w);
1565
+ stem = fp[1];
1566
+ w = stem + "i";
1567
+ }
1568
+
1569
+ // Step 2
1570
+ re = re_2;
1571
+ if (re.test(w)) {
1572
+ var fp = re.exec(w);
1573
+ stem = fp[1];
1574
+ suffix = fp[2];
1575
+ re = re_mgr0;
1576
+ if (re.test(stem)) {
1577
+ w = stem + step2list[suffix];
1578
+ }
1579
+ }
1580
+
1581
+ // Step 3
1582
+ re = re_3;
1583
+ if (re.test(w)) {
1584
+ var fp = re.exec(w);
1585
+ stem = fp[1];
1586
+ suffix = fp[2];
1587
+ re = re_mgr0;
1588
+ if (re.test(stem)) {
1589
+ w = stem + step3list[suffix];
1590
+ }
1591
+ }
1592
+
1593
+ // Step 4
1594
+ re = re_4;
1595
+ re2 = re2_4;
1596
+ if (re.test(w)) {
1597
+ var fp = re.exec(w);
1598
+ stem = fp[1];
1599
+ re = re_mgr1;
1600
+ if (re.test(stem)) {
1601
+ w = stem;
1602
+ }
1603
+ } else if (re2.test(w)) {
1604
+ var fp = re2.exec(w);
1605
+ stem = fp[1] + fp[2];
1606
+ re2 = re_mgr1;
1607
+ if (re2.test(stem)) {
1608
+ w = stem;
1609
+ }
1610
+ }
1611
+
1612
+ // Step 5
1613
+ re = re_5;
1614
+ if (re.test(w)) {
1615
+ var fp = re.exec(w);
1616
+ stem = fp[1];
1617
+ re = re_mgr1;
1618
+ re2 = re_meq1;
1619
+ re3 = re3_5;
1620
+ if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) {
1621
+ w = stem;
1622
+ }
1623
+ }
1624
+
1625
+ re = re_5_1;
1626
+ re2 = re_mgr1;
1627
+ if (re.test(w) && re2.test(w)) {
1628
+ re = re_1b_2;
1629
+ w = w.replace(re,"");
1630
+ }
1631
+
1632
+ // and turn initial Y back to y
1633
+
1634
+ if (firstch == "y") {
1635
+ w = firstch.toLowerCase() + w.substr(1);
1636
+ }
1637
+
1638
+ return w;
1639
+ };
1640
+
1641
+ return porterStemmer;
1642
+ })();
1643
+
1644
+ lunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer')
1645
+ /*!
1646
+ * lunr.stopWordFilter
1647
+ * Copyright (C) 2016 Oliver Nightingale
1648
+ */
1649
+
1650
+ /**
1651
+ * lunr.generateStopWordFilter builds a stopWordFilter function from the provided
1652
+ * list of stop words.
1653
+ *
1654
+ * The built in lunr.stopWordFilter is built using this generator and can be used
1655
+ * to generate custom stopWordFilters for applications or non English languages.
1656
+ *
1657
+ * @module
1658
+ * @param {Array} token The token to pass through the filter
1659
+ * @returns {Function}
1660
+ * @see lunr.Pipeline
1661
+ * @see lunr.stopWordFilter
1662
+ */
1663
+ lunr.generateStopWordFilter = function (stopWords) {
1664
+ var words = stopWords.reduce(function (memo, stopWord) {
1665
+ memo[stopWord] = stopWord
1666
+ return memo
1667
+ }, {})
1668
+
1669
+ return function (token) {
1670
+ if (token && words[token] !== token) return token
1671
+ }
1672
+ }
1673
+
1674
+ /**
1675
+ * lunr.stopWordFilter is an English language stop word list filter, any words
1676
+ * contained in the list will not be passed through the filter.
1677
+ *
1678
+ * This is intended to be used in the Pipeline. If the token does not pass the
1679
+ * filter then undefined will be returned.
1680
+ *
1681
+ * @module
1682
+ * @param {String} token The token to pass through the filter
1683
+ * @returns {String}
1684
+ * @see lunr.Pipeline
1685
+ */
1686
+ lunr.stopWordFilter = lunr.generateStopWordFilter([
1687
+ 'a',
1688
+ 'able',
1689
+ 'about',
1690
+ 'across',
1691
+ 'after',
1692
+ 'all',
1693
+ 'almost',
1694
+ 'also',
1695
+ 'am',
1696
+ 'among',
1697
+ 'an',
1698
+ 'and',
1699
+ 'any',
1700
+ 'are',
1701
+ 'as',
1702
+ 'at',
1703
+ 'be',
1704
+ 'because',
1705
+ 'been',
1706
+ 'but',
1707
+ 'by',
1708
+ 'can',
1709
+ 'cannot',
1710
+ 'could',
1711
+ 'dear',
1712
+ 'did',
1713
+ 'do',
1714
+ 'does',
1715
+ 'either',
1716
+ 'else',
1717
+ 'ever',
1718
+ 'every',
1719
+ 'for',
1720
+ 'from',
1721
+ 'get',
1722
+ 'got',
1723
+ 'had',
1724
+ 'has',
1725
+ 'have',
1726
+ 'he',
1727
+ 'her',
1728
+ 'hers',
1729
+ 'him',
1730
+ 'his',
1731
+ 'how',
1732
+ 'however',
1733
+ 'i',
1734
+ 'if',
1735
+ 'in',
1736
+ 'into',
1737
+ 'is',
1738
+ 'it',
1739
+ 'its',
1740
+ 'just',
1741
+ 'least',
1742
+ 'let',
1743
+ 'like',
1744
+ 'likely',
1745
+ 'may',
1746
+ 'me',
1747
+ 'might',
1748
+ 'most',
1749
+ 'must',
1750
+ 'my',
1751
+ 'neither',
1752
+ 'no',
1753
+ 'nor',
1754
+ 'not',
1755
+ 'of',
1756
+ 'off',
1757
+ 'often',
1758
+ 'on',
1759
+ 'only',
1760
+ 'or',
1761
+ 'other',
1762
+ 'our',
1763
+ 'own',
1764
+ 'rather',
1765
+ 'said',
1766
+ 'say',
1767
+ 'says',
1768
+ 'she',
1769
+ 'should',
1770
+ 'since',
1771
+ 'so',
1772
+ 'some',
1773
+ 'than',
1774
+ 'that',
1775
+ 'the',
1776
+ 'their',
1777
+ 'them',
1778
+ 'then',
1779
+ 'there',
1780
+ 'these',
1781
+ 'they',
1782
+ 'this',
1783
+ 'tis',
1784
+ 'to',
1785
+ 'too',
1786
+ 'twas',
1787
+ 'us',
1788
+ 'wants',
1789
+ 'was',
1790
+ 'we',
1791
+ 'were',
1792
+ 'what',
1793
+ 'when',
1794
+ 'where',
1795
+ 'which',
1796
+ 'while',
1797
+ 'who',
1798
+ 'whom',
1799
+ 'why',
1800
+ 'will',
1801
+ 'with',
1802
+ 'would',
1803
+ 'yet',
1804
+ 'you',
1805
+ 'your'
1806
+ ])
1807
+
1808
+ lunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter')
1809
+ /*!
1810
+ * lunr.trimmer
1811
+ * Copyright (C) 2016 Oliver Nightingale
1812
+ */
1813
+
1814
+ /**
1815
+ * lunr.trimmer is a pipeline function for trimming non word
1816
+ * characters from the begining and end of tokens before they
1817
+ * enter the index.
1818
+ *
1819
+ * This implementation may not work correctly for non latin
1820
+ * characters and should either be removed or adapted for use
1821
+ * with languages with non-latin characters.
1822
+ *
1823
+ * @module
1824
+ * @param {String} token The token to pass through the filter
1825
+ * @returns {String}
1826
+ * @see lunr.Pipeline
1827
+ */
1828
+ lunr.trimmer = function (token) {
1829
+ return token.replace(/^\W+/, '').replace(/\W+$/, '')
1830
+ }
1831
+
1832
+ lunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer')
1833
+ /*!
1834
+ * lunr.stemmer
1835
+ * Copyright (C) 2016 Oliver Nightingale
1836
+ * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
1837
+ */
1838
+
1839
+ /**
1840
+ * lunr.TokenStore is used for efficient storing and lookup of the reverse
1841
+ * index of token to document ref.
1842
+ *
1843
+ * @constructor
1844
+ */
1845
+ lunr.TokenStore = function () {
1846
+ this.root = { docs: {} }
1847
+ this.length = 0
1848
+ }
1849
+
1850
+ /**
1851
+ * Loads a previously serialised token store
1852
+ *
1853
+ * @param {Object} serialisedData The serialised token store to load.
1854
+ * @returns {lunr.TokenStore}
1855
+ * @memberOf TokenStore
1856
+ */
1857
+ lunr.TokenStore.load = function (serialisedData) {
1858
+ var store = new this
1859
+
1860
+ store.root = serialisedData.root
1861
+ store.length = serialisedData.length
1862
+
1863
+ return store
1864
+ }
1865
+
1866
+ /**
1867
+ * Adds a new token doc pair to the store.
1868
+ *
1869
+ * By default this function starts at the root of the current store, however
1870
+ * it can start at any node of any token store if required.
1871
+ *
1872
+ * @param {String} token The token to store the doc under
1873
+ * @param {Object} doc The doc to store against the token
1874
+ * @param {Object} root An optional node at which to start looking for the
1875
+ * correct place to enter the doc, by default the root of this lunr.TokenStore
1876
+ * is used.
1877
+ * @memberOf TokenStore
1878
+ */
1879
+ lunr.TokenStore.prototype.add = function (token, doc, root) {
1880
+ var root = root || this.root,
1881
+ key = token.charAt(0),
1882
+ rest = token.slice(1)
1883
+
1884
+ if (!(key in root)) root[key] = {docs: {}}
1885
+
1886
+ if (rest.length === 0) {
1887
+ root[key].docs[doc.ref] = doc
1888
+ this.length += 1
1889
+ return
1890
+ } else {
1891
+ return this.add(rest, doc, root[key])
1892
+ }
1893
+ }
1894
+
1895
+ /**
1896
+ * Checks whether this key is contained within this lunr.TokenStore.
1897
+ *
1898
+ * By default this function starts at the root of the current store, however
1899
+ * it can start at any node of any token store if required.
1900
+ *
1901
+ * @param {String} token The token to check for
1902
+ * @param {Object} root An optional node at which to start
1903
+ * @memberOf TokenStore
1904
+ */
1905
+ lunr.TokenStore.prototype.has = function (token) {
1906
+ if (!token) return false
1907
+
1908
+ var node = this.root
1909
+
1910
+ for (var i = 0; i < token.length; i++) {
1911
+ if (!node[token.charAt(i)]) return false
1912
+
1913
+ node = node[token.charAt(i)]
1914
+ }
1915
+
1916
+ return true
1917
+ }
1918
+
1919
+ /**
1920
+ * Retrieve a node from the token store for a given token.
1921
+ *
1922
+ * By default this function starts at the root of the current store, however
1923
+ * it can start at any node of any token store if required.
1924
+ *
1925
+ * @param {String} token The token to get the node for.
1926
+ * @param {Object} root An optional node at which to start.
1927
+ * @returns {Object}
1928
+ * @see TokenStore.prototype.get
1929
+ * @memberOf TokenStore
1930
+ */
1931
+ lunr.TokenStore.prototype.getNode = function (token) {
1932
+ if (!token) return {}
1933
+
1934
+ var node = this.root
1935
+
1936
+ for (var i = 0; i < token.length; i++) {
1937
+ if (!node[token.charAt(i)]) return {}
1938
+
1939
+ node = node[token.charAt(i)]
1940
+ }
1941
+
1942
+ return node
1943
+ }
1944
+
1945
+ /**
1946
+ * Retrieve the documents for a node for the given token.
1947
+ *
1948
+ * By default this function starts at the root of the current store, however
1949
+ * it can start at any node of any token store if required.
1950
+ *
1951
+ * @param {String} token The token to get the documents for.
1952
+ * @param {Object} root An optional node at which to start.
1953
+ * @returns {Object}
1954
+ * @memberOf TokenStore
1955
+ */
1956
+ lunr.TokenStore.prototype.get = function (token, root) {
1957
+ return this.getNode(token, root).docs || {}
1958
+ }
1959
+
1960
+ lunr.TokenStore.prototype.count = function (token, root) {
1961
+ return Object.keys(this.get(token, root)).length
1962
+ }
1963
+
1964
+ /**
1965
+ * Remove the document identified by ref from the token in the store.
1966
+ *
1967
+ * By default this function starts at the root of the current store, however
1968
+ * it can start at any node of any token store if required.
1969
+ *
1970
+ * @param {String} token The token to get the documents for.
1971
+ * @param {String} ref The ref of the document to remove from this token.
1972
+ * @param {Object} root An optional node at which to start.
1973
+ * @returns {Object}
1974
+ * @memberOf TokenStore
1975
+ */
1976
+ lunr.TokenStore.prototype.remove = function (token, ref) {
1977
+ if (!token) return
1978
+ var node = this.root
1979
+
1980
+ for (var i = 0; i < token.length; i++) {
1981
+ if (!(token.charAt(i) in node)) return
1982
+ node = node[token.charAt(i)]
1983
+ }
1984
+
1985
+ delete node.docs[ref]
1986
+ }
1987
+
1988
+ /**
1989
+ * Find all the possible suffixes of the passed token using tokens
1990
+ * currently in the store.
1991
+ *
1992
+ * @param {String} token The token to expand.
1993
+ * @returns {Array}
1994
+ * @memberOf TokenStore
1995
+ */
1996
+ lunr.TokenStore.prototype.expand = function (token, memo) {
1997
+ var root = this.getNode(token),
1998
+ docs = root.docs || {},
1999
+ memo = memo || []
2000
+
2001
+ if (Object.keys(docs).length) memo.push(token)
2002
+
2003
+ Object.keys(root)
2004
+ .forEach(function (key) {
2005
+ if (key === 'docs') return
2006
+
2007
+ memo.concat(this.expand(token + key, memo))
2008
+ }, this)
2009
+
2010
+ return memo
2011
+ }
2012
+
2013
+ /**
2014
+ * Returns a representation of the token store ready for serialisation.
2015
+ *
2016
+ * @returns {Object}
2017
+ * @memberOf TokenStore
2018
+ */
2019
+ lunr.TokenStore.prototype.toJSON = function () {
2020
+ return {
2021
+ root: this.root,
2022
+ length: this.length
2023
+ }
2024
+ }
2025
+
2026
+ /**
2027
+ * export the module via AMD, CommonJS or as a browser global
2028
+ * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
2029
+ */
2030
+ ;(function (root, factory) {
2031
+ if (typeof define === 'function' && define.amd) {
2032
+ // AMD. Register as an anonymous module.
2033
+ define(factory)
2034
+ } else if (typeof exports === 'object') {
2035
+ /**
2036
+ * Node. Does not work with strict CommonJS, but
2037
+ * only CommonJS-like enviroments that support module.exports,
2038
+ * like Node.
2039
+ */
2040
+ module.exports = factory()
2041
+ } else {
2042
+ // Browser globals (root is window)
2043
+ root.lunr = factory()
2044
+ }
2045
+ }(this, function () {
2046
+ /**
2047
+ * Just return a value to define the module export.
2048
+ * This example returns an object, but the module
2049
+ * can return a function as the exported value.
2050
+ */
2051
+ return lunr
2052
+ }))
2053
+ })();