From 5e0c0b3c3dd79cede1f625b47a7f0b33b0b1c648 Mon Sep 17 00:00:00 2001
From: Michael Rose
Date: Thu, 4 Oct 2018 23:27:49 -0400
Subject: [PATCH 1/6] Move jekyll-include-cache notice up
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 0a38c37d2ec7..3a4cfde08218 100644
--- a/README.md
+++ b/README.md
@@ -5,10 +5,12 @@
[![Ruby gem](https://img.shields.io/gem/v/minimal-mistakes-jekyll.svg)](https://rubygems.org/gems/minimal-mistakes-jekyll)
[![Tip Me via PayPal](https://img.shields.io/badge/PayPal-tip%20me-green.svg?logo=paypal)](https://www.paypal.me/mmistakes)
-Minimal Mistakes is a flexible two-column Jekyll theme. Perfect for hosting your personal site, blog, or portfolio on GitHub or self-hosting on your own server. As the name implies --- styling is purposely minimalistic to be enhanced and customized by you :smile:.
+Minimal Mistakes is a flexible two-column Jekyll theme. Perfect for hosting your personal site, blog, or portfolio on GitHub or self-hosting on your own server. As the name implies -- styling is purposely minimalistic to be enhanced and customized by you :smile:.
:sparkles: See what's new in the [CHANGELOG](CHANGELOG.md).
+**Note:** The theme uses the [jekyll-include-cache](https://github.com/benbalter/jekyll-include-cache) plugin which will need to be installed in your `Gemfile` and added to the `plugins` array of `_config.yml`. Otherwise you'll throw `Unknown tag 'include_cached'` errors at build.
+
[![Minimal Mistakes live preview][2]][1]
[1]: https://mmistakes.github.io/minimal-mistakes/
@@ -72,8 +74,6 @@ Additional sample posts are available under [posts archive][year-archive] on the
There are three ways to install the theme: as a Ruby gem (for self-hosted sites), as a Ruby gem + jekyll-remote-theme plugin (GitHub Pages hosted sites), or forking/directly copying all of the theme files into your project.
-**Note:** The theme uses the [jekyll-include-cache](https://github.com/benbalter/jekyll-include-cache) plugin which will need to be installed in your `Gemfile` and added to the `plugins` array of `_config.yml`. Otherwise you'll throw `Unknown tag 'include_cached'` errors at build.
-
### Ruby Gem Method
1. Install the theme as a Ruby Gem by adding it to your `Gemfile` like so:
From 1f0365f38843aa3feee86308c68c8cf2d5ca1bea Mon Sep 17 00:00:00 2001
From: Ben McGough
Date: Tue, 9 Oct 2018 10:54:36 -0700
Subject: [PATCH 2/6] Fix Lunr search index merging words (#1884)
Close #1883
---
assets/js/lunr/lunr-store.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/assets/js/lunr/lunr-store.js b/assets/js/lunr/lunr-store.js
index 434b59978bee..660e9f2b23ed 100644
--- a/assets/js/lunr/lunr-store.js
+++ b/assets/js/lunr/lunr-store.js
@@ -18,7 +18,8 @@ var store = [
"title": {{ doc.title | jsonify }},
"excerpt":
{%- if site.search_full_content == true -%}
- {{ doc.content |
+ {{ doc.content | newline_to_br |
+ replace:"
", " " |
replace:"
", " " |
replace:"", " " |
replace:"", " " |
@@ -28,7 +29,8 @@ var store = [
replace:"", " "|
strip_html | strip_newlines | jsonify }},
{%- else -%}
- {{ doc.content |
+ {{ doc.content | newline_to_br |
+ replace:"
", " " |
replace:"", " " |
replace:"", " " |
replace:"", " " |
From 4d9f9825713f037601a33184513ec0d47c7699ab Mon Sep 17 00:00:00 2001
From: Michael Rose
Date: Tue, 9 Oct 2018 13:55:53 -0400
Subject: [PATCH 3/6] Update CHANGELOG and history
---
CHANGELOG.md | 1 +
docs/_docs/18-history.md | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fce8401db225..19ea74720889 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@
### Bug Fixes
+- Fix Lunr search index merging words. [#1883](https://github.com/mmistakes/minimal-mistakes/issues/1883)
- Properly apply `relative_url` filter to internal links in header overlay `actions` array.
## [4.13.0](https://github.com/mmistakes/minimal-mistakes/releases/tag/4.13.0)
diff --git a/docs/_docs/18-history.md b/docs/_docs/18-history.md
index 79e23bc73d21..da0364194ff8 100644
--- a/docs/_docs/18-history.md
+++ b/docs/_docs/18-history.md
@@ -4,7 +4,7 @@ permalink: /docs/history/
excerpt: "Change log of enhancements and bug fixes made to the theme."
sidebar:
nav: docs
-last_modified_at: 2018-10-04T20:16:47-04:00
+last_modified_at: 2018-10-09T13:55:44-04:00
toc: true
---
@@ -23,6 +23,7 @@ toc: true
### Bug Fixes
+- Fix Lunr search index merging words. [#1883](https://github.com/mmistakes/minimal-mistakes/issues/1883)
- Properly apply `relative_url` filter to internal links in header overlay `actions` array.
## [4.13.0](https://github.com/mmistakes/minimal-mistakes/releases/tag/4.13.0)
From a351f84fd3f3add474c7c4eafb7664e51afff969 Mon Sep 17 00:00:00 2001
From: Justin Rummel
Date: Tue, 9 Oct 2018 14:48:51 -0400
Subject: [PATCH 4/6] Update LUNR to 2.3.3 (#1885)
Close #1882
---
assets/js/lunr/lunr.js | 675 ++++++++++++++++++++++++++++++++-----
assets/js/lunr/lunr.min.js | 6 +-
2 files changed, 594 insertions(+), 87 deletions(-)
diff --git a/assets/js/lunr/lunr.js b/assets/js/lunr/lunr.js
index f208eba5a7a5..0ede1a1a4865 100644
--- a/assets/js/lunr/lunr.js
+++ b/assets/js/lunr/lunr.js
@@ -1,6 +1,6 @@
/**
- * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.1.5
- * Copyright (C) 2017 Oliver Nightingale
+ * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.3
+ * Copyright (C) 2018 Oliver Nightingale
* @license MIT
*/
@@ -54,14 +54,15 @@ var lunr = function (config) {
return builder.build()
}
-lunr.version = "2.1.5"
+lunr.version = "2.3.3"
/*!
* lunr.utils
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
* A namespace containing utils for the rest of the lunr library
+ * @namespace lunr.utils
*/
lunr.utils = {}
@@ -69,7 +70,8 @@ lunr.utils = {}
* Print a warning message to the console.
*
* @param {String} message The message to be printed.
- * @memberOf Utils
+ * @memberOf lunr.utils
+ * @function
*/
lunr.utils.warn = (function (global) {
/* eslint-disable no-console */
@@ -90,7 +92,7 @@ lunr.utils.warn = (function (global) {
*
* @param {Any} obj The object to convert to a string.
* @return {String} string representation of the passed object.
- * @memberOf Utils
+ * @memberOf lunr.utils
*/
lunr.utils.asString = function (obj) {
if (obj === void 0 || obj === null) {
@@ -99,6 +101,52 @@ lunr.utils.asString = function (obj) {
return obj.toString()
}
}
+
+/**
+ * Clones an object.
+ *
+ * Will create a copy of an existing object such that any mutations
+ * on the copy cannot affect the original.
+ *
+ * Only shallow objects are supported, passing a nested object to this
+ * function will cause a TypeError.
+ *
+ * Objects with primitives, and arrays of primitives are supported.
+ *
+ * @param {Object} obj The object to clone.
+ * @return {Object} a clone of the passed object.
+ * @throws {TypeError} when a nested object is passed.
+ * @memberOf Utils
+ */
+lunr.utils.clone = function (obj) {
+ if (obj === null || obj === undefined) {
+ return obj
+ }
+
+ var clone = Object.create(null),
+ keys = Object.keys(obj)
+
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i],
+ val = obj[key]
+
+ if (Array.isArray(val)) {
+ clone[key] = val.slice()
+ continue
+ }
+
+ if (typeof val === 'string' ||
+ typeof val === 'number' ||
+ typeof val === 'boolean') {
+ clone[key] = val
+ continue
+ }
+
+ throw new TypeError("clone is not deep and does not support nested objects")
+ }
+
+ return clone
+}
lunr.FieldRef = function (docRef, fieldName, stringValue) {
this.docRef = docRef
this.fieldName = fieldName
@@ -127,6 +175,139 @@ lunr.FieldRef.prototype.toString = function () {
return this._stringValue
}
+/*!
+ * lunr.Set
+ * Copyright (C) 2018 Oliver Nightingale
+ */
+
+/**
+ * A lunr set.
+ *
+ * @constructor
+ */
+lunr.Set = function (elements) {
+ this.elements = Object.create(null)
+
+ if (elements) {
+ this.length = elements.length
+
+ for (var i = 0; i < this.length; i++) {
+ this.elements[elements[i]] = true
+ }
+ } else {
+ this.length = 0
+ }
+}
+
+/**
+ * A complete set that contains all elements.
+ *
+ * @static
+ * @readonly
+ * @type {lunr.Set}
+ */
+lunr.Set.complete = {
+ intersect: function (other) {
+ return other
+ },
+
+ union: function (other) {
+ return other
+ },
+
+ contains: function () {
+ return true
+ }
+}
+
+/**
+ * An empty set that contains no elements.
+ *
+ * @static
+ * @readonly
+ * @type {lunr.Set}
+ */
+lunr.Set.empty = {
+ intersect: function () {
+ return this
+ },
+
+ union: function (other) {
+ return other
+ },
+
+ contains: function () {
+ return false
+ }
+}
+
+/**
+ * Returns true if this set contains the specified object.
+ *
+ * @param {object} object - Object whose presence in this set is to be tested.
+ * @returns {boolean} - True if this set contains the specified object.
+ */
+lunr.Set.prototype.contains = function (object) {
+ return !!this.elements[object]
+}
+
+/**
+ * Returns a new set containing only the elements that are present in both
+ * this set and the specified set.
+ *
+ * @param {lunr.Set} other - set to intersect with this set.
+ * @returns {lunr.Set} a new set that is the intersection of this and the specified set.
+ */
+
+lunr.Set.prototype.intersect = function (other) {
+ var a, b, elements, intersection = []
+
+ if (other === lunr.Set.complete) {
+ return this
+ }
+
+ if (other === lunr.Set.empty) {
+ return other
+ }
+
+ if (this.length < other.length) {
+ a = this
+ b = other
+ } else {
+ a = other
+ b = this
+ }
+
+ elements = Object.keys(a.elements)
+
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i]
+ if (element in b.elements) {
+ intersection.push(element)
+ }
+ }
+
+ return new lunr.Set (intersection)
+}
+
+/**
+ * Returns a new set combining the elements of this and the specified set.
+ *
+ * @param {lunr.Set} other - set to union with this set.
+ * @return {lunr.Set} a new set that is the union of this and the specified set.
+ */
+
+lunr.Set.prototype.union = function (other) {
+ if (other === lunr.Set.complete) {
+ return lunr.Set.complete
+ }
+
+ if (other === lunr.Set.empty) {
+ return this
+ }
+
+ return new lunr.Set(Object.keys(this.elements).concat(Object.keys(other.elements)))
+}
/**
* A function to calculate the inverse document frequency for
* a posting. This is shared between the builder and the index
@@ -208,7 +389,7 @@ lunr.Token.prototype.clone = function (fn) {
}
/*!
* lunr.tokenizer
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
@@ -220,18 +401,26 @@ lunr.Token.prototype.clone = function (fn) {
* then will split this string on the character in `lunr.tokenizer.separator`.
* Arrays will have their elements converted to strings and wrapped in a lunr.Token.
*
+ * Optional metadata can be passed to the tokenizer, this metadata will be cloned and
+ * added as metadata to every token that is created from the object to be tokenized.
+ *
* @static
* @param {?(string|object|object[])} obj - The object to convert into tokens
+ * @param {?object} metadata - Optional metadata to associate with every token
* @returns {lunr.Token[]}
+ * @see {@link lunr.Pipeline}
*/
-lunr.tokenizer = function (obj) {
+lunr.tokenizer = function (obj, metadata) {
if (obj == null || obj == undefined) {
return []
}
if (Array.isArray(obj)) {
return obj.map(function (t) {
- return new lunr.Token(lunr.utils.asString(t).toLowerCase())
+ return new lunr.Token(
+ lunr.utils.asString(t).toLowerCase(),
+ lunr.utils.clone(metadata)
+ )
})
}
@@ -246,11 +435,15 @@ lunr.tokenizer = function (obj) {
if ((char.match(lunr.tokenizer.separator) || sliceEnd == len)) {
if (sliceLength > 0) {
+ var tokenMetadata = lunr.utils.clone(metadata) || {}
+ tokenMetadata["position"] = [sliceStart, sliceLength]
+ tokenMetadata["index"] = tokens.length
+
tokens.push(
- new lunr.Token (str.slice(sliceStart, sliceEnd), {
- position: [sliceStart, sliceLength],
- index: tokens.length
- })
+ new lunr.Token (
+ str.slice(sliceStart, sliceEnd),
+ tokenMetadata
+ )
)
}
@@ -272,7 +465,7 @@ lunr.tokenizer = function (obj) {
lunr.tokenizer.separator = /[\s\-]+/
/*!
* lunr.Pipeline
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
@@ -475,14 +668,23 @@ lunr.Pipeline.prototype.run = function (tokens) {
for (var i = 0; i < stackLength; i++) {
var fn = this._stack[i]
+ var memo = []
- tokens = tokens.reduce(function (memo, token, j) {
- var result = fn(token, j, tokens)
+ for (var j = 0; j < tokens.length; j++) {
+ var result = fn(tokens[j], j, tokens)
- if (result === void 0 || result === '') return memo
+ if (result === void 0 || result === '') continue
+
+ if (result instanceof Array) {
+ for (var k = 0; k < result.length; k++) {
+ memo.push(result[k])
+ }
+ } else {
+ memo.push(result)
+ }
+ }
- return memo.concat(result)
- }, [])
+ tokens = memo
}
return tokens
@@ -494,10 +696,12 @@ lunr.Pipeline.prototype.run = function (tokens) {
* token and mapping the resulting tokens back to strings.
*
* @param {string} str - The string to pass through the pipeline.
+ * @param {?object} metadata - Optional metadata to associate with the token
+ * passed to the pipeline.
* @returns {string[]}
*/
-lunr.Pipeline.prototype.runString = function (str) {
- var token = new lunr.Token (str)
+lunr.Pipeline.prototype.runString = function (str, metadata) {
+ var token = new lunr.Token (str, metadata)
return this.run([token]).map(function (t) {
return t.toString()
@@ -528,7 +732,7 @@ lunr.Pipeline.prototype.toJSON = function () {
}
/*!
* lunr.Vector
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
@@ -689,15 +893,14 @@ lunr.Vector.prototype.dot = function (otherVector) {
}
/**
- * Calculates the cosine similarity between this vector and another
- * vector.
+ * Calculates the similarity between this vector and another vector.
*
* @param {lunr.Vector} otherVector - The other vector to calculate the
* similarity with.
* @returns {Number}
*/
lunr.Vector.prototype.similarity = function (otherVector) {
- return this.dot(otherVector) / (this.magnitude() * otherVector.magnitude())
+ return this.dot(otherVector) / this.magnitude() || 0
}
/**
@@ -726,7 +929,7 @@ lunr.Vector.prototype.toJSON = function () {
/* eslint-disable */
/*!
* lunr.stemmer
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
* Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
*/
@@ -739,6 +942,7 @@ lunr.Vector.prototype.toJSON = function () {
* @param {lunr.Token} token - The string to stem
* @returns {lunr.Token}
* @see {@link lunr.Pipeline}
+ * @function
*/
lunr.stemmer = (function(){
var step2list = {
@@ -947,7 +1151,7 @@ lunr.stemmer = (function(){
lunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer')
/*!
* lunr.stopWordFilter
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
@@ -957,6 +1161,7 @@ lunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer')
* The built in lunr.stopWordFilter is built using this generator and can be used
* to generate custom stopWordFilters for applications or non English languages.
*
+ * @function
* @param {Array} token The token to pass through the filter
* @returns {lunr.PipelineFunction}
* @see lunr.Pipeline
@@ -980,6 +1185,7 @@ lunr.generateStopWordFilter = function (stopWords) {
* This is intended to be used in the Pipeline. If the token does not pass the
* filter then undefined will be returned.
*
+ * @function
* @implements {lunr.PipelineFunction}
* @params {lunr.Token} token - A token to check for being a stop word.
* @returns {lunr.Token}
@@ -1110,7 +1316,7 @@ lunr.stopWordFilter = lunr.generateStopWordFilter([
lunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter')
/*!
* lunr.trimmer
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
@@ -1137,7 +1343,7 @@ lunr.trimmer = function (token) {
lunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer')
/*!
* lunr.TokenSet
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
@@ -1379,14 +1585,13 @@ lunr.TokenSet.fromFuzzyString = function (str, editDistance) {
*/
lunr.TokenSet.fromString = function (str) {
var node = new lunr.TokenSet,
- root = node,
- wildcardFound = false
+ root = node
/*
* Iterates through all characters within the passed string
* appending a node for each character.
*
- * As soon as a wildcard character is found then a self
+ * When a wildcard character is found then a self
* referencing edge is introduced to continually match
* any number of any characters.
*/
@@ -1395,7 +1600,6 @@ lunr.TokenSet.fromString = function (str) {
final = (i == len - 1)
if (char == "*") {
- wildcardFound = true
node.edges[char] = node
node.final = final
@@ -1405,11 +1609,6 @@ lunr.TokenSet.fromString = function (str) {
node.edges[char] = next
node = next
-
- // TODO: is this needed anymore?
- if (wildcardFound) {
- node.edges["*"] = root
- }
}
}
@@ -1436,6 +1635,11 @@ lunr.TokenSet.prototype.toArray = function () {
len = edges.length
if (frame.node.final) {
+ /* In Safari, at this point the prefix is sometimes corrupted, see:
+ * https://github.com/olivernn/lunr.js/issues/279 Calling any
+ * String.prototype method forces Safari to "cast" this string to what
+ * it's supposed to be, fixing the bug. */
+ frame.prefix.charAt(0)
words.push(frame.prefix)
}
@@ -1632,7 +1836,7 @@ lunr.TokenSet.Builder.prototype.minimize = function (downTo) {
}
/*!
* lunr.Index
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
@@ -1646,7 +1850,7 @@ lunr.TokenSet.Builder.prototype.minimize = function (downTo) {
* @constructor
* @param {Object} attrs - The attributes of the built search index.
* @param {Object} attrs.invertedIndex - An index of term/field to document reference.
- * @param {Object} attrs.documentVectors - Document vectors keyed by document reference.
+ * @param {Object} attrs.fieldVectors - Field vectors
* @param {lunr.TokenSet} attrs.tokenSet - An set of all corpus tokens.
* @param {string[]} attrs.fields - The names of indexed document fields.
* @param {lunr.Pipeline} attrs.pipeline - The pipeline to use for search terms.
@@ -1692,6 +1896,12 @@ lunr.Index = function (attrs) {
* to provide fuzzy matching, e.g. 'hello~2' will match documents with hello with an edit distance of 2.
* Avoid large values for edit distance to improve query performance.
*
+ * Each term also supports a presence modifier. By default a term's presence in document is optional, however
+ * this can be changed to either required or prohibited. For a term's presence to be required in a document the
+ * term should be prefixed with a '+', e.g. `+foo bar` is a search for documents that must contain 'foo' and
+ * optionally contain 'bar'. Conversely a leading '-' sets the terms presence to prohibited, i.e. it must not
+ * appear in a document, e.g. `-foo bar` is a search for documents that do not contain 'foo' but may contain 'bar'.
+ *
* To escape special characters the backslash character '\' can be used, this allows searches to include
* characters that would normally be considered modifiers, e.g. `foo\~2` will search for a term "foo~2" instead
* of attempting to apply a boost of 2 to the search term "foo".
@@ -1707,13 +1917,16 @@ lunr.Index = function (attrs) {
* hello^10
* @example term with an edit distance of 2
* hello~2
+ * @example terms with presence modifiers
+ * -foo +bar baz
*/
/**
* Performs a search against the index using lunr query syntax.
*
* Results will be returned sorted by their score, the most relevant results
- * will be returned first.
+ * will be returned first. For details on how the score is calculated, please see
+ * the {@link https://lunrjs.com/guides/searching.html#scoring|guide}.
*
* For more programmatic querying use lunr.Index#query.
*
@@ -1764,7 +1977,18 @@ lunr.Index.prototype.query = function (fn) {
var query = new lunr.Query(this.fields),
matchingFields = Object.create(null),
queryVectors = Object.create(null),
- termFieldCache = Object.create(null)
+ termFieldCache = Object.create(null),
+ requiredMatches = Object.create(null),
+ prohibitedMatches = Object.create(null)
+
+ /*
+ * To support field level boosts a query vector is created per
+ * field. An empty vector is eagerly created to support negated
+ * queries.
+ */
+ for (var i = 0; i < this.fields.length; i++) {
+ queryVectors[this.fields[i]] = new lunr.Vector
+ }
fn.call(query, query)
@@ -1778,10 +2002,13 @@ lunr.Index.prototype.query = function (fn) {
* for a single query term.
*/
var clause = query.clauses[i],
- terms = null
+ terms = null,
+ clauseMatches = lunr.Set.complete
if (clause.usePipeline) {
- terms = this.pipeline.runString(clause.term)
+ terms = this.pipeline.runString(clause.term, {
+ fields: clause.fields
+ })
} else {
terms = [clause.term]
}
@@ -1805,6 +2032,21 @@ lunr.Index.prototype.query = function (fn) {
var termTokenSet = lunr.TokenSet.fromClause(clause),
expandedTerms = this.tokenSet.intersect(termTokenSet).toArray()
+ /*
+ * If a term marked as required does not exist in the tokenSet it is
+ * impossible for the search to return any matches. We set all the field
+ * scoped required matches set to empty and stop examining any further
+ * clauses.
+ */
+ if (expandedTerms.length === 0 && clause.presence === lunr.Query.presence.REQUIRED) {
+ for (var k = 0; k < clause.fields.length; k++) {
+ var field = clause.fields[k]
+ requiredMatches[field] = lunr.Set.empty
+ }
+
+ break
+ }
+
for (var j = 0; j < expandedTerms.length; j++) {
/*
* For each term get the posting and termIndex, this is required for
@@ -1826,26 +2068,50 @@ lunr.Index.prototype.query = function (fn) {
var field = clause.fields[k],
fieldPosting = posting[field],
matchingDocumentRefs = Object.keys(fieldPosting),
- termField = expandedTerm + "/" + field
+ termField = expandedTerm + "/" + field,
+ matchingDocumentsSet = new lunr.Set(matchingDocumentRefs)
/*
- * To support field level boosts a query vector is created per
- * field. This vector is populated using the termIndex found for
- * the term and a unit value with the appropriate boost applied.
+ * if the presence of this term is required ensure that the matching
+ * documents are added to the set of required matches for this clause.
*
- * If the query vector for this field does not exist yet it needs
- * to be created.
*/
- if (queryVectors[field] === undefined) {
- queryVectors[field] = new lunr.Vector
+ if (clause.presence == lunr.Query.presence.REQUIRED) {
+ clauseMatches = clauseMatches.union(matchingDocumentsSet)
+
+ if (requiredMatches[field] === undefined) {
+ requiredMatches[field] = lunr.Set.complete
+ }
+ }
+
+ /*
+ * if the presence of this term is prohibited ensure that the matching
+ * documents are added to the set of prohibited matches for this field,
+ * creating that set if it does not yet exist.
+ */
+ if (clause.presence == lunr.Query.presence.PROHIBITED) {
+ if (prohibitedMatches[field] === undefined) {
+ prohibitedMatches[field] = lunr.Set.empty
+ }
+
+ prohibitedMatches[field] = prohibitedMatches[field].union(matchingDocumentsSet)
+
+ /*
+ * Prohibited matches should not be part of the query vector used for
+ * similarity scoring and no metadata should be extracted so we continue
+ * to the next field
+ */
+ continue
}
/*
+ * The query field vector is populated using the termIndex found for
+ * the term and a unit value with the appropriate boost applied.
* Using upsert because there could already be an entry in the vector
* for the term we are working with. In that case we just add the scores
* together.
*/
- queryVectors[field].upsert(termIndex, 1 * clause.boost, function (a, b) { return a + b })
+ queryVectors[field].upsert(termIndex, clause.boost, function (a, b) { return a + b })
/**
* If we've already seen this term, field combo then we've already collected
@@ -1879,12 +2145,65 @@ lunr.Index.prototype.query = function (fn) {
}
}
}
+
+ /**
+ * If the presence was required we need to update the requiredMatches field sets.
+ * We do this after all fields for the term have collected their matches because
+ * the clause terms presence is required in _any_ of the fields not _all_ of the
+ * fields.
+ */
+ if (clause.presence === lunr.Query.presence.REQUIRED) {
+ for (var k = 0; k < clause.fields.length; k++) {
+ var field = clause.fields[k]
+ requiredMatches[field] = requiredMatches[field].intersect(clauseMatches)
+ }
+ }
+ }
+
+ /**
+ * Need to combine the field scoped required and prohibited
+ * matching documents into a global set of required and prohibited
+ * matches
+ */
+ var allRequiredMatches = lunr.Set.complete,
+ allProhibitedMatches = lunr.Set.empty
+
+ for (var i = 0; i < this.fields.length; i++) {
+ var field = this.fields[i]
+
+ if (requiredMatches[field]) {
+ allRequiredMatches = allRequiredMatches.intersect(requiredMatches[field])
+ }
+
+ if (prohibitedMatches[field]) {
+ allProhibitedMatches = allProhibitedMatches.union(prohibitedMatches[field])
+ }
}
var matchingFieldRefs = Object.keys(matchingFields),
results = [],
matches = Object.create(null)
+ /*
+ * If the query is negated (contains only prohibited terms)
+ * we need to get _all_ fieldRefs currently existing in the
+ * index. This is only done when we know that the query is
+ * entirely prohibited terms to avoid any cost of getting all
+ * fieldRefs unnecessarily.
+ *
+ * Additionally, blank MatchData must be created to correctly
+ * populate the results.
+ */
+ if (query.isNegated()) {
+ matchingFieldRefs = Object.keys(this.fieldVectors)
+
+ for (var i = 0; i < matchingFieldRefs.length; i++) {
+ var matchingFieldRef = matchingFieldRefs[i]
+ var fieldRef = lunr.FieldRef.fromString(matchingFieldRef)
+ matchingFields[matchingFieldRef] = new lunr.MatchData
+ }
+ }
+
for (var i = 0; i < matchingFieldRefs.length; i++) {
/*
* Currently we have document fields that match the query, but we
@@ -1895,8 +2214,17 @@ lunr.Index.prototype.query = function (fn) {
* above, and combined into a final document score using addition.
*/
var fieldRef = lunr.FieldRef.fromString(matchingFieldRefs[i]),
- docRef = fieldRef.docRef,
- fieldVector = this.fieldVectors[fieldRef],
+ docRef = fieldRef.docRef
+
+ if (!allRequiredMatches.contains(docRef)) {
+ continue
+ }
+
+ if (allProhibitedMatches.contains(docRef)) {
+ continue
+ }
+
+ var fieldVector = this.fieldVectors[fieldRef],
score = queryVectors[fieldRef.fieldName].similarity(fieldVector),
docMatch
@@ -2000,7 +2328,7 @@ lunr.Index.load = function (serializedIndex) {
}
/*!
* lunr.Builder
- * Copyright (C) 2017 Oliver Nightingale
+ * Copyright (C) 2018 Oliver Nightingale
*/
/**
@@ -2029,7 +2357,8 @@ lunr.Index.load = function (serializedIndex) {
*/
lunr.Builder = function () {
this._ref = "id"
- this._fields = []
+ this._fields = Object.create(null)
+ this._documents = Object.create(null)
this.invertedIndex = Object.create(null)
this.fieldTermFrequencies = {}
this.fieldLengths = {}
@@ -2059,6 +2388,20 @@ lunr.Builder.prototype.ref = function (ref) {
this._ref = ref
}
+/**
+ * A function that is used to extract a field from a document.
+ *
+ * Lunr expects a field to be at the top level of a document, if however the field
+ * is deeply nested within a document an extractor function can be used to extract
+ * the right field for indexing.
+ *
+ * @callback fieldExtractor
+ * @param {object} doc - The document being added to the index.
+ * @returns {?(string|object|object[])} obj - The object that will be indexed for this field.
+ * @example Extracting a nested field
+ * function (doc) { return doc.nested.field }
+ */
+
/**
* Adds a field to the list of document fields that will be indexed. Every document being
* indexed should have this field. Null values for this field in indexed documents will
@@ -2067,10 +2410,22 @@ lunr.Builder.prototype.ref = function (ref) {
* All fields should be added before adding documents to the index. Adding fields after
* a document has been indexed will have no effect on already indexed documents.
*
- * @param {string} field - The name of a field to index in all documents.
+ * Fields can be boosted at build time. This allows terms within that field to have more
+ * importance when ranking search results. Use a field boost to specify that matches within
+ * one field are more important than other fields.
+ *
+ * @param {string} fieldName - The name of a field to index in all documents.
+ * @param {object} attributes - Optional attributes associated with this field.
+ * @param {number} [attributes.boost=1] - Boost applied to all terms within this field.
+ * @param {fieldExtractor} [attributes.extractor] - Function to extract a field from a document.
+ * @throws {RangeError} fieldName cannot contain unsupported characters '/'
*/
-lunr.Builder.prototype.field = function (field) {
- this._fields.push(field)
+lunr.Builder.prototype.field = function (fieldName, attributes) {
+ if (/\//.test(fieldName)) {
+ throw new RangeError ("Field '" + fieldName + "' contains illegal character '/'")
+ }
+
+ this._fields[fieldName] = attributes || {}
}
/**
@@ -2112,17 +2467,27 @@ lunr.Builder.prototype.k1 = function (number) {
* it should have all fields defined for indexing, though null or undefined values will not
* cause errors.
*
+ * Entire documents can be boosted at build time. Applying a boost to a document indicates that
+ * this document should rank higher in search results than other documents.
+ *
* @param {object} doc - The document to add to the index.
+ * @param {object} attributes - Optional attributes associated with this document.
+ * @param {number} [attributes.boost=1] - Boost applied to all terms within this document.
*/
-lunr.Builder.prototype.add = function (doc) {
- var docRef = doc[this._ref]
+lunr.Builder.prototype.add = function (doc, attributes) {
+ var docRef = doc[this._ref],
+ fields = Object.keys(this._fields)
+ this._documents[docRef] = attributes || {}
this.documentCount += 1
- for (var i = 0; i < this._fields.length; i++) {
- var fieldName = this._fields[i],
- field = doc[fieldName],
- tokens = this.tokenizer(field),
+ for (var i = 0; i < fields.length; i++) {
+ var fieldName = fields[i],
+ extractor = this._fields[fieldName].extractor,
+ field = extractor ? extractor(doc) : doc[fieldName],
+ tokens = this.tokenizer(field, {
+ fields: [fieldName]
+ }),
terms = this.pipeline.run(tokens),
fieldRef = new lunr.FieldRef (docRef, fieldName),
fieldTerms = Object.create(null)
@@ -2150,8 +2515,8 @@ lunr.Builder.prototype.add = function (doc) {
posting["_index"] = this.termIndex
this.termIndex += 1
- for (var k = 0; k < this._fields.length; k++) {
- posting[this._fields[k]] = Object.create(null)
+ for (var k = 0; k < fields.length; k++) {
+ posting[fields[k]] = Object.create(null)
}
this.invertedIndex[term] = posting
@@ -2202,9 +2567,11 @@ lunr.Builder.prototype.calculateAverageFieldLengths = function () {
accumulator[field] += this.fieldLengths[fieldRef]
}
- for (var i = 0; i < this._fields.length; i++) {
- var field = this._fields[i]
- accumulator[field] = accumulator[field] / documentsWithField[field]
+ var fields = Object.keys(this._fields)
+
+ for (var i = 0; i < fields.length; i++) {
+ var fieldName = fields[i]
+ accumulator[fieldName] = accumulator[fieldName] / documentsWithField[fieldName]
}
this.averageFieldLength = accumulator
@@ -2223,13 +2590,17 @@ lunr.Builder.prototype.createFieldVectors = function () {
for (var i = 0; i < fieldRefsLength; i++) {
var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),
- field = fieldRef.fieldName,
+ fieldName = fieldRef.fieldName,
fieldLength = this.fieldLengths[fieldRef],
fieldVector = new lunr.Vector,
termFrequencies = this.fieldTermFrequencies[fieldRef],
terms = Object.keys(termFrequencies),
termsLength = terms.length
+
+ var fieldBoost = this._fields[fieldName].boost || 1,
+ docBoost = this._documents[fieldRef.docRef].boost || 1
+
for (var j = 0; j < termsLength; j++) {
var term = terms[j],
tf = termFrequencies[term],
@@ -2243,7 +2614,9 @@ lunr.Builder.prototype.createFieldVectors = function () {
idf = termIdfCache[term]
}
- score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[field])) + tf)
+ score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[fieldName])) + tf)
+ score *= fieldBoost
+ score *= docBoost
scoreWithPrecision = Math.round(score * 1000) / 1000
// Converts 1.23456789 to 1.234.
// Reducing the precision so that the vectors take up less
@@ -2289,7 +2662,7 @@ lunr.Builder.prototype.build = function () {
invertedIndex: this.invertedIndex,
fieldVectors: this.fieldVectors,
tokenSet: this.tokenSet,
- fields: this._fields,
+ fields: Object.keys(this._fields),
pipeline: this.searchPipeline
})
}
@@ -2327,7 +2700,7 @@ lunr.Builder.prototype.use = function (fn) {
*/
lunr.MatchData = function (term, field, metadata) {
var clonedMetadata = Object.create(null),
- metadataKeys = Object.keys(metadata)
+ metadataKeys = Object.keys(metadata || {})
// Cloning the metadata to prevent the original
// being mutated during match data combination.
@@ -2340,8 +2713,11 @@ lunr.MatchData = function (term, field, metadata) {
}
this.metadata = Object.create(null)
- this.metadata[term] = Object.create(null)
- this.metadata[term][field] = clonedMetadata
+
+ if (term !== undefined) {
+ this.metadata[term] = Object.create(null)
+ this.metadata[term][field] = clonedMetadata
+ }
}
/**
@@ -2456,11 +2832,42 @@ lunr.Query = function (allFields) {
* wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING
* })
*/
+
lunr.Query.wildcard = new String ("*")
lunr.Query.wildcard.NONE = 0
lunr.Query.wildcard.LEADING = 1
lunr.Query.wildcard.TRAILING = 2
+/**
+ * Constants for indicating what kind of presence a term must have in matching documents.
+ *
+ * @constant
+ * @enum {number}
+ * @see lunr.Query~Clause
+ * @see lunr.Query#clause
+ * @see lunr.Query#term
+ * @example query term with required presence
+ * query.term('foo', { presence: lunr.Query.presence.REQUIRED })
+ */
+lunr.Query.presence = {
+ /**
+ * Term's presence in a document is optional, this is the default value.
+ */
+ OPTIONAL: 1,
+
+ /**
+ * Term's presence in a document is required, documents that do not contain
+ * this term will not be returned.
+ */
+ REQUIRED: 2,
+
+ /**
+ * Term's presence in a document is prohibited, documents that do contain
+ * this term will not be returned.
+ */
+ PROHIBITED: 3
+}
+
/**
* A single clause in a {@link lunr.Query} contains a term and details on how to
* match that term against a {@link lunr.Index}.
@@ -2470,7 +2877,8 @@ lunr.Query.wildcard.TRAILING = 2
* @property {number} [boost=1] - Any boost that should be applied when matching this clause.
* @property {number} [editDistance] - Whether the term should have fuzzy matching applied, and how fuzzy the match should be.
* @property {boolean} [usePipeline] - Whether the term should be passed through the search pipeline.
- * @property {number} [wildcard=0] - Whether the term should have wildcards appended or prepended.
+ * @property {number} [wildcard=lunr.Query.wildcard.NONE] - Whether the term should have wildcards appended or prepended.
+ * @property {number} [presence=lunr.Query.presence.OPTIONAL] - The terms presence in any matching documents.
*/
/**
@@ -2508,17 +2916,44 @@ lunr.Query.prototype.clause = function (clause) {
clause.term = "" + clause.term + "*"
}
+ if (!('presence' in clause)) {
+ clause.presence = lunr.Query.presence.OPTIONAL
+ }
+
this.clauses.push(clause)
return this
}
+/**
+ * A negated query is one in which every clause has a presence of
+ * prohibited. These queries require some special processing to return
+ * the expected results.
+ *
+ * @returns boolean
+ */
+lunr.Query.prototype.isNegated = function () {
+ for (var i = 0; i < this.clauses.length; i++) {
+ if (this.clauses[i].presence != lunr.Query.presence.PROHIBITED) {
+ return false
+ }
+ }
+
+ return true
+}
+
/**
* Adds a term to the current query, under the covers this will create a {@link lunr.Query~Clause}
* to the list of clauses that make up this query.
*
- * @param {string} term - The term to add to the query.
- * @param {Object} [options] - Any additional properties to add to the query clause.
+ * The term is used as is, i.e. no tokenization will be performed by this method. Instead conversion
+ * to a token or token-like string should be done before calling this method.
+ *
+ * The term will be converted to a string by calling `toString`. Multiple terms can be passed as an
+ * array, each term in the array will share the same options.
+ *
+ * @param {object|object[]} term - The term(s) to add to the query.
+ * @param {object} [options] - Any additional properties to add to the query clause.
* @returns {lunr.Query}
* @see lunr.Query#clause
* @see lunr.Query~Clause
@@ -2530,10 +2965,17 @@ lunr.Query.prototype.clause = function (clause) {
* boost: 10,
* wildcard: lunr.Query.wildcard.TRAILING
* })
+ * @example using lunr.tokenizer to convert a string to tokens before using them as terms
+ * query.term(lunr.tokenizer("foo bar"))
*/
lunr.Query.prototype.term = function (term, options) {
+ if (Array.isArray(term)) {
+ term.forEach(function (t) { this.term(t, lunr.utils.clone(options)) }, this)
+ return this
+ }
+
var clause = options || {}
- clause.term = term
+ clause.term = term.toString()
this.clause(clause)
@@ -2645,6 +3087,7 @@ lunr.QueryLexer.FIELD = 'FIELD'
lunr.QueryLexer.TERM = 'TERM'
lunr.QueryLexer.EDIT_DISTANCE = 'EDIT_DISTANCE'
lunr.QueryLexer.BOOST = 'BOOST'
+lunr.QueryLexer.PRESENCE = 'PRESENCE'
lunr.QueryLexer.lexField = function (lexer) {
lexer.backup()
@@ -2733,6 +3176,22 @@ lunr.QueryLexer.lexText = function (lexer) {
return lunr.QueryLexer.lexBoost
}
+ // "+" indicates term presence is required
+ // checking for length to ensure that only
+ // leading "+" are considered
+ if (char == "+" && lexer.width() === 1) {
+ lexer.emit(lunr.QueryLexer.PRESENCE)
+ return lunr.QueryLexer.lexText
+ }
+
+ // "-" indicates term presence is prohibited
+ // checking for length to ensure that only
+ // leading "-" are considered
+ if (char == "-" && lexer.width() === 1) {
+ lexer.emit(lunr.QueryLexer.PRESENCE)
+ return lunr.QueryLexer.lexText
+ }
+
if (char.match(lunr.QueryLexer.termSeparator)) {
return lunr.QueryLexer.lexTerm
}
@@ -2750,7 +3209,7 @@ lunr.QueryParser.prototype.parse = function () {
this.lexer.run()
this.lexemes = this.lexer.lexemes
- var state = lunr.QueryParser.parseFieldOrTerm
+ var state = lunr.QueryParser.parseClause
while (state) {
state = state(this)
@@ -2775,7 +3234,7 @@ lunr.QueryParser.prototype.nextClause = function () {
this.currentClause = {}
}
-lunr.QueryParser.parseFieldOrTerm = function (parser) {
+lunr.QueryParser.parseClause = function (parser) {
var lexeme = parser.peekLexeme()
if (lexeme == undefined) {
@@ -2783,6 +3242,8 @@ lunr.QueryParser.parseFieldOrTerm = function (parser) {
}
switch (lexeme.type) {
+ case lunr.QueryLexer.PRESENCE:
+ return lunr.QueryParser.parsePresence
case lunr.QueryLexer.FIELD:
return lunr.QueryParser.parseField
case lunr.QueryLexer.TERM:
@@ -2798,6 +3259,43 @@ lunr.QueryParser.parseFieldOrTerm = function (parser) {
}
}
+lunr.QueryParser.parsePresence = function (parser) {
+ var lexeme = parser.consumeLexeme()
+
+ if (lexeme == undefined) {
+ return
+ }
+
+ switch (lexeme.str) {
+ case "-":
+ parser.currentClause.presence = lunr.Query.presence.PROHIBITED
+ break
+ case "+":
+ parser.currentClause.presence = lunr.Query.presence.REQUIRED
+ break
+ default:
+ var errorMessage = "unrecognised presence operator'" + lexeme.str + "'"
+ throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
+ }
+
+ var nextLexeme = parser.peekLexeme()
+
+ if (nextLexeme == undefined) {
+ var errorMessage = "expecting term or field, found nothing"
+ throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)
+ }
+
+ switch (nextLexeme.type) {
+ case lunr.QueryLexer.FIELD:
+ return lunr.QueryParser.parseField
+ case lunr.QueryLexer.TERM:
+ return lunr.QueryParser.parseTerm
+ default:
+ var errorMessage = "expecting term or field, found '" + nextLexeme.type + "'"
+ throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
+ }
+}
+
lunr.QueryParser.parseField = function (parser) {
var lexeme = parser.consumeLexeme()
@@ -2861,6 +3359,9 @@ lunr.QueryParser.parseTerm = function (parser) {
return lunr.QueryParser.parseEditDistance
case lunr.QueryLexer.BOOST:
return lunr.QueryParser.parseBoost
+ case lunr.QueryLexer.PRESENCE:
+ parser.nextClause()
+ return lunr.QueryParser.parsePresence
default:
var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'"
throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
@@ -2901,6 +3402,9 @@ lunr.QueryParser.parseEditDistance = function (parser) {
return lunr.QueryParser.parseEditDistance
case lunr.QueryLexer.BOOST:
return lunr.QueryParser.parseBoost
+ case lunr.QueryLexer.PRESENCE:
+ parser.nextClause()
+ return lunr.QueryParser.parsePresence
default:
var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'"
throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
@@ -2941,6 +3445,9 @@ lunr.QueryParser.parseBoost = function (parser) {
return lunr.QueryParser.parseEditDistance
case lunr.QueryLexer.BOOST:
return lunr.QueryParser.parseBoost
+ case lunr.QueryLexer.PRESENCE:
+ parser.nextClause()
+ return lunr.QueryParser.parsePresence
default:
var errorMessage = "Unexpected lexeme type '" + nextLexeme.type + "'"
throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)
@@ -2974,4 +3481,4 @@ lunr.QueryParser.parseBoost = function (parser) {
*/
return lunr
}))
-})();
+})();
\ No newline at end of file
diff --git a/assets/js/lunr/lunr.min.js b/assets/js/lunr/lunr.min.js
index 75f6a2b749be..4c1012760a63 100644
--- a/assets/js/lunr/lunr.min.js
+++ b/assets/js/lunr/lunr.min.js
@@ -1,6 +1,6 @@
/**
- * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.1.5
- * Copyright (C) 2017 Oliver Nightingale
+ * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.3
+ * Copyright (C) 2018 Oliver Nightingale
* @license MIT
*/
-!function(){var e=function(t){var r=new e.Builder;return r.pipeline.add(e.trimmer,e.stopWordFilter,e.stemmer),r.searchPipeline.add(e.stemmer),t.call(r,r),r.build()};e.version="2.1.5",e.utils={},e.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),e.utils.asString=function(e){return void 0===e||null===e?"":e.toString()},e.FieldRef=function(e,t,r){this.docRef=e,this.fieldName=t,this._stringValue=r},e.FieldRef.joiner="/",e.FieldRef.fromString=function(t){var r=t.indexOf(e.FieldRef.joiner);if(-1===r)throw"malformed field ref string";var i=t.slice(0,r),n=t.slice(r+1);return new e.FieldRef(n,i,t)},e.FieldRef.prototype.toString=function(){return void 0==this._stringValue&&(this._stringValue=this.fieldName+e.FieldRef.joiner+this.docRef),this._stringValue},e.idf=function(e,t){var r=0;for(var i in e)"_index"!=i&&(r+=Object.keys(e[i]).length);var n=(t-r+.5)/(r+.5);return Math.log(1+Math.abs(n))},e.Token=function(e,t){this.str=e||"",this.metadata=t||{}},e.Token.prototype.toString=function(){return this.str},e.Token.prototype.update=function(e){return this.str=e(this.str,this.metadata),this},e.Token.prototype.clone=function(t){return t=t||function(e){return e},new e.Token(t(this.str,this.metadata),this.metadata)},e.tokenizer=function(t){if(null==t||void 0==t)return[];if(Array.isArray(t))return t.map(function(t){return new e.Token(e.utils.asString(t).toLowerCase())});for(var r=t.toString().trim().toLowerCase(),i=r.length,n=[],s=0,o=0;i>=s;s++){var a=r.charAt(s),u=s-o;(a.match(e.tokenizer.separator)||s==i)&&(u>0&&n.push(new e.Token(r.slice(o,s),{position:[o,u],index:n.length})),o=s+1)}return n},e.tokenizer.separator=/[\s\-]+/,e.Pipeline=function(){this._stack=[]},e.Pipeline.registeredFunctions=Object.create(null),e.Pipeline.registerFunction=function(t,r){r in this.registeredFunctions&&e.utils.warn("Overwriting existing registered function: "+r),t.label=r,e.Pipeline.registeredFunctions[t.label]=t},e.Pipeline.warnIfFunctionNotRegistered=function(t){var r=t.label&&t.label in this.registeredFunctions;r||e.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",t)},e.Pipeline.load=function(t){var r=new e.Pipeline;return t.forEach(function(t){var i=e.Pipeline.registeredFunctions[t];if(!i)throw new Error("Cannot load unregistered function: "+t);r.add(i)}),r},e.Pipeline.prototype.add=function(){var t=Array.prototype.slice.call(arguments);t.forEach(function(t){e.Pipeline.warnIfFunctionNotRegistered(t),this._stack.push(t)},this)},e.Pipeline.prototype.after=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(-1==i)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,r)},e.Pipeline.prototype.before=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(-1==i)throw new Error("Cannot find existingFn");this._stack.splice(i,0,r)},e.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},e.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;t>r;r++){var i=this._stack[r];e=e.reduce(function(t,r,n){var s=i(r,n,e);return void 0===s||""===s?t:t.concat(s)},[])}return e},e.Pipeline.prototype.runString=function(t){var r=new e.Token(t);return this.run([r]).map(function(e){return e.toString()})},e.Pipeline.prototype.reset=function(){this._stack=[]},e.Pipeline.prototype.toJSON=function(){return this._stack.map(function(t){return e.Pipeline.warnIfFunctionNotRegistered(t),t.label})},e.Vector=function(e){this._magnitude=0,this.elements=e||[]},e.Vector.prototype.positionForIndex=function(e){if(0==this.elements.length)return 0;for(var t=0,r=this.elements.length/2,i=r-t,n=Math.floor(i/2),s=this.elements[2*n];i>1&&(e>s&&(t=n),s>e&&(r=n),s!=e);)i=r-t,n=t+Math.floor(i/2),s=this.elements[2*n];return s==e?2*n:s>e?2*n:e>s?2*(n+1):void 0},e.Vector.prototype.insert=function(e,t){this.upsert(e,t,function(){throw"duplicate index"})},e.Vector.prototype.upsert=function(e,t,r){this._magnitude=0;var i=this.positionForIndex(e);this.elements[i]==e?this.elements[i+1]=r(this.elements[i+1],t):this.elements.splice(i,0,e,t)},e.Vector.prototype.magnitude=function(){if(this._magnitude)return this._magnitude;for(var e=0,t=this.elements.length,r=1;t>r;r+=2){var i=this.elements[r];e+=i*i}return this._magnitude=Math.sqrt(e)},e.Vector.prototype.dot=function(e){for(var t=0,r=this.elements,i=e.elements,n=r.length,s=i.length,o=0,a=0,u=0,l=0;n>u&&s>l;)o=r[u],a=i[l],a>o?u+=2:o>a?l+=2:o==a&&(t+=r[u+1]*i[l+1],u+=2,l+=2);return t},e.Vector.prototype.similarity=function(e){return this.dot(e)/(this.magnitude()*e.magnitude())},e.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;ti;i++)r.insert(t[i]);return r.finish(),r.root},e.TokenSet.fromClause=function(t){return"editDistance"in t?e.TokenSet.fromFuzzyString(t.term,t.editDistance):e.TokenSet.fromString(t.term)},e.TokenSet.fromFuzzyString=function(t,r){for(var i=new e.TokenSet,n=[{node:i,editsRemaining:r,str:t}];n.length;){var s=n.pop();if(s.str.length>0){var o,a=s.str.charAt(0);a in s.node.edges?o=s.node.edges[a]:(o=new e.TokenSet,s.node.edges[a]=o),1==s.str.length?o["final"]=!0:n.push({node:o,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining>0&&s.str.length>1){var u,a=s.str.charAt(1);a in s.node.edges?u=s.node.edges[a]:(u=new e.TokenSet,s.node.edges[a]=u),s.str.length<=2?u["final"]=!0:n.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(2)})}if(s.editsRemaining>0&&1==s.str.length&&(s.node["final"]=!0),s.editsRemaining>0&&s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new e.TokenSet;s.node.edges["*"]=l}1==s.str.length?l["final"]=!0:n.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.editsRemaining>0){if("*"in s.node.edges)var d=s.node.edges["*"];else{var d=new e.TokenSet;s.node.edges["*"]=d}0==s.str.length?d["final"]=!0:n.push({node:d,editsRemaining:s.editsRemaining-1,str:s.str})}if(s.editsRemaining>0&&s.str.length>1){var h,c=s.str.charAt(0),f=s.str.charAt(1);f in s.node.edges?h=s.node.edges[f]:(h=new e.TokenSet,s.node.edges[f]=h),1==s.str.length?h["final"]=!0:n.push({node:h,editsRemaining:s.editsRemaining-1,str:c+s.str.slice(2)})}}return i},e.TokenSet.fromString=function(t){for(var r=new e.TokenSet,i=r,n=!1,s=0,o=t.length;o>s;s++){var a=t[s],u=s==o-1;if("*"==a)n=!0,r.edges[a]=r,r["final"]=u;else{var l=new e.TokenSet;l["final"]=u,r.edges[a]=l,r=l,n&&(r.edges["*"]=i)}}return i},e.TokenSet.prototype.toArray=function(){for(var e=[],t=[{prefix:"",node:this}];t.length;){var r=t.pop(),i=Object.keys(r.node.edges),n=i.length;r.node["final"]&&e.push(r.prefix);for(var s=0;n>s;s++){var o=i[s];t.push({prefix:r.prefix.concat(o),node:r.node.edges[o]})}}return e},e.TokenSet.prototype.toString=function(){if(this._str)return this._str;for(var e=this["final"]?"1":"0",t=Object.keys(this.edges).sort(),r=t.length,i=0;r>i;i++){var n=t[i],s=this.edges[n];e=e+n+s.id}return e},e.TokenSet.prototype.intersect=function(t){for(var r=new e.TokenSet,i=void 0,n=[{qNode:t,output:r,node:this}];n.length;){i=n.pop();for(var s=Object.keys(i.qNode.edges),o=s.length,a=Object.keys(i.node.edges),u=a.length,l=0;o>l;l++)for(var d=s[l],h=0;u>h;h++){var c=a[h];if(c==d||"*"==d){var f=i.node.edges[c],p=i.qNode.edges[d],y=f["final"]&&p["final"],m=void 0;c in i.output.edges?(m=i.output.edges[c],m["final"]=m["final"]||y):(m=new e.TokenSet,m["final"]=y,i.output.edges[c]=m),n.push({qNode:p,output:m,node:f})}}}return r},e.TokenSet.Builder=function(){this.previousWord="",this.root=new e.TokenSet,this.uncheckedNodes=[],this.minimizedNodes={}},e.TokenSet.Builder.prototype.insert=function(t){var r,i=0;if(t=e;t--){var r=this.uncheckedNodes[t],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r["char"]]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}},e.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},e.Index.prototype.search=function(t){return this.query(function(r){var i=new e.QueryParser(t,r);i.parse()})},e.Index.prototype.query=function(t){var r=new e.Query(this.fields),i=Object.create(null),n=Object.create(null),s=Object.create(null);t.call(r,r);for(var o=0;oe?this._b=0:e>1?this._b=1:this._b=e},e.Builder.prototype.k1=function(e){this._k1=e},e.Builder.prototype.add=function(t){var r=t[this._ref];this.documentCount+=1;for(var i=0;is;s++){var o=e.FieldRef.fromString(t[s]),a=o.fieldName;n[a]||(n[a]=0),n[a]+=1,i[a]||(i[a]=0),i[a]+=this.fieldLengths[o]}for(var s=0;ss;s++){for(var o=e.FieldRef.fromString(r[s]),a=o.fieldName,u=this.fieldLengths[o],l=new e.Vector,d=this.fieldTermFrequencies[o],h=Object.keys(d),c=h.length,f=0;c>f;f++){var p,y,m,v=h[f],g=d[v],x=this.invertedIndex[v]._index;void 0===n[v]?(p=e.idf(this.invertedIndex[v],this.documentCount),n[v]=p):p=n[v],y=p*((this._k1+1)*g)/(this._k1*(1-this._b+this._b*(u/this.averageFieldLength[a]))+g),m=Math.round(1e3*y)/1e3,l.insert(x,m)}t[o]=l}this.fieldVectors=t},e.Builder.prototype.createTokenSet=function(){this.tokenSet=e.TokenSet.fromArray(Object.keys(this.invertedIndex).sort())},e.Builder.prototype.build=function(){return this.calculateAverageFieldLengths(),this.createFieldVectors(),this.createTokenSet(),new e.Index({invertedIndex:this.invertedIndex,fieldVectors:this.fieldVectors,tokenSet:this.tokenSet,fields:this._fields,pipeline:this.searchPipeline})},e.Builder.prototype.use=function(e){var t=Array.prototype.slice.call(arguments,1);t.unshift(this),e.apply(this,t)},e.MatchData=function(e,t,r){for(var i=Object.create(null),n=Object.keys(r),s=0;s=this.length)return e.QueryLexer.EOS;var t=this.str.charAt(this.pos);return this.pos+=1,t},e.QueryLexer.prototype.width=function(){return this.pos-this.start},e.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},e.QueryLexer.prototype.backup=function(){this.pos-=1},e.QueryLexer.prototype.acceptDigitRun=function(){var t,r;do t=this.next(),r=t.charCodeAt(0);while(r>47&&58>r);t!=e.QueryLexer.EOS&&this.backup()},e.QueryLexer.prototype.more=function(){return this.pos1&&(t.backup(),t.emit(e.QueryLexer.TERM)),t.ignore(),t.more()?e.QueryLexer.lexText:void 0},e.QueryLexer.lexEditDistance=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.EDIT_DISTANCE),e.QueryLexer.lexText},e.QueryLexer.lexBoost=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.BOOST),e.QueryLexer.lexText},e.QueryLexer.lexEOS=function(t){t.width()>0&&t.emit(e.QueryLexer.TERM)},e.QueryLexer.termSeparator=e.tokenizer.separator,e.QueryLexer.lexText=function(t){for(;;){var r=t.next();if(r==e.QueryLexer.EOS)return e.QueryLexer.lexEOS;if(92!=r.charCodeAt(0)){if(":"==r)return e.QueryLexer.lexField;if("~"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexEditDistance;if("^"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexBoost;if(r.match(e.QueryLexer.termSeparator))return e.QueryLexer.lexTerm}else t.escapeCharacter()}},e.QueryParser=function(t,r){this.lexer=new e.QueryLexer(t),this.query=r,this.currentClause={},this.lexemeIdx=0},e.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var t=e.QueryParser.parseFieldOrTerm;t;)t=t(this);return this.query},e.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},e.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},e.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},e.QueryParser.parseFieldOrTerm=function(t){var r=t.peekLexeme();if(void 0!=r)switch(r.type){case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(i+=" with value '"+r.str+"'"),new e.QueryParseError(i,r.start,r.end)}},e.QueryParser.parseField=function(t){var r=t.consumeLexeme();if(void 0!=r){if(-1==t.query.allFields.indexOf(r.str)){var i=t.query.allFields.map(function(e){return"'"+e+"'"}).join(", "),n="unrecognised field '"+r.str+"', possible fields: "+i;throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.fields=[r.str];var s=t.peekLexeme();if(void 0==s){var n="expecting term, found nothing";throw new e.QueryParseError(n,r.start,r.end)}switch(s.type){case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var n="expecting term, found '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseTerm=function(t){var r=t.consumeLexeme();if(void 0!=r){t.currentClause.term=r.str.toLowerCase(),-1!=r.str.indexOf("*")&&(t.currentClause.usePipeline=!1);var i=t.peekLexeme();if(void 0==i)return void t.nextClause();switch(i.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;default:var n="Unexpected lexeme type '"+i.type+"'";throw new e.QueryParseError(n,i.start,i.end)}}},e.QueryParser.parseEditDistance=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="edit distance must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.editDistance=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseBoost=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="boost must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.boost=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.lunr=t()}(this,function(){return e})}();
\ No newline at end of file
+!function(){var e,t,r,i,n,s,o,a,u,l,c,d,h,f,p,y,m,g,x,v,w,Q,k,S,E,L,b,P,T=function(e){var t=new T.Builder;return t.pipeline.add(T.trimmer,T.stopWordFilter,T.stemmer),t.searchPipeline.add(T.stemmer),e.call(t,t),t.build()};T.version="2.3.3",T.utils={},T.utils.warn=(e=this,function(t){e.console&&console.warn&&console.warn(t)}),T.utils.asString=function(e){return void 0===e||null===e?"":e.toString()},T.utils.clone=function(e){if(null===e||void 0===e)return e;for(var t=Object.create(null),r=Object.keys(e),i=0;i0){var u=T.utils.clone(t)||{};u.position=[o,a],u.index=n.length,n.push(new T.Token(r.slice(o,s),u))}o=s+1}}return n},T.tokenizer.separator=/[\s\-]+/,T.Pipeline=function(){this._stack=[]},T.Pipeline.registeredFunctions=Object.create(null),T.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&T.utils.warn("Overwriting existing registered function: "+t),e.label=t,T.Pipeline.registeredFunctions[e.label]=e},T.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||T.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},T.Pipeline.load=function(e){var t=new T.Pipeline;return e.forEach(function(e){var r=T.Pipeline.registeredFunctions[e];if(!r)throw new Error("Cannot load unregistered function: "+e);t.add(r)}),t},T.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(e){T.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},T.Pipeline.prototype.after=function(e,t){T.Pipeline.warnIfFunctionNotRegistered(t);var r=this._stack.indexOf(e);if(-1==r)throw new Error("Cannot find existingFn");r+=1,this._stack.splice(r,0,t)},T.Pipeline.prototype.before=function(e,t){T.Pipeline.warnIfFunctionNotRegistered(t);var r=this._stack.indexOf(e);if(-1==r)throw new Error("Cannot find existingFn");this._stack.splice(r,0,t)},T.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},T.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;r1&&(se&&(r=n),s!=e);)i=r-t,n=t+Math.floor(i/2),s=this.elements[2*n];return s==e?2*n:s>e?2*n:sa?l+=2:o==a&&(t+=r[u+1]*i[l+1],u+=2,l+=2);return t},T.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},T.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;t0)(s=a.str.charAt(0))in a.node.edges?n=a.node.edges[s]:(n=new T.TokenSet,a.node.edges[s]=n),1==a.str.length?n.final=!0:i.push({node:n,editsRemaining:a.editsRemaining,str:a.str.slice(1)});if(a.editsRemaining>0&&a.str.length>1)(s=a.str.charAt(1))in a.node.edges?o=a.node.edges[s]:(o=new T.TokenSet,a.node.edges[s]=o),a.str.length<=2?o.final=!0:i.push({node:o,editsRemaining:a.editsRemaining-1,str:a.str.slice(2)});if(a.editsRemaining>0&&1==a.str.length&&(a.node.final=!0),a.editsRemaining>0&&a.str.length>=1){if("*"in a.node.edges)var u=a.node.edges["*"];else{u=new T.TokenSet;a.node.edges["*"]=u}1==a.str.length?u.final=!0:i.push({node:u,editsRemaining:a.editsRemaining-1,str:a.str.slice(1)})}if(a.editsRemaining>0){if("*"in a.node.edges)var l=a.node.edges["*"];else{l=new T.TokenSet;a.node.edges["*"]=l}0==a.str.length?l.final=!0:i.push({node:l,editsRemaining:a.editsRemaining-1,str:a.str})}if(a.editsRemaining>0&&a.str.length>1){var c,d=a.str.charAt(0),h=a.str.charAt(1);h in a.node.edges?c=a.node.edges[h]:(c=new T.TokenSet,a.node.edges[h]=c),1==a.str.length?c.final=!0:i.push({node:c,editsRemaining:a.editsRemaining-1,str:d+a.str.slice(2)})}}return r},T.TokenSet.fromString=function(e){for(var t=new T.TokenSet,r=t,i=0,n=e.length;i=e;t--){var r=this.uncheckedNodes[t],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}},T.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},T.Index.prototype.search=function(e){return this.query(function(t){new T.QueryParser(e,t).parse()})},T.Index.prototype.query=function(e){for(var t=new T.Query(this.fields),r=Object.create(null),i=Object.create(null),n=Object.create(null),s=Object.create(null),o=Object.create(null),a=0;a1?1:e},T.Builder.prototype.k1=function(e){this._k1=e},T.Builder.prototype.add=function(e,t){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=t||{},this.documentCount+=1;for(var n=0;n=this.length)return T.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},T.QueryLexer.prototype.width=function(){return this.pos-this.start},T.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},T.QueryLexer.prototype.backup=function(){this.pos-=1},T.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do{t=(e=this.next()).charCodeAt(0)}while(t>47&&t<58);e!=T.QueryLexer.EOS&&this.backup()},T.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(T.QueryLexer.TERM)),e.ignore(),e.more())return T.QueryLexer.lexText},T.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(T.QueryLexer.EDIT_DISTANCE),T.QueryLexer.lexText},T.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(T.QueryLexer.BOOST),T.QueryLexer.lexText},T.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(T.QueryLexer.TERM)},T.QueryLexer.termSeparator=T.tokenizer.separator,T.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==T.QueryLexer.EOS)return T.QueryLexer.lexEOS;if(92!=t.charCodeAt(0)){if(":"==t)return T.QueryLexer.lexField;if("~"==t)return e.backup(),e.width()>0&&e.emit(T.QueryLexer.TERM),T.QueryLexer.lexEditDistance;if("^"==t)return e.backup(),e.width()>0&&e.emit(T.QueryLexer.TERM),T.QueryLexer.lexBoost;if("+"==t&&1===e.width())return e.emit(T.QueryLexer.PRESENCE),T.QueryLexer.lexText;if("-"==t&&1===e.width())return e.emit(T.QueryLexer.PRESENCE),T.QueryLexer.lexText;if(t.match(T.QueryLexer.termSeparator))return T.QueryLexer.lexTerm}else e.escapeCharacter()}},T.QueryParser=function(e,t){this.lexer=new T.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},T.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=T.QueryParser.parseClause;e;)e=e(this);return this.query},T.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},T.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},T.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},T.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(void 0!=t)switch(t.type){case T.QueryLexer.PRESENCE:return T.QueryParser.parsePresence;case T.QueryLexer.FIELD:return T.QueryParser.parseField;case T.QueryLexer.TERM:return T.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+t.type;throw t.str.length>=1&&(r+=" with value '"+t.str+"'"),new T.QueryParseError(r,t.start,t.end)}},T.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(void 0!=t){switch(t.str){case"-":e.currentClause.presence=T.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=T.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+t.str+"'";throw new T.QueryParseError(r,t.start,t.end)}var i=e.peekLexeme();if(void 0==i){r="expecting term or field, found nothing";throw new T.QueryParseError(r,t.start,t.end)}switch(i.type){case T.QueryLexer.FIELD:return T.QueryParser.parseField;case T.QueryLexer.TERM:return T.QueryParser.parseTerm;default:r="expecting term or field, found '"+i.type+"'";throw new T.QueryParseError(r,i.start,i.end)}}},T.QueryParser.parseField=function(e){var t=e.consumeLexeme();if(void 0!=t){if(-1==e.query.allFields.indexOf(t.str)){var r=e.query.allFields.map(function(e){return"'"+e+"'"}).join(", "),i="unrecognised field '"+t.str+"', possible fields: "+r;throw new T.QueryParseError(i,t.start,t.end)}e.currentClause.fields=[t.str];var n=e.peekLexeme();if(void 0==n){i="expecting term, found nothing";throw new T.QueryParseError(i,t.start,t.end)}switch(n.type){case T.QueryLexer.TERM:return T.QueryParser.parseTerm;default:i="expecting term, found '"+n.type+"'";throw new T.QueryParseError(i,n.start,n.end)}}},T.QueryParser.parseTerm=function(e){var t=e.consumeLexeme();if(void 0!=t){e.currentClause.term=t.str.toLowerCase(),-1!=t.str.indexOf("*")&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(void 0!=r)switch(r.type){case T.QueryLexer.TERM:return e.nextClause(),T.QueryParser.parseTerm;case T.QueryLexer.FIELD:return e.nextClause(),T.QueryParser.parseField;case T.QueryLexer.EDIT_DISTANCE:return T.QueryParser.parseEditDistance;case T.QueryLexer.BOOST:return T.QueryParser.parseBoost;case T.QueryLexer.PRESENCE:return e.nextClause(),T.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new T.QueryParseError(i,r.start,r.end)}else e.nextClause()}},T.QueryParser.parseEditDistance=function(e){var t=e.consumeLexeme();if(void 0!=t){var r=parseInt(t.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new T.QueryParseError(i,t.start,t.end)}e.currentClause.editDistance=r;var n=e.peekLexeme();if(void 0!=n)switch(n.type){case T.QueryLexer.TERM:return e.nextClause(),T.QueryParser.parseTerm;case T.QueryLexer.FIELD:return e.nextClause(),T.QueryParser.parseField;case T.QueryLexer.EDIT_DISTANCE:return T.QueryParser.parseEditDistance;case T.QueryLexer.BOOST:return T.QueryParser.parseBoost;case T.QueryLexer.PRESENCE:return e.nextClause(),T.QueryParser.parsePresence;default:i="Unexpected lexeme type '"+n.type+"'";throw new T.QueryParseError(i,n.start,n.end)}else e.nextClause()}},T.QueryParser.parseBoost=function(e){var t=e.consumeLexeme();if(void 0!=t){var r=parseInt(t.str,10);if(isNaN(r)){var i="boost must be numeric";throw new T.QueryParseError(i,t.start,t.end)}e.currentClause.boost=r;var n=e.peekLexeme();if(void 0!=n)switch(n.type){case T.QueryLexer.TERM:return e.nextClause(),T.QueryParser.parseTerm;case T.QueryLexer.FIELD:return e.nextClause(),T.QueryParser.parseField;case T.QueryLexer.EDIT_DISTANCE:return T.QueryParser.parseEditDistance;case T.QueryLexer.BOOST:return T.QueryParser.parseBoost;case T.QueryLexer.PRESENCE:return e.nextClause(),T.QueryParser.parsePresence;default:i="Unexpected lexeme type '"+n.type+"'";throw new T.QueryParseError(i,n.start,n.end)}else e.nextClause()}},b=this,P=function(){return T},"function"==typeof define&&define.amd?define(P):"object"==typeof exports?module.exports=P():b.lunr=P()}();
\ No newline at end of file
From ef64fd88c27c1dab2897e75d12a8470595d0d997 Mon Sep 17 00:00:00 2001
From: Michael Rose
Date: Tue, 9 Oct 2018 14:49:36 -0400
Subject: [PATCH 5/6] Update CHANGELOG and history
---
CHANGELOG.md | 1 +
docs/_docs/18-history.md | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 19ea74720889..c1ac603daccd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
### Enhancements
+- Update Lunr to `2.3.3`. [#1885](https://github.com/mmistakes/minimal-mistakes/pull/1885)
- Cache "static" includes to improve build performance. **Note:** The theme uses the [jekyll-include-cache](https://github.com/benbalter/jekyll-include-cache) plugin which will need to be installed in your `Gemfile` and added to the `plugins` array of `_config.yml`. Otherwise you'll throw `Unknown tag 'include_cached'` errors at build. [#1874](https://github.com/mmistakes/minimal-mistakes/pull/1874)
- Make entire feature and archive items "clickable". [#1864](https://github.com/mmistakes/minimal-mistakes/pull/1864)
- Allow custom Staticman endpoints. [#1842](https://github.com/mmistakes/minimal-mistakes/issues/1842)
diff --git a/docs/_docs/18-history.md b/docs/_docs/18-history.md
index da0364194ff8..9b8d29867baa 100644
--- a/docs/_docs/18-history.md
+++ b/docs/_docs/18-history.md
@@ -4,7 +4,7 @@ permalink: /docs/history/
excerpt: "Change log of enhancements and bug fixes made to the theme."
sidebar:
nav: docs
-last_modified_at: 2018-10-09T13:55:44-04:00
+last_modified_at: 2018-10-09T14:49:28-04:00
toc: true
---
@@ -12,6 +12,7 @@ toc: true
### Enhancements
+- Update Lunr to `2.3.3`. [#1885](https://github.com/mmistakes/minimal-mistakes/pull/1885)
- Cache "static" includes to improve build performance. **Note:** The theme uses the [jekyll-include-cache](https://github.com/benbalter/jekyll-include-cache) plugin which will need to be installed in your `Gemfile` and added to the `plugins` array of `_config.yml`. Otherwise you'll throw `Unknown tag 'include_cached'` errors at build. [#1874]
- Make entire feature and archive items "clickable". [#1864](https://github.com/mmistakes/minimal-mistakes/pull/1864)
- Allow custom Staticman endpoints. [#1842](https://github.com/mmistakes/minimal-mistakes/issues/1842)
From 1182447793bfa7baad7ac37bdb33167e4bce6ba7 Mon Sep 17 00:00:00 2001
From: Michael Rose
Date: Tue, 9 Oct 2018 17:44:56 -0400
Subject: [PATCH 6/6] Update license (#1886)
---
LICENSE | 21 +++++++++++++
LICENSE.txt | 63 --------------------------------------
README.md | 2 +-
_layouts/default.html | 2 +-
docs/_docs/04-upgrading.md | 2 +-
docs/_layouts/default.html | 2 +-
6 files changed, 25 insertions(+), 67 deletions(-)
create mode 100644 LICENSE
delete mode 100644 LICENSE.txt
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000000..cacc496292f7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2018 Michael Rose and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/LICENSE.txt b/LICENSE.txt
deleted file mode 100644
index afcb825ce2e9..000000000000
--- a/LICENSE.txt
+++ /dev/null
@@ -1,63 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013-2018 Michael Rose and contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Minimal Mistakes incorporates icons from [The Noun Project](https://thenounproject.com/)
-creators Garrett Knoll, Arthur Shlain, and Tracy Tam.
-Icons are distributed under Creative Commons Attribution 3.0 United States (CC BY 3.0 US).
-
-Minimal Mistakes incorporates [Font Awesome](http://fontawesome.io/),
-Copyright (c) 2017 Dave Gandy.
-Font Awesome is distributed under the terms of the [SIL OFL 1.1](http://scripts.sil.org/OFL)
-and [MIT License](http://opensource.org/licenses/MIT).
-
-Minimal Mistakes incorporates photographs from [Unsplash](https://unsplash.com).
-
-Minimal Mistakes incorporates [Susy](http://susy.oddbird.net/),
-Copyright (c) 2017, Miriam Eric Suzanne.
-Susy is distributed under the terms of the [BSD 3-clause "New" or "Revised" License](https://opensource.org/licenses/BSD-3-Clause).
-
-Minimal Mistakes incorporates [Breakpoint](http://breakpoint-sass.com/).
-Breakpoint is distributed under the terms of the [MIT/GPL Licenses](http://opensource.org/licenses/MIT).
-
-Minimal Mistakes incorporates [FitVids.js](https://github.com/davatron5000/FitVids.js/),
-Copyright (c) 2013 Dave Rubert and Chris Coyier.
-FitVids is distributed under the terms of the [WTFPL License](http://sam.zoy.org/wtfpl/).
-
-Minimal Mistakes incorporates [Magnific Popup](http://dimsemenov.com/plugins/magnific-popup/),
-Copyright (c) 2014-2016 Dmitry Semenov, http://dimsemenov.com.
-Magnific Popup is distributed under the terms of the MIT License.
-
-Minimal Mistakes incorporates [jQuery Smooth Scroll](https://github.com/kswedberg/jquery-smooth-scroll),
-Copyright (c) 2017 Karl Swedberg.
-jQuery Smooth Scroll is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
-
-Minimal Mistakes incorporates [GreedyNav.js](https://github.com/lukejacksonn/GreedyNav),
-Copyright (c) 2015 Luke Jackson.
-GreedyNav.js is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
-
-Minimal Mistakes incorporates [Jekyll Group-By-Array](https://github.com/mushishi78/jekyll-group-by-array),
-Copyright (c) 2015 Max White .
-Jekyll Group-By-Array is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
-
-Minimal Mistakes incorporates [Lunr](http://lunrjs.com),
-Copyright (c) 2017 Oliver Nightingale.
-Lunr is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
diff --git a/README.md b/README.md
index 3a4cfde08218..6d2e7d43c8fa 100644
--- a/README.md
+++ b/README.md
@@ -243,5 +243,5 @@ Copyright (c) 2017 Vladimir Jimenez.
Pure Liquid Jekyll Table of Contents is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
Minimal Mistakes incorporates [Lunr](http://lunrjs.com),
-Copyright (c) 2017 Oliver Nightingale.
+Copyright (c) 2018 Oliver Nightingale.
Lunr is distributed under the terms of the [MIT License](http://opensource.org/licenses/MIT).
diff --git a/_layouts/default.html b/_layouts/default.html
index c699dc2148ab..0cdcd0591b73 100644
--- a/_layouts/default.html
+++ b/_layouts/default.html
@@ -6,7 +6,7 @@
Minimal Mistakes Jekyll Theme 4.13.0 by Michael Rose
Copyright 2013-2018 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
- https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE.txt
+ https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
-->
diff --git a/docs/_docs/04-upgrading.md b/docs/_docs/04-upgrading.md
index 811709f24de9..327883dc8536 100644
--- a/docs/_docs/04-upgrading.md
+++ b/docs/_docs/04-upgrading.md
@@ -15,7 +15,7 @@ To check which version you are currently using, view the source of your built si
Minimal Mistakes Jekyll Theme 4.9.0 by Michael Rose
Copyright 2013-2018 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
- https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE.txt
+ https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
-->
```
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html
index fe21bbc1f5c1..1e3e52fcedc3 100644
--- a/docs/_layouts/default.html
+++ b/docs/_layouts/default.html
@@ -6,7 +6,7 @@
Minimal Mistakes Jekyll Theme 4.13.0 by Michael Rose
Copyright 2013-2018 Michael Rose - mademistakes.com | @mmistakes
Free for personal and commercial use under the MIT license
- https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE.txt
+ https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE
-->