+Callback function `cb` is called for each schema object (not including draft-06 boolean schemas), including the root schema, in pre-order traversal. Schema references ($ref) are not resolved, they are passed as is. Alternatively, you can pass a `{pre, post}` object as `cb`, and then `pre` will be called before traversing child elements, and `post` will be called after all child elements have been traversed.
+
+Callback is passed these parameters:
+
+- _schema_: the current schema object
+- _JSON pointer_: from the root schema to the current schema object
+- _root schema_: the schema passed to `traverse` object
+- _parent JSON pointer_: from the root schema to the parent schema object (see below)
+- _parent keyword_: the keyword inside which this schema appears (e.g. `properties`, `anyOf`, etc.)
+- _parent schema_: not necessarily parent object/array; in the example above the parent schema for `{type: 'string'}` is the root schema
+- _index/property_: index or property name in the array/object containing multiple schemas; in the example above for `{type: 'string'}` the property name is `'foo'`
+Without option `allKeys: true` callback will be called only with root schema.
+
+
+## Enterprise support
+
+json-schema-traverse package is a part of [Tidelift enterprise subscription](https://tidelift.com/subscription/pkg/npm-json-schema-traverse?utm_source=npm-json-schema-traverse&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) - it provides a centralised commercial support to open-source software users, in addition to the support provided by software maintainers.
+
+
+## Security contact
+
+To report a security vulnerability, please use the
+ throw new Error(`Can not ${value === void 0 ? 'remove' : (options.isArrayInsertion ? 'insert' : 'modify')} Array index ${insertIndex} as length is not sufficient`);
+ }
+ }
+ else {
+ throw new Error(`Can not add ${typeof lastSegment !== 'number' ? 'index' : 'property'} to parent of type ${parent.type}`);
+ }
+}
+function withFormatting(text, edit, options) {
+ if (!options.formattingOptions) {
+ return [edit];
+ }
+ // apply the edit
+ let newText = applyEdit(text, edit);
+ // format the new text
+ let begin = edit.offset;
+ let end = edit.offset + edit.content.length;
+ if (edit.length === 0 || edit.content.length === 0) { // insert or remove
+ while (begin > 0 && !isEOL(newText, begin - 1)) {
+ begin--;
+ }
+ while (end < newText.length && !isEOL(newText, end)) {
+ end++;
+ }
+ }
+ const edits = format(newText, { offset: begin, length: end - begin }, { ...options.formattingOptions, keepLines: false });
+ // apply the formatting edits and track the begin and end offsets of the changes
+ * For a given offset, evaluate the location in the JSON document. Each segment in the location path is either a property name or an array index.
+ */
+export const getLocation = parser.getLocation;
+/**
+ * Parses the given text and returns the object the JSON content represents. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
+ * Therefore, always check the errors list to find out if the input was valid.
+ */
+export const parse = parser.parse;
+/**
+ * Parses the given text and returns a tree representation the JSON content. On invalid input, the parser tries to be as fault tolerant as possible, but still return a result.
+ */
+export const parseTree = parser.parseTree;
+/**
+ * Finds the node at the given path in a JSON DOM.
+ throw new Error(`Can not ${value === void 0 ? 'remove' : (options.isArrayInsertion ? 'insert' : 'modify')} Array index ${insertIndex} as length is not sufficient`);
+ }
+ }
+ else {
+ throw new Error(`Can not add ${typeof lastSegment !== 'number' ? 'index' : 'property'} to parent of type ${parent.type}`);
+ }
+ }
+ exports.setProperty = setProperty;
+ function withFormatting(text, edit, options) {
+ if (!options.formattingOptions) {
+ return [edit];
+ }
+ // apply the edit
+ let newText = applyEdit(text, edit);
+ // format the new text
+ let begin = edit.offset;
+ let end = edit.offset + edit.content.length;
+ if (edit.length === 0 || edit.content.length === 0) { // insert or remove
+ while (begin > 0 && !(0, format_1.isEOL)(newText, begin - 1)) {
+ begin--;
+ }
+ while (end < newText.length && !(0, format_1.isEOL)(newText, end)) {
+ end++;
+ }
+ }
+ const edits = (0, format_1.format)(newText, { offset: begin, length: end - begin }, { ...options.formattingOptions, keepLines: false });
+ // apply the formatting edits and track the begin and end offsets of the changes
+- **BREAKING:** Drop support for Node 6 & 8 ([#128](https://github.com/jprichardson/node-jsonfile/pull/128))
+- **BREAKING:** Do not allow passing `null` as options to `readFile()` or `writeFile()` ([#128](https://github.com/jprichardson/node-jsonfile/pull/128))
+- **BREAKING:** If no callback is passed to an asynchronous method, a promise is now returned ([#109](https://github.com/jprichardson/node-jsonfile/pull/109))
+- Cleanup docs
+
+4.0.0 / 2017-07-12
+------------------
+
+- **BREAKING:** Remove global `spaces` option.
+- **BREAKING:** Drop support for Node 0.10, 0.12, and io.js.
+- Added `EOL` override option to `writeFile` when using `spaces`. [#89]
+
+3.0.1 / 2017-07-05
+------------------
+
+- Fixed bug in `writeFile` when there was a serialization error & no callback was passed. In previous versions, an empty file would be written; now no file is written.
+
+3.0.0 / 2017-04-25
+------------------
+
+- Changed behavior of `throws` option for `readFileSync`; now does not throw filesystem errors when `throws` is `false`
+
+2.4.0 / 2016-09-15
+------------------
+### Changed
+- added optional support for `graceful-fs` [#62]
+
+2.3.1 / 2016-05-13
+------------------
+- fix to support BOM. [#45][#45]
+
+2.3.0 / 2016-04-16
+------------------
+- add `throws` to `readFile()`. See [#39][#39]
+- add support for any arbitrary `fs` module. Useful with [mock-fs](https://www.npmjs.com/package/mock-fs)
+
+2.2.3 / 2015-10-14
+------------------
+- include file name in parse error. See: https://github.com/jprichardson/node-jsonfile/pull/34
+
+2.2.2 / 2015-09-16
+------------------
+- split out tests into separate files
+- fixed `throws` when set to `true` in `readFileSync()`. See: https://github.com/jprichardson/node-jsonfile/pull/33
+
+2.2.1 / 2015-06-25
+------------------
+- fixed regression when passing in string as encoding for options in `writeFile()` and `writeFileSync()`. See: https://github.com/jprichardson/node-jsonfile/issues/28
+
+2.2.0 / 2015-06-25
+------------------
+- added `options.spaces` to `writeFile()` and `writeFileSync()`
+
+2.1.2 / 2015-06-22
+------------------
+- fixed if passed `readFileSync(file, 'utf8')`. See: https://github.com/jprichardson/node-jsonfile/issues/25
+
+2.1.1 / 2015-06-19
+------------------
+- fixed regressions if `null` is passed for options. See: https://github.com/jprichardson/node-jsonfile/issues/24
+
+2.1.0 / 2015-06-19
+------------------
+- cleanup: JavaScript Standard Style, rename files, dropped terst for assert
+`options` (`object`, default `undefined`): Pass in any [`fs.readFile`](https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback) options or set `reviver` for a [JSON reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
+ - `throws` (`boolean`, default: `true`). If `JSON.parse` throws an error, pass this error to the callback.
+ If `false`, returns `null` for the object.
+
+
+```js
+const jsonfile = require('jsonfile')
+const file = '/tmp/data.json'
+jsonfile.readFile(file, function (err, obj) {
+ if (err) console.error(err)
+ console.dir(obj)
+})
+```
+
+You can also use this method with promises. The `readFile` method will return a promise if you do not pass a callback function.
+
+```js
+const jsonfile = require('jsonfile')
+const file = '/tmp/data.json'
+jsonfile.readFile(file)
+ .then(obj => console.dir(obj))
+ .catch(error => console.error(error))
+```
+
+----
+
+### readFileSync(filename, [options])
+
+`options` (`object`, default `undefined`): Pass in any [`fs.readFileSync`](https://nodejs.org/api/fs.html#fs_fs_readfilesync_path_options) options or set `reviver` for a [JSON reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
+- `throws` (`boolean`, default: `true`). If an error is encountered reading or parsing the file, throw the error. If `false`, returns `null` for the object.
+`options`: Pass in any [`fs.writeFile`](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback) options or set `replacer` for a [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). Can also pass in `spaces`, or override `EOL` string or set `finalEOL` flag as `false` to not save the file with `EOL` at the end.
+
+
+```js
+const jsonfile = require('jsonfile')
+
+const file = '/tmp/data.json'
+const obj = { name: 'JP' }
+
+jsonfile.writeFile(file, obj, function (err) {
+ if (err) console.error(err)
+})
+```
+Or use with promises as follows:
+
+```js
+const jsonfile = require('jsonfile')
+
+const file = '/tmp/data.json'
+const obj = { name: 'JP' }
+
+jsonfile.writeFile(file, obj)
+ .then(res => {
+ console.log('Write complete')
+ })
+ .catch(error => console.error(error))
+```
+
+
+**formatting with spaces:**
+
+```js
+const jsonfile = require('jsonfile')
+
+const file = '/tmp/data.json'
+const obj = { name: 'JP' }
+
+jsonfile.writeFile(file, obj, { spaces: 2 }, function (err) {
+You can use `fs.writeFile` option `{ flag: 'a' }` to achieve this.
+
+```js
+const jsonfile = require('jsonfile')
+
+const file = '/tmp/mayAlreadyExistedData.json'
+const obj = { name: 'JP' }
+
+jsonfile.writeFile(file, obj, { flag: 'a' }, function (err) {
+ if (err) console.error(err)
+})
+```
+
+----
+
+### writeFileSync(filename, obj, [options])
+
+`options`: Pass in any [`fs.writeFileSync`](https://nodejs.org/api/fs.html#fs_fs_writefilesync_file_data_options) options or set `replacer` for a [JSON replacer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). Can also pass in `spaces`, or override `EOL` string or set `finalEOL` flag as `false` to not save the file with `EOL` at the end.
+keys.bind("a", function () {}, 'keydown'); // key, callback function, 'keydown' or 'keyup'
+```
+
+Available options (all are optional):
+```
+{
+ container: document.getElementById("element"), // optional div to bind keycharm to. It will NEED a tabindex. When not supplied, this defaults to window.
+Each initiation of keycharm has its own bindings to the key events.
+
+Available methods:
+
+```
+.bind(key, callback, [type]); // bind key, type = 'keydown' or 'keyup', default type = keydown.
+.unbind(key, [callback], [type]); // unbind key, type = 'keydown' or 'keyup', default type = keydown. No callback deletes all bound callbacks from key
+.reset(); // remove all bound keys
+.destroy(); // remove all bound keys and the event listeners of keycharm
+.getKey(event); // get the key label of the event
+.bindAll(function, 'keydown' or 'keyup'); // bind all keys to this function, could be used for testing or demos.
+```
+
+Keycharm is Dual-licensed with both the Apache 2.0 license as well as the MIT license. I'll leave it up to the user to pick which one they prefer.
+The [lodash](https://lodash.com/) method `_.debounce` exported as a [Node.js](https://nodejs.org/) module.
+
+## Installation
+
+Using npm:
+```bash
+$ {sudo -H} npm i -g npm
+$ npm i --save lodash.debounce
+```
+
+In Node.js:
+```js
+var debounce = require('lodash.debounce');
+```
+
+See the [documentation](https://lodash.com/docs#debounce) or [package source](https://github.com/lodash/lodash/blob/4.0.8-npm-packages/lodash.debounce) for more details.
+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.
+// Terminals with Unicode support: ✔ Finished successfully!
+// Terminals without Unicode support: √ Finished successfully!
+```
+
+## API
+
+### logSymbols
+
+#### info
+#### success
+#### warning
+#### error
+
+## Related
+
+- [figures](https://github.com/sindresorhus/figures) - Unicode symbols with Windows CMD fallbacks
+- [py-log-symbols](https://github.com/ManrajGrover/py-log-symbols) - Python port
+- [log-symbols](https://github.com/palash25/log-symbols) - Ruby port
+- [guumaster/logsymbols](https://github.com/guumaster/logsymbols) - Golang port
+
+---
+
+<div align="center">
+ <b>
+ <a href="https://tidelift.com/subscription/pkg/npm-log-symbols?utm_source=npm-log-symbols&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
+ </b>
+ <br>
+ <sub>
+ Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
+**This plugin is under active development and should be considered as an unstable. No guarantees regarding API stability are made. Backward compatibility is guaranteed only by path releases.**
+
+#### `reg(loglevel)`
+
+This method registers plugin for loglevel. This method must be called at least once before any call to the apply method. Repeated calls to this method are ignored.
+
+#### Parameters
+
+`loglevel` - the root logger, imported from loglevel module
+
+#### `apply(logger, options)`
+
+This method applies the plugin to the logger. Before using this method, the `reg` method must be called, otherwise a warning will be logged. **From the next release, the call apply before reg will throw an error.**
+Plugin formats the prefix using `template` option as a printf-like format. The `template` is a string containing zero or more placeholder tokens. Each placeholder token is replaced with the value from loglevel messages parameters. Supported placeholders are:
+
+- `%l` - level of message
+- `%n` - name of logger
+- `%t` - timestamp of message
+
+The `levelFormatter`, `nameFormatter` and `timestampFormatter` is a functions for formatting corresponding values.
+
+Alternatively, you can use `format` option. This is a function that receives formatted values (level, name, timestamp) and should returns a prefix string.
+
+If both `format` and` template` are present in the configuration, the `template` parameter is ignored. When both these parameters are missing in the configuration, the inherited behavior is used.
+!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof module&&module.exports?module.exports=t():e.prefix=t(e)}(this,function(e){"use strict";var n,t,a={template:"[%t] %l:",levelFormatter:function(e){return e.toUpperCase()},nameFormatter:function(e){return e||"root"},timestampFormatter:function(e){return e.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/,"$1")},format:void 0},d={},r={reg:function(e){if(!e||!e.getLogger)throw new TypeError("Argument is not a root logger");n=e},apply:function(e,t){if(!e||!e.setLevel)throw new TypeError("Argument is not a logger");var r=e.methodFactory,s=e.name||"",o=d[s]||d[""]||a;return d[s]||(e.methodFactory=function(i,e,f){var p=r(i,e,f),m=d[f]||d[""],u=-1!==m.template.indexOf("%t"),c=-1!==m.template.indexOf("%l"),g=-1!==m.template.indexOf("%n");return function(){for(var e="",t=arguments.length,r=Array(t),o=0;o<t;o++)r[o]=arguments[o];if(s||!d[f]){var n=m.timestampFormatter(new Date),a=m.levelFormatter(i),l=m.nameFormatter(f);m.format?e+=m.format(a,l,n):(e+=m.template,u&&(e=e.replace(/%t/,n)),c&&(e=e.replace(/%l/,a)),g&&(e=e.replace(/%n/,l))),r.length&&"string"==typeof r[0]?r[0]=e+" "+r[0]:r.unshift(e)}p.apply(void 0,r)}}),(t=t||{}).template&&(t.format=void 0),d[s]=function(e){for(var t,r=1,o=arguments.length;r<o;r++)for(t in arguments[r])Object.prototype.hasOwnProperty.call(arguments[r],t)&&(e[t]=arguments[r][t]);return e}({},o,t),e.setLevel(e.getLevel()),n||e.warn("It is necessary to call the function reg() of loglevel-plugin-prefix before calling apply. From the next release, it will throw an error. See more: https://github.com/kutuluk/loglevel-plugin-prefix/blob/master/README.md"),e}};return e&&(t=e.prefix,r.noConflict=function(){return e.prefix===r&&(e.prefix=t),r}),r});
+[](https://gitter.im/olivernn/lunr.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+A bit like Solr, but much smaller and not as bright.
+
+## Example
+
+A very simple search index can be created using the following:
+
+```javascript
+var idx = lunr(function () {
+ this.field('title')
+ this.field('body')
+
+ this.add({
+ "title": "Twelfth-Night",
+ "body": "If music be the food of love, play on: Give me excess of it…",
+ "author": "William Shakespeare",
+ "id": "1"
+ })
+})
+```
+
+Then searching is as simple as:
+
+```javascript
+idx.search("love")
+```
+
+This returns a list of matching documents with a score of how closely they match the search query as well as any associated metadata about the match:
+
+```javascript
+[
+ {
+ "ref": "1",
+ "score": 0.3535533905932737,
+ "matchData": {
+ "metadata": {
+ "love": {
+ "body": {}
+ }
+ }
+ }
+ }
+]
+```
+
+[API documentation](https://lunrjs.com/docs/index.html) is available, as well as a [full working example](https://olivernn.github.io/moonwalkers/).
+
+## Description
+
+Lunr.js is a small, full-text search library for use in the browser. It indexes JSON documents and provides a simple search interface for retrieving documents that best match text queries.
+
+## Why
+
+For web applications with all their data already sitting in the client, it makes sense to be able to search that data on the client too. It saves adding extra, compacted services on the server. A local search index will be quicker, there is no network overhead, and will remain available and usable even without a network connection.
+
+## Installation
+
+Simply include the lunr.js source file in the page that you want to use it. Lunr.js is supported in all modern browsers.
+
+Alternatively an npm package is also available `npm install lunr`.
+
+Browsers that do not support ES5 will require a JavaScript shim for Lunr to work. You can either use [Augment.js](https://github.com/olivernn/augment.js), [ES5-Shim](https://github.com/kriskowal/es5-shim) or any library that patches old browsers to provide an ES5 compatible JavaScript environment.
+
+## Features
+
+* Full text search support for 14 languages
+* Boost terms at query time or boost entire documents at index time
+* Scope searches to specific fields
+* Fuzzy term matching with wildcards or edit distance
+
+## Contributing
+
+See the [`CONTRIBUTING.md` file](CONTRIBUTING.md).
+ * Converts the vector to an array of the elements within the vector.
+ *
+ * @returns {Number[]}
+ */
+lunr.Vector.prototype.toArray = function () {
+ var output = new Array (this.elements.length / 2)
+
+ for (var i = 1, j = 0; i < this.elements.length; i += 2, j++) {
+ output[j] = this.elements[i]
+ }
+
+ return output
+}
+
+/**
+ * A JSON serializable representation of the vector.
+ *
+ * @returns {Number[]}
+ */
+lunr.Vector.prototype.toJSON = function () {
+ return this.elements
+}
+/* eslint-disable */
+/*!
+ * lunr.stemmer
+ * Copyright (C) 2020 Oliver Nightingale
+ * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
+ */
+
+/**
+ * lunr.stemmer is an english language stemmer, this is a JavaScript
+ * implementation of the PorterStemmer taken from http://tartarus.org/~martin
+ *
+ * @static
+ * @implements {lunr.PipelineFunction}
+ * @param {lunr.Token} token - The string to stem
+ * @returns {lunr.Token}
+ * @see {@link lunr.Pipeline}
+ * @function
+ */
+lunr.stemmer = (function(){
+ var step2list = {
+ "ational" : "ate",
+ "tional" : "tion",
+ "enci" : "ence",
+ "anci" : "ance",
+ "izer" : "ize",
+ "bli" : "ble",
+ "alli" : "al",
+ "entli" : "ent",
+ "eli" : "e",
+ "ousli" : "ous",
+ "ization" : "ize",
+ "ation" : "ate",
+ "ator" : "ate",
+ "alism" : "al",
+ "iveness" : "ive",
+ "fulness" : "ful",
+ "ousness" : "ous",
+ "aliti" : "al",
+ "iviti" : "ive",
+ "biliti" : "ble",
+ "logi" : "log"
+ },
+
+ step3list = {
+ "icate" : "ic",
+ "ative" : "",
+ "alize" : "al",
+ "iciti" : "ic",
+ "ical" : "ic",
+ "ful" : "",
+ "ness" : ""
+ },
+
+ c = "[^aeiou]", // consonant
+ v = "[aeiouy]", // vowel
+ C = c + "[^aeiouy]*", // consonant sequence
+ V = v + "[aeiou]*", // vowel sequence
+
+ mgr0 = "^(" + C + ")?" + V + C, // [C]VC... is m>0
+ meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$", // [C]VC[V] is m=1
+ mgr1 = "^(" + C + ")?" + V + C + V + C, // [C]VCVC... is m>1
+ s_v = "^(" + C + ")?" + v; // vowel in stem
+
+ var re_mgr0 = new RegExp(mgr0);
+ var re_mgr1 = new RegExp(mgr1);
+ var re_meq1 = new RegExp(meq1);
+ var re_s_v = new RegExp(s_v);
+
+ var re_1a = /^(.+?)(ss|i)es$/;
+ var re2_1a = /^(.+?)([^s])s$/;
+ var re_1b = /^(.+?)eed$/;
+ var re2_1b = /^(.+?)(ed|ing)$/;
+ var re_1b_2 = /.$/;
+ var re2_1b_2 = /(at|bl|iz)$/;
+ var re3_1b_2 = new RegExp("([^aeiouylsz])\\1$");
+ var re4_1b_2 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+
+ var re_1c = /^(.+?[^aeiou])y$/;
+ var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
+
+ var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
+
+ var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
+ var re2_4 = /^(.+?)(s|t)(ion)$/;
+
+ var re_5 = /^(.+?)e$/;
+ var re_5_1 = /ll$/;
+ var re3_5 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+
+ var porterStemmer = function porterStemmer(w) {
+ var stem,
+ suffix,
+ firstch,
+ re,
+ re2,
+ re3,
+ re4;
+
+ if (w.length < 3) { return w; }
+
+ firstch = w.substr(0,1);
+ if (firstch == "y") {
+ w = firstch.toUpperCase() + w.substr(1);
+ }
+
+ // Step 1a
+ re = re_1a
+ re2 = re2_1a;
+
+ if (re.test(w)) { w = w.replace(re,"$1$2"); }
+ else if (re2.test(w)) { w = w.replace(re2,"$1$2"); }
+
+ // Step 1b
+ re = re_1b;
+ re2 = re2_1b;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ re = re_mgr0;
+ if (re.test(fp[1])) {
+ re = re_1b_2;
+ w = w.replace(re,"");
+ }
+ } else if (re2.test(w)) {
+ var fp = re2.exec(w);
+ stem = fp[1];
+ re2 = re_s_v;
+ if (re2.test(stem)) {
+ w = stem;
+ re2 = re2_1b_2;
+ re3 = re3_1b_2;
+ re4 = re4_1b_2;
+ if (re2.test(w)) { w = w + "e"; }
+ else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,""); }
+ else if (re4.test(w)) { w = w + "e"; }
+ }
+ }
+
+ // 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)
+ re = re_1c;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ w = stem + "i";
+ }
+
+ // Step 2
+ re = re_2;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ suffix = fp[2];
+ re = re_mgr0;
+ if (re.test(stem)) {
+ w = stem + step2list[suffix];
+ }
+ }
+
+ // Step 3
+ re = re_3;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ suffix = fp[2];
+ re = re_mgr0;
+ if (re.test(stem)) {
+ w = stem + step3list[suffix];
+ }
+ }
+
+ // Step 4
+ re = re_4;
+ re2 = re2_4;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ re = re_mgr1;
+ if (re.test(stem)) {
+ w = stem;
+ }
+ } else if (re2.test(w)) {
+ var fp = re2.exec(w);
+ stem = fp[1] + fp[2];
+ re2 = re_mgr1;
+ if (re2.test(stem)) {
+ w = stem;
+ }
+ }
+
+ // Step 5
+ re = re_5;
+ if (re.test(w)) {
+ var fp = re.exec(w);
+ stem = fp[1];
+ re = re_mgr1;
+ re2 = re_meq1;
+ re3 = re3_5;
+ if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) {
+ lunr.utils.warn("Version mismatch when loading serialised index. Current version of lunr '" + lunr.version + "' does not match serialized index '" + serializedIndex.version + "'")
+ }
+
+ for (var i = 0; i < serializedVectors.length; i++) {
+ var tuple = serializedVectors[i],
+ ref = tuple[0],
+ elements = tuple[1]
+
+ fieldVectors[ref] = new lunr.Vector(elements)
+ }
+
+ for (var i = 0; i < serializedInvertedIndex.length; i++) {
+ var tuple = serializedInvertedIndex[i],
+ term = tuple[0],
+ posting = tuple[1]
+
+ tokenSetBuilder.insert(term)
+ invertedIndex[term] = posting
+ }
+
+ tokenSetBuilder.finish()
+
+ attrs.fields = serializedIndex.fields
+
+ attrs.fieldVectors = fieldVectors
+ attrs.invertedIndex = invertedIndex
+ attrs.tokenSet = tokenSetBuilder.root
+ attrs.pipeline = pipeline
+
+ return new lunr.Index(attrs)
+}
+/*!
+ * lunr.Builder
+ * Copyright (C) 2020 Oliver Nightingale
+ */
+
+/**
+ * lunr.Builder performs indexing on a set of documents and
+ * returns instances of lunr.Index ready for querying.
+ *
+ * All configuration of the index is done via the builder, the
+ * fields to index, the document reference, the text processing
+ * pipeline and document scoring parameters are all set on the
+ * builder before indexing.
+ *
+ * @constructor
+ * @property {string} _ref - Internal reference to the document reference field.
+ * @property {string[]} _fields - Internal reference to the document fields to index.
+ * @property {object} invertedIndex - The inverted index maps terms to document fields.
+ * @property {object} documentTermFrequencies - Keeps track of document term frequencies.
+ * @property {object} documentLengths - Keeps track of the length of documents added to the index.
+ * @property {lunr.tokenizer} tokenizer - Function for splitting strings into tokens for indexing.
+ * @property {lunr.Pipeline} pipeline - The pipeline performs text processing on tokens before indexing.
+ * @property {lunr.Pipeline} searchPipeline - A pipeline for processing search terms before querying the index.
+ * @property {number} documentCount - Keeps track of the total number of documents indexed.
+ * @property {number} _b - A parameter to control field length normalization, setting this to 0 disabled normalization, 1 fully normalizes field lengths, the default value is 0.75.
+ * @property {number} _k1 - A parameter to control how quickly an increase in term frequency results in term frequency saturation, the default value is 1.2.
+ * @property {number} termIndex - A counter incremented for each unique term, used to identify a terms position in the vector space.
+ * @property {array} metadataWhitelist - A list of metadata keys that have been whitelisted for entry in the index.
+ */
+lunr.Builder = function () {
+ this._ref = "id"
+ this._fields = Object.create(null)
+ this._documents = Object.create(null)
+ this.invertedIndex = Object.create(null)
+ this.fieldTermFrequencies = {}
+ this.fieldLengths = {}
+ this.tokenizer = lunr.tokenizer
+ this.pipeline = new lunr.Pipeline
+ this.searchPipeline = new lunr.Pipeline
+ this.documentCount = 0
+ this._b = 0.75
+ this._k1 = 1.2
+ this.termIndex = 0
+ this.metadataWhitelist = []
+}
+
+/**
+ * Sets the document field used as the document reference. Every document must have this field.
+ * The type of this field in the document should be a string, if it is not a string it will be
+ * coerced into a string by calling toString.
+ *
+ * The default ref is 'id'.
+ *
+ * The ref should _not_ be changed during indexing, it should be set before any documents are
+ * added to the index. Changing it during indexing can lead to inconsistent results.
+ *
+ * @param {string} ref - The name of the reference field in the document.
+ */
+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 <caption>Extracting a nested field</caption>
+ * 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
+ * not cause errors but will limit the chance of that document being retrieved by searches.
+ *
+ * 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.
+ *
+ * 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.
+ Get the name and version of a macOS release from the Darwin version.
+
+ @param release - By default, the current operating system is used, but you can supply a custom [Darwin kernel version](https://en.wikipedia.org/wiki/Darwin_%28operating_system%29#Release_history), which is the output of [`os.release()`](https://nodejs.org/api/os.html#os_os_release).
+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.
+By default, the current operating system is used, but you can supply a custom [Darwin kernel version](https://en.wikipedia.org/wiki/Darwin_%28operating_system%29#Release_history), which is the output of [`os.release()`](https://nodejs.org/api/os.html#os_os_release).
+
+## Related
+
+- [os-name](https://github.com/sindresorhus/os-name) - Get the name of the current operating system. Example: `macOS Sierra`
+- [macos-version](https://github.com/sindresorhus/macos-version) - Get the macOS version of the current system. Example: `10.9.3`
+- [win-release](https://github.com/sindresorhus/win-release) - Get the name of a Windows version from the release number: `5.1.2600` → `XP`
+
+---
+
+<div align="center">
+ <b>
+ <a href="https://tidelift.com/subscription/pkg/npm-macos-release?utm_source=npm-macos-release&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
+ </b>
+ <br>
+ <sub>
+ Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
+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.