Created
December 4, 2020 21:35
-
-
Save dspdog/105faa58bd8493c81f0b51bcc6046555 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var util = require('util'), | |
Classifier = require('./classifier'); | |
var BayesClassifier = function(smoothing) { | |
Classifier.call(this); | |
this.classFeatures = {}; | |
this.classTotals = {}; | |
this.totalExamples = 1; // start at one to smooth | |
this.smoothing = smoothing === undefined ? 1.0 : smoothing; | |
}; | |
util.inherits(BayesClassifier, Classifier); | |
function addExample(observation, label) { | |
if(!this.classFeatures[label]) { | |
this.classFeatures[label] = {}; | |
this.classTotals[label] = 1; // give an extra for smoothing | |
} | |
if(observation instanceof Array) { | |
var i = observation.length; | |
this.totalExamples++; | |
this.classTotals[label]++; | |
while(i--) { | |
if(observation[i]) { | |
if(this.classFeatures[label][i]) { | |
this.classFeatures[label][i]++; | |
} else { | |
// give an extra for smoothing | |
this.classFeatures[label][i] = 1 + this.smoothing; | |
} | |
} | |
} | |
} else { | |
// sparse observation | |
for(var key in observation){ | |
value = observation[key]; | |
if(this.classFeatures[label][value]) { | |
this.classFeatures[label][value]++; | |
} else { | |
// give an extra for smoothing | |
this.classFeatures[label][value] = 1 + this.smoothing; | |
} | |
} | |
} | |
} | |
function train() { | |
} | |
function probabilityOfClass(observation, label) { | |
var prob = 0; | |
if(observation instanceof Array){ | |
var i = observation.length; | |
while(i--) { | |
if(observation[i]) { | |
var count = this.classFeatures[label][i] || this.smoothing; | |
// numbers are tiny, add logs rather than take product | |
prob += Math.log(count / this.classTotals[label]); | |
} | |
} | |
} else { | |
// sparse observation | |
for(var key in observation){ | |
var count = this.classFeatures[label][observation[key]] || this.smoothing; | |
// numbers are tiny, add logs rather than take product | |
prob += Math.log(count / this.classTotals[label]); | |
} | |
} | |
// p(C) * unlogging the above calculation P(X|C) | |
prob = (this.classTotals[label] / this.totalExamples) * Math.exp(prob); | |
return prob; | |
} | |
function getClassifications(observation) { | |
var classifier = this; | |
var labels = []; | |
for(var className in this.classFeatures) { | |
labels.push({label: className, | |
value: classifier.probabilityOfClass(observation, className)}); | |
} | |
return labels.sort(function(x, y) { | |
return y.value - x.value; | |
}); | |
} | |
function restore(classifier) { | |
classifier = Classifier.restore(classifier); | |
classifier.__proto__ = BayesClassifier.prototype; | |
return classifier; | |
} | |
BayesClassifier.prototype.addExample = addExample; | |
BayesClassifier.prototype.train = train; | |
BayesClassifier.prototype.getClassifications = getClassifications; | |
BayesClassifier.prototype.probabilityOfClass = probabilityOfClass; | |
BayesClassifier.restore = restore; | |
module.exports = BayesClassifier; | |
},{"./classifier":2,"util":68}],2:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
function Classifier() { | |
} | |
function restore(classifier) { | |
classifier = typeof classifier == 'string' ? JSON.parse(classifier) : classifier; | |
return classifier; | |
} | |
function addExample(observation, classification) { | |
throw 'Not implemented'; | |
} | |
function classify(observation) { | |
var classifications = this.getClassifications(observation); | |
if(!classifications || classifications.length === 0) { | |
throw "Not Trained"; | |
} | |
return classifications[0].label; | |
} | |
function train() { | |
throw 'Not implemented'; | |
} | |
Classifier.prototype.addExample = addExample; | |
Classifier.prototype.train = train; | |
Classifier.prototype.classify = classify; | |
Classifier.restore = restore; | |
module.exports = Classifier; | |
},{}],3:[function(require,module,exports){ | |
exports.BayesClassifier = require('./classifier/bayes_classifier'); | |
//exports.LogisticRegressionClassifier = require('./classifier/logistic_regression_classifier'); | |
//exports.KMeans = require('./clusterer/kmeans'); | |
},{"./classifier/bayes_classifier":1}],4:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Rob Ellis, Chris Umbel | |
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. | |
*/ | |
var _ = require("underscore"); | |
/* | |
Sentences Analizer Class | |
From http://www.writingcentre.uottawa.ca/hypergrammar/sntpurps.html | |
Take a POS input and analyse it for | |
- Type of Sentense | |
- Interrogative | |
- Tag Questions | |
- | |
- Declarative | |
- Exclamatory | |
- Imperative | |
- Parts of a Sentense | |
- Subject | |
- Predicate | |
- Show Preposition Phrases | |
*/ | |
var Sentences = function(pos, callback) { | |
this.posObj = pos; | |
this.senType = null; | |
callback(this); | |
}; | |
Sentences.prototype.part = function(callback) { | |
var subject = [], | |
predicat = [], | |
verbFound = false; | |
this.prepositionPhrases(); | |
for (var i = 0; i < this.posObj.tags.length; i++) { | |
if (this.posObj.tags[i].pos == "VB") { | |
if (i === 0) { | |
verbFound = true; | |
} else { | |
// We need to Test for any EX before the VB | |
if (this.posObj.tags[i - 1].pos != "EX") { | |
verbFound = true; | |
} else { | |
predicat.push(this.posObj.tags[i].token); | |
} | |
} | |
} | |
// Add Pronoun Phrase (pp) Or Subject Phrase (sp) | |
if (!verbFound) { | |
if (this.posObj.tags[i].pp != true) | |
this.posObj.tags[i].spos = "SP"; | |
subject.push(this.posObj.tags[i].token); | |
} else { | |
if (this.posObj.tags[i].pp != true) | |
this.posObj.tags[i].spos = "PP"; | |
predicat.push(this.posObj.tags[i].token) | |
} | |
} | |
if (subject.length == 0) { | |
this.posObj.tags.push({token:"You",spos:"SP",pos:"PRP",added:true}); | |
} | |
callback(this); | |
}; | |
// Takes POS and removes IN to NN or NNS | |
// Adds a PP for each prepositionPhrases | |
Sentences.prototype.prepositionPhrases = function() { | |
var remove = false; | |
for (var i = 0; i < this.posObj.tags.length; i++) { | |
if (this.posObj.tags[i].pos.match("IN")) { | |
remove = true; | |
} | |
if (remove) { | |
this.posObj.tags[i].pp = true; | |
} | |
if (this.posObj.tags[i].pos.match("NN")) { | |
remove = false; | |
} | |
} | |
}; | |
Sentences.prototype.subjectToString = function() { | |
return this.posObj.tags.map(function(t){ if (t.spos == "SP" || t.spos == "S" ) return t.token }).join(' '); | |
}; | |
Sentences.prototype.predicateToString = function() { | |
return this.posObj.tags.map(function(t){ if (t.spos == "PP" || t.spos == "P" ) return t.token }).join(' '); | |
}; | |
Sentences.prototype.implicitYou = function() { | |
for (var i = 0; i < this.posObj.tags.length;i++) { | |
if (this.posObj.tags[i].added) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
Sentences.prototype.toString = function() { | |
return this.posObj.tags.map(function(t){return t.token}).join(' '); | |
}; | |
// This is quick and incomplete. | |
Sentences.prototype.type = function(callback) { | |
var callback = callback || false; | |
// Check for implicit you before popping a tag. | |
var implicitYou = this.implicitYou(); | |
// FIXME - punct seems useless | |
var lastElement = this.posObj.punct(); | |
lastElement = (lastElement.length != 0) ? lastElement.pop() : this.posObj.tags.pop(); | |
if (lastElement.pos !== ".") { | |
if (implicitYou) { | |
this.senType = "COMMAND"; | |
} else if (_(["WDT","WP","WP$","WRB"]).contains(this.posObj.tags[0].pos)) { | |
// Sentences that start with: who, what where when why and how, then they are questions | |
this.senType = "INTERROGATIVE"; | |
} else if (_(["PRP"]).contains(lastElement.pos)) { | |
// Sentences that end in a Personal pronoun are most likely questions | |
// eg. We should run away, should we [?] | |
// eg. You want to see that again, do you [?] | |
this.senType = "INTERROGATIVE"; | |
} else { | |
this.senType = "UNKNOWN"; | |
} | |
} else { | |
switch(lastElement.token) { | |
case "?": this.senType = "INTERROGATIVE"; break; | |
case "!": this.senType = (implicitYou) ? "COMMAND":"EXCLAMATORY"; break; | |
case ".": this.senType = (implicitYou) ? "COMMAND":"DECLARATIVE"; break; | |
} | |
} | |
if (callback && _(callback).isFunction()) { | |
callback(this); | |
} else { | |
return this.senType; | |
} | |
}; | |
module.exports = Sentences; | |
},{"underscore":43}],5:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var util = require('util'), | |
Classifier = require('./classifier'), | |
ApparatusBayesClassifier = require('apparatus').BayesClassifier; | |
var BayesClassifier = function(stemmer, smoothing) { | |
var abc = new ApparatusBayesClassifier(); | |
if (smoothing && isFinite(smoothing)) { | |
abc = new ApparatusBayesClassifier(smoothing); | |
} | |
Classifier.call(this, abc, stemmer); | |
}; | |
util.inherits(BayesClassifier, Classifier); | |
function restore(classifier, stemmer) { | |
classifier = Classifier.restore(classifier, stemmer); | |
classifier.__proto__ = BayesClassifier.prototype; | |
classifier.classifier = ApparatusBayesClassifier.restore(classifier.classifier); | |
return classifier; | |
} | |
function load(filename, stemmer, callback) { | |
Classifier.load(filename, function(err, classifier) { | |
if (err) { | |
return callback(err); | |
} | |
else { | |
callback(err, restore(classifier, stemmer)); | |
} | |
}); | |
} | |
BayesClassifier.restore = restore; | |
BayesClassifier.load = load; | |
module.exports = BayesClassifier; | |
},{"./classifier":6,"apparatus":3,"util":68}],6:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var PorterStemmer = require('../stemmers/porter_stemmer'), | |
util = require('util'), | |
events = require('events'), | |
os = require('os'); | |
try { | |
var Threads = null;//require('webworker-threads'); | |
} catch (e) { | |
// Since webworker-threads are optional, only thow if the module is found | |
if (e.code !== 'MODULE_NOT_FOUND') throw e; | |
} | |
function checkThreadSupport() { | |
if (typeof Threads === 'undefined') { | |
throw new Error('parallel classification requires the optional dependency webworker-threads'); | |
} | |
} | |
var Classifier = function(classifier, stemmer) { | |
this.classifier = classifier; | |
this.docs = []; | |
this.features = {}; | |
this.stemmer = stemmer || PorterStemmer; | |
this.lastAdded = 0; | |
this.events = new events.EventEmitter(); | |
}; | |
function addDocument(text, classification) { | |
// Ignore further processing if classification is undefined | |
if(typeof classification === 'undefined') return; | |
// If classification is type of string then make sure it's dosen't have blank space at both end | |
if(typeof classification === 'string'){ | |
classification = classification.trim(); | |
} | |
if(typeof text === 'string') | |
text = this.stemmer.tokenizeAndStem(text, this.keepStops); | |
if(text.length === 0) { | |
// ignore empty documents | |
return; | |
} | |
this.docs.push({ | |
label: classification, | |
text: text | |
}); | |
for (var i = 0; i < text.length; i++) { | |
var token = text[i]; | |
this.features[token] = (this.features[token] || 0) + 1; | |
} | |
} | |
function removeDocument(text, classification) { | |
var docs = this.docs | |
, doc | |
, pos; | |
if (typeof text === 'string') { | |
text = this.stemmer.tokenizeAndStem(text, this.keepStops); | |
} | |
for (var i = 0, ii = docs.length; i < ii; i++) { | |
doc = docs[i]; | |
if (doc.text.join(' ') == text.join(' ') && | |
doc.label == classification) { | |
pos = i; | |
} | |
} | |
// Remove if there's a match | |
if (!isNaN(pos)) { | |
this.docs.splice(pos, 1); | |
for (var i = 0, ii = text.length; i < ii; i++) { | |
delete this.features[text[i]]; | |
} | |
} | |
} | |
function textToFeatures(observation) { | |
var features = []; | |
if(typeof observation === 'string') | |
observation = this.stemmer.tokenizeAndStem(observation, this.keepStops); | |
for(var feature in this.features) { | |
if(observation.indexOf(feature) > -1) | |
features.push(1); | |
else | |
features.push(0); | |
} | |
return features; | |
} | |
function docsToFeatures(docs) { | |
var parsedDocs = []; | |
for (var i = 0; i < docs.length; i++) { | |
var features = []; | |
for (var feature in FEATURES) { | |
if (docs[i].observation.indexOf(feature) > -1) | |
features.push(1); | |
else | |
features.push(0); | |
} | |
parsedDocs.push({ | |
index: docs[i].index, | |
features: features | |
}); | |
} | |
return JSON.stringify(parsedDocs); | |
} | |
function train() { | |
var totalDocs = this.docs.length; | |
for(var i = this.lastAdded; i < totalDocs; i++) { | |
var features = this.textToFeatures(this.docs[i].text); | |
this.classifier.addExample(features, this.docs[i].label); | |
this.events.emit('trainedWithDocument', {index: i, total: totalDocs, doc: this.docs[i]}); | |
this.lastAdded++; | |
} | |
this.events.emit('doneTraining', true); | |
this.classifier.train(); | |
} | |
function trainParallel(numThreads, callback) { | |
checkThreadSupport(); | |
if (!callback) { | |
callback = numThreads; | |
numThreads = undefined; | |
} | |
if (isNaN(numThreads)) { | |
numThreads = os.cpus().length; | |
} | |
var totalDocs = this.docs.length; | |
var threadPool = Threads.createPool(numThreads); | |
var docFeatures = {}; | |
var finished = 0; | |
var self = this; | |
// Init pool; send the features array and the parsing function | |
threadPool.all.eval('var FEATURES = ' + JSON.stringify(this.features)); | |
threadPool.all.eval(docsToFeatures); | |
// Convert docs to observation objects | |
var obsDocs = []; | |
for (var i = this.lastAdded; i < totalDocs; i++) { | |
var observation = this.docs[i].text; | |
if (typeof observation === 'string') | |
observation = this.stemmer.tokenizeAndStem(observation, this.keepStops); | |
obsDocs.push({ | |
index: i, | |
observation: observation | |
}); | |
} | |
// Called when a batch completes processing | |
var onFeaturesResult = function(docs) { | |
setTimeout(function() { | |
self.events.emit('processedBatch', { | |
size: docs.length, | |
docs: totalDocs, | |
batches: numThreads, | |
index: finished | |
}); | |
}); | |
for (var j = 0; j < docs.length; j++) { | |
docFeatures[docs[j].index] = docs[j].features; | |
} | |
}; | |
// Called when all batches finish processing | |
var onFinished = function(err) { | |
if (err) { | |
threadPool.destroy(); | |
return callback(err); | |
} | |
for (var j = self.lastAdded; j < totalDocs; j++) { | |
self.classifier.addExample(docFeatures[j], self.docs[j].label); | |
self.events.emit('trainedWithDocument', { | |
index: j, | |
total: totalDocs, | |
doc: self.docs[j] | |
}); | |
self.lastAdded++; | |
} | |
self.events.emit('doneTraining', true); | |
self.classifier.train(); | |
threadPool.destroy(); | |
callback(null); | |
}; | |
// Split the docs and start processing | |
var batchSize = Math.ceil(obsDocs.length / numThreads); | |
var lastError; | |
for (var i = 0; i < numThreads; i++) { | |
var batchDocs = obsDocs.slice(i * batchSize, (i+1) * batchSize); | |
var batchJson = JSON.stringify(batchDocs); | |
threadPool.any.eval('docsToFeatures(' + batchJson + ')', function(err, docs) { | |
lastError = err || lastError; | |
finished++; | |
if (docs) { | |
docs = JSON.parse(docs); | |
onFeaturesResult(docs); | |
} | |
if (finished >= numThreads) { | |
onFinished(lastError); | |
} | |
}); | |
} | |
} | |
function trainParallelBatches(options) { | |
checkThreadSupport(); | |
var numThreads = options && options.numThreads; | |
var batchSize = options && options.batchSize; | |
if (isNaN(numThreads)) { | |
numThreads = os.cpus().length; | |
} | |
if (isNaN(batchSize)) { | |
batchSize = 2500; | |
} | |
var totalDocs = this.docs.length; | |
var threadPool = Threads.createPool(numThreads); | |
var docFeatures = {}; | |
var finished = 0; | |
var self = this; | |
var abort = false; | |
var onError = function(err) { | |
if (!err || abort) return; | |
abort = true; | |
threadPool.destroy(true); | |
self.events.emit('doneTrainingError', err); | |
}; | |
// Init pool; send the features array and the parsing function | |
var str = JSON.stringify(this.features); | |
threadPool.all.eval('var FEATURES = ' + str + ';', onError); | |
threadPool.all.eval(docsToFeatures, onError); | |
// Convert docs to observation objects | |
var obsDocs = []; | |
for (var i = this.lastAdded; i < totalDocs; i++) { | |
var observation = this.docs[i].text; | |
if (typeof observation === 'string') | |
observation = this.stemmer.tokenizeAndStem(observation, this.keepStops); | |
obsDocs.push({ | |
index: i, | |
observation: observation | |
}); | |
} | |
// Split the docs in batches | |
var obsBatches = []; | |
var i = 0; | |
while (true) { | |
var batch = obsDocs.slice(i * batchSize, (i+1) * batchSize); | |
if (!batch || !batch.length) break; | |
obsBatches.push(batch); | |
i++; | |
} | |
obsDocs = null; | |
self.events.emit('startedTraining', { | |
docs: totalDocs, | |
batches: obsBatches.length | |
}); | |
// Called when a batch completes processing | |
var onFeaturesResult = function(docs) { | |
self.events.emit('processedBatch', { | |
size: docs.length, | |
docs: totalDocs, | |
batches: obsBatches.length, | |
index: finished | |
}); | |
for (var j = 0; j < docs.length; j++) { | |
docFeatures[docs[j].index] = docs[j].features; | |
} | |
}; | |
// Called when all batches finish processing | |
var onFinished = function() { | |
threadPool.destroy(true); | |
abort = true; | |
for (var j = self.lastAdded; j < totalDocs; j++) { | |
self.classifier.addExample(docFeatures[j], self.docs[j].label); | |
self.events.emit('trainedWithDocument', { | |
index: j, | |
total: totalDocs, | |
doc: self.docs[j] | |
}); | |
self.lastAdded++; | |
} | |
self.events.emit('doneTraining', true); | |
self.classifier.train(); | |
}; | |
// Called to send the next batch to be processed | |
var batchIndex = 0; | |
var sendNext = function() { | |
if (abort) return; | |
if (batchIndex >= obsBatches.length) { | |
return; | |
} | |
sendBatch(JSON.stringify(obsBatches[batchIndex])); | |
batchIndex++; | |
}; | |
// Called to send a batch of docs to the threads | |
var sendBatch = function(batchJson) { | |
if (abort) return; | |
threadPool.any.eval('docsToFeatures(' + batchJson + ');', function(err, docs) { | |
if (err) { | |
return onError(err); | |
} | |
finished++; | |
if (docs) { | |
docs = JSON.parse(docs); | |
setTimeout(onFeaturesResult.bind(null, docs)); | |
} | |
if (finished >= obsBatches.length) { | |
setTimeout(onFinished); | |
} | |
setTimeout(sendNext); | |
}); | |
}; | |
// Start processing | |
for (var i = 0; i < numThreads; i++) { | |
sendNext(); | |
} | |
} | |
function retrain() { | |
this.classifier = new (this.classifier.constructor)(); | |
this.lastAdded = 0; | |
this.train(); | |
} | |
function retrainParallel(numThreads, callback) { | |
this.classifier = new (this.classifier.constructor)(); | |
this.lastAdded = 0; | |
this.trainParallel(numThreads, callback); | |
} | |
function getClassifications(observation) { | |
return this.classifier.getClassifications(this.textToFeatures(observation)); | |
} | |
function classify(observation) { | |
return this.classifier.classify(this.textToFeatures(observation)); | |
} | |
function restore(classifier, stemmer) { | |
classifier.stemmer = stemmer || PorterStemmer; | |
classifier.events = new events.EventEmitter(); | |
return classifier; | |
} | |
function save(filename, callback) { | |
var data = JSON.stringify(this); | |
var fs = require('fs'); | |
var classifier = this; | |
fs.writeFile(filename, data, 'utf8', function(err) { | |
if(callback) { | |
callback(err, err ? null : classifier); | |
} | |
}); | |
} | |
function load(filename, callback) { | |
var fs = require('fs'); | |
fs.readFile(filename, 'utf8', function(err, data) { | |
var classifier; | |
if(!err) { | |
classifier = JSON.parse(data); | |
} | |
if(callback) | |
callback(err, classifier); | |
}); | |
} | |
function setOptions(options){ | |
this.keepStops = (options.keepStops) ? true : false; | |
} | |
Classifier.prototype.addDocument = addDocument; | |
Classifier.prototype.removeDocument = removeDocument; | |
Classifier.prototype.train = train; | |
if (Threads) { | |
Classifier.prototype.trainParallel = trainParallel; | |
Classifier.prototype.trainParallelBatches = trainParallelBatches; | |
Classifier.prototype.retrainParallel = retrainParallel; | |
} | |
Classifier.prototype.retrain = retrain; | |
Classifier.prototype.classify = classify; | |
Classifier.prototype.textToFeatures = textToFeatures; | |
Classifier.prototype.save = save; | |
Classifier.prototype.getClassifications = getClassifications; | |
Classifier.prototype.setOptions = setOptions; | |
Classifier.restore = restore; | |
Classifier.load = load; | |
module.exports = Classifier; | |
},{"../stemmers/porter_stemmer":26,"events":53,"fs":44,"os":64,"util":68}],7:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var util = require('util'), | |
Classifier = require('./classifier'), | |
ApparatusLogisticRegressionClassifier = require('apparatus').LogisticRegressionClassifier; | |
var LogisticRegressionClassifier = function(stemmer) { | |
Classifier.call(this, new ApparatusLogisticRegressionClassifier(), stemmer); | |
}; | |
util.inherits(LogisticRegressionClassifier, Classifier); | |
function restore(classifier, stemmer) { | |
classifier = Classifier.restore(classifier, stemmer); | |
classifier.__proto__ = LogisticRegressionClassifier.prototype; | |
classifier.classifier = ApparatusLogisticRegressionClassifier.restore(classifier.classifier); | |
return classifier; | |
} | |
function load(filename, stemmer, callback) { | |
Classifier.load(filename, function(err, classifier) { | |
if (err) { | |
callback(err); | |
} | |
else { | |
callback(err, restore(classifier, stemmer)); | |
} | |
}); | |
} | |
function train() { | |
// we need to reset the traning state because logistic regression | |
// needs its matricies to have their widths synced, etc. | |
this.lastAdded = 0; | |
this.classifier = new ApparatusLogisticRegressionClassifier(); | |
Classifier.prototype.train.call(this); | |
} | |
LogisticRegressionClassifier.prototype.train = train; | |
LogisticRegressionClassifier.restore = restore; | |
LogisticRegressionClassifier.load = load; | |
module.exports = LogisticRegressionClassifier; | |
},{"./classifier":6,"apparatus":3,"util":68}],8:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, John Crepezzi, Chris Umbel | |
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. | |
*/ | |
// Get all of the pairs of letters for a string | |
var letterPairs = function (str) { | |
var numPairs = str.length - 1; | |
var pairs = new Array(numPairs); | |
for (var i = 0; i < numPairs; i++) { | |
pairs[i] = str.substring(i, i + 2); | |
} | |
return pairs; | |
}; | |
// Get all of the pairs in all of the words for a string | |
var wordLetterPairs = function (str) { | |
var allPairs = [], pairs; | |
var words = str.split(/\s+/); | |
for (var i = 0; i < words.length; i++) { | |
pairs = letterPairs(words[i]); | |
allPairs.push.apply(allPairs, pairs); | |
} | |
return allPairs; | |
}; | |
// Perform some sanitization steps | |
var sanitize = function (str) { | |
return str.toLowerCase().replace(/^\s+|\s+$/g, ''); | |
}; | |
// Compare two strings, and spit out a number from 0-1 | |
var compare = function (str1, str2) { | |
var sanitized_str1 = sanitize(str1); | |
var sanitized_str2 = sanitize(str2); | |
var pairs1 = wordLetterPairs(sanitized_str1); | |
var pairs2 = wordLetterPairs(sanitized_str2); | |
var intersection = 0, union = pairs1.length + pairs2.length; | |
if (union === 0) { | |
if (sanitized_str1 === sanitized_str2) { | |
return 1; | |
} else { | |
return 0; | |
} | |
} else { | |
var i, j, pair1, pair2; | |
for (i = 0; i < pairs1.length; i++) { | |
pair1 = pairs1[i]; | |
for (j = 0; j < pairs2.length; j++) { | |
pair2 = pairs2[j]; | |
if (pair1 == pair2) { | |
intersection ++; | |
delete pairs2[j]; | |
break; | |
} | |
} | |
} | |
return 2 * intersection / union; | |
} | |
}; | |
module.exports = compare; | |
},{}],9:[function(require,module,exports){ | |
/* | |
Copyright (c) 2018, Shane Caldwell, Hugo ter Doest | |
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. | |
*/ | |
// Computes the Hamming distance between two string -- intrepreted from: | |
// https://en.wikipedia.org/wiki/Hamming_distance | |
// s1 is the first string to compare | |
// s2 is the second string to compare | |
// Strings should have equal length | |
function HammingDistance(s1, s2, ignoreCase) { | |
// Return -1 if one of the parameters is not a string | |
if (typeof(s1) != "string" || typeof(s2) != "string") { | |
return -1; | |
} | |
// Return -1 the lengths of the strings differ | |
if (s1.length != s2.length) { | |
return -1; | |
} | |
if (ignoreCase) { | |
s1 = s1.toLowerCase(); | |
s2 = s2.toLowerCase(); | |
} | |
var diffs = 0; | |
for (var i = 0; i < s1.length; i++) { | |
if (s1[i] != s2[i]) { | |
diffs++; | |
} | |
} | |
return diffs; | |
} | |
module.exports = HammingDistance; | |
},{}],10:[function(require,module,exports){ | |
/* | |
Copyright (c) 2012, Adam Phillabaum, Chris Umbel | |
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. | |
Unless otherwise stated by a specific section of code | |
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. | |
*/ | |
// Computes the Jaro distance between two string -- intrepreted from: | |
// http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance | |
// s1 is the first string to compare | |
// s2 is the second string to compare | |
function distance(s1, s2) { | |
if (typeof(s1) !== "string" || typeof(s2) !== "string") { | |
return 0; | |
} | |
if (s1.length === 0 || s2.length === 0) { | |
return 0; | |
} | |
var matchWindow = (Math.floor(Math.max(s1.length, s2.length) / 2.0)) - 1; | |
var matches1 = new Array(s1.length); | |
var matches2 = new Array(s2.length); | |
var m = 0; // number of matches | |
var t = 0; // number of transpositions | |
var i = 0; // index for string 1 | |
var k = 0; // index for string 2 | |
//debug helpers | |
//console.log("s1: " + s1 + "; s2: " + s2); | |
//console.log(" - matchWindow: " + matchWindow); | |
for (i = 0; i < s1.length; i++) { // loop to find matched characters | |
var start = Math.max(0, (i - matchWindow)); // use the higher of the window diff | |
var end = Math.min((i + matchWindow + 1), s2.length); // use the min of the window and string 2 length | |
for (k = start; k < end; k++) { // iterate second string index | |
if (matches2[k]) { // if second string character already matched | |
continue; | |
} | |
if (s1[i] !== s2[k]) { // characters don't match | |
continue; | |
} | |
// assume match if the above 2 checks don't continue | |
matches1[i] = true; | |
matches2[k] = true; | |
m++; | |
break; | |
} | |
} | |
// nothing matched | |
if (m === 0) { | |
return 0.0; | |
} | |
k = 0; // reset string 2 index | |
for(i = 0; i < s1.length; i++) { // loop to find transpositions | |
if (!matches1[i]) { // non-matching character | |
continue; | |
} | |
while(!matches2[k]) { // move k index to the next match | |
k++; | |
} | |
if (s1[i] !== s2[k]) { // if the characters don't match, increase transposition | |
// HtD: t is always less than the number of matches m, because transpositions are a subset of matches | |
t++; | |
} | |
k++; // iterate k index normally | |
} | |
// transpositions divided by 2 | |
t = t / 2.0; | |
return ((m / s1.length) + (m / s2.length) + ((m - t) / m)) / 3.0; // HtD: therefore, m - t > 0, and m - t < m | |
// HtD: => return value is between 0 and 1 | |
} | |
// Computes the Winkler distance between two string -- intrepreted from: | |
// http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance | |
// s1 is the first string to compare | |
// s2 is the second string to compare | |
// dj is the Jaro Distance (if you've already computed it), leave blank and the method handles it | |
// ignoreCase: if true strings are first converted to lower case before comparison | |
function JaroWinklerDistance(s1, s2, dj, ignoreCase) { | |
if (s1 === s2) { | |
return 1; | |
} else { | |
if (ignoreCase) { | |
s1 = s1.toLowerCase(); | |
s2 = s2.toLowerCase(); | |
} | |
//console.log(news1); | |
//console.log(news2); | |
var jaro = (typeof(dj) === 'undefined') ? distance(s1, s2) : dj; | |
var p = 0.1; // default scaling factor | |
var l = 0 // length of the matching prefix | |
while(s1[l] === s2[l] && l < 4) { | |
l++; | |
} | |
// HtD: 1 - jaro >= 0 | |
return jaro + l * p * (1 - jaro); | |
} | |
} | |
module.exports = JaroWinklerDistance; | |
},{}],11:[function(require,module,exports){ | |
/* | |
Copyright (c) 2012, Sid Nallu, Chris Umbel | |
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. | |
*/ | |
/* | |
* contribution by sidred123 | |
*/ | |
/* | |
* Compute the Levenshtein distance between two strings. | |
* Algorithm based from Speech and Language Processing - Daniel Jurafsky and James H. Martin. | |
*/ | |
var _ = require('underscore'); | |
// Walk the path back from the matchEnd to the beginning of the match. | |
// Do this by traversing the distanceMatrix as you would a linked list, | |
// following going from cell child to parent until reach row 0. | |
function _getMatchStart(distanceMatrix, matchEnd, sourceLength) { | |
var row = sourceLength; | |
var column = matchEnd; | |
var tmpRow; | |
var tmpColumn; | |
// match will be empty string | |
if (matchEnd === 0) { return 0; } | |
while(row > 1 && column > 1) { | |
tmpRow = row; | |
tmpColumn = column; | |
row = distanceMatrix[tmpRow][tmpColumn].parentCell.row; | |
column = distanceMatrix[tmpRow][tmpColumn].parentCell.column; | |
} | |
return column-1; | |
} | |
function getMinCostSubstring(distanceMatrix, source, target) { | |
var sourceLength = source.length; | |
var targetLength = target.length; | |
var minDistance = sourceLength + targetLength; | |
var matchEnd = targetLength; | |
// Find minimum value in last row of the cost matrix. This cell marks the | |
// end of the match string. | |
for (var column = 0; column <= targetLength; column++) { | |
if (minDistance > distanceMatrix[sourceLength][column].cost) { | |
minDistance = distanceMatrix[sourceLength][column].cost; | |
matchEnd = column; | |
} | |
} | |
var matchStart = _getMatchStart(distanceMatrix, matchEnd, sourceLength); | |
return {substring: target.slice(matchStart, matchEnd), distance: minDistance, offset: matchStart}; | |
} | |
/* | |
* Returns the Damerau-Levenshtein distance between strings. Counts the distance | |
* between two strings by returning the number of edit operations required to | |
* convert `source` into `target`. | |
* | |
* Valid edit operations are: | |
* - transposition, insertion, deletion, and substitution | |
* | |
* Options: | |
* insertion_cost: (default: 1) | |
* deletion_cost: number (default: 1) | |
* substitution_cost: number (default: 1) | |
* transposition_cost: number (default: 1) | |
* search: boolean (default: false) | |
* restricted: boolean (default: false) | |
*/ | |
function DamerauLevenshteinDistance(source, target, options) { | |
var damLevOptions = _.extend( | |
{ transposition_cost: 1, restricted: false }, | |
options || {}, | |
{ damerau: true } | |
); | |
return levenshteinDistance(source, target, damLevOptions); | |
} | |
function LevenshteinDistance(source, target, options) { | |
var levOptions = _.extend({}, options || {}, { damerau: false }); | |
return levenshteinDistance(source, target, levOptions); | |
} | |
function levenshteinDistance (source, target, options) { | |
if(isNaN(options.insertion_cost)) options.insertion_cost = 1; | |
if(isNaN(options.deletion_cost)) options.deletion_cost = 1; | |
if(isNaN(options.substitution_cost)) options.substitution_cost = 1; | |
if(typeof options.search !== 'boolean') options.search = false; | |
var isUnrestrictedDamerau = options.damerau && !options.restricted; | |
var isRestrictedDamerau = options.damerau && options.restricted; | |
if (isUnrestrictedDamerau) { | |
var lastRowMap = {}; | |
} | |
var sourceLength = source.length; | |
var targetLength = target.length; | |
var distanceMatrix = [[{cost: 0}]]; //the root, has no parent cell | |
for (var row = 1; row <= sourceLength; row++) { | |
distanceMatrix[row] = []; | |
distanceMatrix[row][0] = {cost: distanceMatrix[row-1][0].cost + options.deletion_cost, parentCell: {row: row-1, column: 0}}; | |
} | |
for (var column = 1; column <= targetLength; column++) { | |
if (options.search) { | |
distanceMatrix[0][column] = {cost: 0}; | |
} else { | |
distanceMatrix[0][column] = {cost: distanceMatrix[0][column-1].cost + options.insertion_cost, parentCell: {row: 0, column: column-1}}; | |
} | |
} | |
for (var row = 1; row <= sourceLength; row++) { | |
if (isUnrestrictedDamerau) { | |
var lastColMatch = null; | |
} | |
for (var column = 1; column <= targetLength; column++) { | |
var costToInsert = distanceMatrix[row][column-1].cost + options.insertion_cost; | |
var costToDelete = distanceMatrix[row-1][column].cost + options.deletion_cost; | |
var sourceElement = source[row-1]; | |
var targetElement = target[column-1]; | |
var costToSubstitute = distanceMatrix[row-1][column-1].cost; | |
if (sourceElement !== targetElement) { | |
costToSubstitute = costToSubstitute + options.substitution_cost; | |
} | |
var possibleParents = [ | |
{cost: costToInsert, coordinates: {row: row, column: column-1}}, | |
{cost: costToDelete, coordinates: {row: row-1, column: column}}, | |
{cost: costToSubstitute, coordinates: {row: row-1, column: column-1}} | |
]; | |
// We can add damerau to the possibleParents if the current | |
// target-letter has been encountered in our lastRowMap, | |
// and if there exists a previous column in this row where the | |
// row & column letters matched | |
var canDamerau = isUnrestrictedDamerau | |
&& row > 1 && column > 1 | |
&& lastColMatch | |
&& targetElement in lastRowMap; | |
if (canDamerau) { | |
var lastRowMatch = lastRowMap[targetElement]; | |
var costBeforeTransposition = | |
distanceMatrix[lastRowMatch - 1][lastColMatch - 1].cost; | |
var costToTranspose = costBeforeTransposition | |
+ ((row - lastRowMatch - 1) * options.deletion_cost) | |
+ ((column - lastColMatch - 1) * options.insertion_cost) | |
+ options.transposition_cost; | |
possibleParents.push({ | |
cost: costToTranspose, | |
coordinates: { | |
row: lastRowMatch - 1, | |
column: lastColMatch - 1, | |
}, | |
}); | |
} | |
// Source and target chars are 1-indexed in the distanceMatrix so previous | |
// source/target element is (col/row - 2) | |
var canDoRestrictedDamerau = isRestrictedDamerau | |
&& row > 1 && column > 1 | |
&& sourceElement === target[column - 2] | |
&& source[row - 2] === targetElement; | |
if (canDoRestrictedDamerau) { | |
var costBeforeTransposition = distanceMatrix[row - 2][column - 2].cost; | |
possibleParents.push({ | |
cost: costBeforeTransposition + options.transposition_cost, | |
coordinates: { row: row - 2, column: column - 2 }, | |
}); | |
} | |
var minCostParent = _.min(possibleParents, function(p) { return p.cost; }); | |
distanceMatrix[row][column] = {cost: minCostParent.cost, parentCell: minCostParent.coordinates}; | |
if (isUnrestrictedDamerau) { | |
lastRowMap[sourceElement] = row; | |
if (sourceElement === targetElement) { | |
lastColMatch = column; | |
} | |
} | |
} | |
} | |
if (!options.search) { | |
return distanceMatrix[sourceLength][targetLength].cost; | |
} | |
return getMinCostSubstring(distanceMatrix, source, target); | |
} | |
module.exports = { | |
LevenshteinDistance: LevenshteinDistance, | |
DamerauLevenshteinDistance: DamerauLevenshteinDistance, | |
}; | |
},{"underscore":43}],12:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
function nthForm(i) { | |
var teenth = (i % 100); | |
if(teenth > 10 && teenth < 14) | |
return 'th'; | |
else { | |
switch(i % 10) { | |
case 1: | |
return 'st'; | |
break; | |
case 2: | |
return 'nd'; | |
break; | |
case 3: | |
return 'rd'; | |
break; | |
default: | |
return 'th'; | |
} | |
} | |
} | |
function nth(i) { | |
return i.toString() + nthForm(i); | |
} | |
var CountInflector = function() { | |
}; | |
CountInflector.nth = nth; | |
module.exports = CountInflector; | |
},{}],13:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var FormSet = function() { | |
this.regularForms = []; | |
this.irregularForms = {}; | |
} | |
module.exports = FormSet; | |
},{}],14:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var SingularPluralInflector = require('./singular_plural_inflector'), | |
util = require('util'), | |
FormSet = require('./form_set'); | |
function attach() { | |
var inflector = this; | |
String.prototype.singularizeNoun = function() { | |
return inflector.singularize(this); | |
} | |
String.prototype.pluralizeNoun = function() { | |
return inflector.pluralize(this); | |
} | |
} | |
var NounInflector = function() { | |
this.ambiguous = [ | |
'bison', 'bream', 'carp', 'chassis', 'christmas', 'cod', 'corps', 'debris', 'deer', | |
'diabetes', 'equipment', 'elk', 'fish', 'flounder', 'gallows', 'graffiti', | |
'headquarters', 'herpes', 'highjinks', 'homework', 'information', | |
'mackerel', 'mews', 'money', 'news', 'rice', 'rabies', 'salmon', 'series', | |
'sheep', 'shrimp', 'species', 'swine', 'tennis', 'trout', 'tuna', 'whiting', 'wildebeest' | |
]; | |
this.customPluralForms = []; | |
this.customSingularForms = []; | |
this.singularForms = new FormSet(); | |
this.pluralForms = new FormSet(); | |
this.attach = attach; | |
this.addIrregular("child", "children"); | |
this.addIrregular("man", "men"); | |
this.addIrregular("person", "people"); | |
this.addIrregular("sex", "sexes"); | |
this.addIrregular("mouse", "mice"); | |
this.addIrregular("ox", "oxen"); | |
this.addIrregular("foot", "feet"); | |
this.addIrregular("tooth", "teeth"); | |
this.addIrregular("goose", "geese"); | |
this.addIrregular("ephemeris", "ephemerides"); | |
this.addIrregular("cloth", "clothes"); | |
this.addIrregular("hero", "heroes"); | |
this.addIrregular("torso", "torsi"); | |
// see if it is possible to unify the creation of both the singular and | |
// plural regexes or maybe even just have one list. with a complete list | |
// of rules it may only be possible for some regular forms, but worth a shot | |
this.pluralForms.regularForms.push([/([aeiou]y)$/i, '$1s']); | |
this.pluralForms.regularForms.push([/y$/i, 'ies']); | |
this.pluralForms.regularForms.push([/ife$/i, 'ives']); | |
this.pluralForms.regularForms.push([/(antenn|formul|nebul|vertebr|vit)a$/i, '$1ae']); | |
this.pluralForms.regularForms.push([/(octop|vir|radi|nucle|fung|cact|stimul|alumn|calcul|hippopotam|macrofung|phoet|syllab|troph)us$/i, '$1i']); | |
this.pluralForms.regularForms.push([/(buffal|tomat|tornad)o$/i, '$1oes']); | |
this.pluralForms.regularForms.push([/(sis)$/i, 'ses']); | |
this.pluralForms.regularForms.push([/(matr|vert|ind|cort)(ix|ex)$/i, '$1ices']); | |
this.pluralForms.regularForms.push([/sses$/i, 'sses']); | |
this.pluralForms.regularForms.push([/(x|ch|ss|sh|s|z)$/i, '$1es']); | |
this.pluralForms.regularForms.push([/^(?!talis|.*hu)(.*)man$/i, '$1men']); | |
this.pluralForms.regularForms.push([/(.*)/i, '$1s']); | |
this.singularForms.regularForms.push([/([^v])ies$/i, '$1y']); | |
this.singularForms.regularForms.push([/ives$/i, 'ife']); | |
this.singularForms.regularForms.push([/(antenn|formul|nebul|vertebr|vit)ae$/i, '$1a']); | |
this.singularForms.regularForms.push([/(octop|vir|radi|nucle|fung|cact|stimul|alumn|calcul|hippopotam|macrofung|phoet|syllab|troph)(i)$/i, '$1us']); | |
this.singularForms.regularForms.push([/(buffal|tomat|tornad)(oes)$/i, '$1o']); | |
this.singularForms.regularForms.push([/(analy|naly|synop|parenthe|diagno|the)ses$/i, '$1sis']); | |
this.singularForms.regularForms.push([/(vert|ind|cort)(ices)$/i, '$1ex']); | |
// our pluralizer won''t cause this form of appendix (appendicies) | |
// but we should handle it | |
this.singularForms.regularForms.push([/(matr|append)(ices)$/i, '$1ix']); | |
this.singularForms.regularForms.push([/(x|ch|ss|sh|s|z)es$/i, '$1']); | |
this.singularForms.regularForms.push([/men$/i, 'man']); | |
this.singularForms.regularForms.push([/ss$/i, 'ss']); | |
this.singularForms.regularForms.push([/s$/i, '']); | |
this.pluralize = function (token) { | |
return this.ize(token, this.pluralForms, this.customPluralForms); | |
}; | |
this.singularize = function(token) { | |
return this.ize(token, this.singularForms, this.customSingularForms); | |
}; | |
}; | |
util.inherits(NounInflector, SingularPluralInflector); | |
module.exports = NounInflector; | |
},{"./form_set":13,"./singular_plural_inflector":16,"util":68}],15:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var util = require('util'), | |
SingularPluralInflector = require('./singular_plural_inflector'), | |
FormSet = require('./form_set'); | |
function attach() { | |
var inflector = this; | |
String.prototype.singularizePresentVerb = function() { | |
return inflector.singularize(this); | |
} | |
String.prototype.pluralizePresentVerb = function() { | |
return inflector.pluralize(this); | |
} | |
} | |
var VerbInflector = function() { | |
this.ambiguous = [ | |
'will' | |
]; | |
this.attach = attach; | |
this.customPluralForms = []; | |
this.customSingularForms = []; | |
this.singularForms = new FormSet(); | |
this.pluralForms = new FormSet(); | |
this.addIrregular("am", "are"); | |
this.addIrregular("is", "are"); | |
this.addIrregular("was", "were"); | |
this.addIrregular("has", "have"); | |
this.singularForms.regularForms.push([/ed$/i, 'ed']); | |
this.singularForms.regularForms.push([/ss$/i, 'sses']); | |
this.singularForms.regularForms.push([/x$/i, 'xes']); | |
this.singularForms.regularForms.push([/(h|z|o)$/i, '$1es']); | |
this.singularForms.regularForms.push([/$zz/i, 'zzes']); | |
this.singularForms.regularForms.push([/([^a|e|i|o|u])y$/i, '$1ies']); | |
this.singularForms.regularForms.push([/$/i, 's']); | |
this.pluralForms.regularForms.push([/sses$/i, 'ss']); | |
this.pluralForms.regularForms.push([/xes$/i, 'x']); | |
this.pluralForms.regularForms.push([/([cs])hes$/i, '$1h']); | |
this.pluralForms.regularForms.push([/zzes$/i, 'zz']); | |
this.pluralForms.regularForms.push([/([^h|z|o|i])es$/i, '$1e']); | |
this.pluralForms.regularForms.push([/ies$/i, 'y']);//flies->fly | |
this.pluralForms.regularForms.push([/e?s$/i, '']); | |
}; | |
util.inherits(VerbInflector, SingularPluralInflector); | |
module.exports = VerbInflector; | |
},{"./form_set":13,"./singular_plural_inflector":16,"util":68}],16:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var TenseInflector = function () { | |
}; | |
TenseInflector.prototype.addSingular = function(pattern, replacement) { | |
this.customSingularForms.push([pattern, replacement]); | |
}; | |
TenseInflector.prototype.addPlural = function(pattern, replacement) { | |
this.customPluralForms.push([pattern, replacement]); | |
}; | |
TenseInflector.prototype.ize = function (token, formSet, customForms) { | |
var restoreCase = this.restoreCase(token); | |
return restoreCase(this.izeRegExps(token, customForms) || this.izeAbiguous(token) || | |
this.izeRegulars(token, formSet) || this.izeRegExps(token, formSet.regularForms) || | |
token); | |
} | |
TenseInflector.prototype.izeAbiguous = function (token) { | |
if(this.ambiguous.indexOf(token.toLowerCase()) > -1) | |
return token.toLowerCase(); | |
return false; | |
} | |
TenseInflector.prototype.pluralize = function (token) { | |
return this.ize(token, this.pluralForms, this.customPluralForms); | |
}; | |
TenseInflector.prototype.singularize = function(token) { | |
return this.ize(token, this.singularForms, this.customSingularForms); | |
}; | |
var uppercaseify = function(token) { | |
return token.toUpperCase(); | |
} | |
var capitalize = function(token) { | |
return token[0].toUpperCase() + token.slice(1); | |
} | |
var lowercaseify = function(token) { | |
return token.toLowerCase(); | |
} | |
TenseInflector.prototype.restoreCase = function(token) { | |
if (token[0] === token[0].toUpperCase()) { | |
if (token[1] && token[1] === token[1].toLowerCase()) { | |
return capitalize; | |
} else { | |
return uppercaseify; | |
} | |
} else { | |
return lowercaseify; | |
} | |
} | |
TenseInflector.prototype.izeRegulars = function(token, formSet) { | |
token = token.toLowerCase(); | |
if(formSet.irregularForms.hasOwnProperty(token) && formSet.irregularForms[token]) | |
return formSet.irregularForms[token]; | |
return false; | |
} | |
TenseInflector.prototype.addForm = function(singularTable, pluralTable, singular, plural) { | |
singular = singular.toLowerCase(); | |
plural = plural.toLowerCase(); | |
pluralTable[singular] = plural; | |
singularTable[plural] = singular; | |
}; | |
TenseInflector.prototype.addIrregular = function(singular, plural) { | |
this.addForm(this.singularForms.irregularForms, this.pluralForms.irregularForms, singular, plural); | |
}; | |
TenseInflector.prototype.izeRegExps = function(token, forms) { | |
var i, form; | |
for(i = 0; i < forms.length; i++) { | |
form = forms[i]; | |
if(token.match(form[0])) | |
return token.replace(form[0], form[1]); | |
} | |
return false; | |
} | |
module.exports = TenseInflector; | |
},{}],17:[function(require,module,exports){ | |
/* | |
Copyright (c) 2013, Kenneth Koch | |
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. | |
*/ | |
/** | |
* The english normalizer will create a string in which all contractions are expanded to their | |
* full meaning (i.e. "we'll" becomes "we will"). | |
* | |
* It currently works off a conversion table and falls back to a set of rules. | |
* Since it is applied first, the conversion table provides an "override" for the rules. | |
**/ | |
var replacer = require('../util/utils').replacer; | |
var conversionTable = { | |
"can't":"can not", | |
"won't":"will not", | |
"couldn't've":"could not have", | |
"i'm":"I am", | |
"how'd":"how did" | |
}; | |
var rules = [ | |
{ regex: /([azAZ]*)n\'[tT]/g, output: "$1 not" }, | |
{ regex: /([azAZ]*)\'[sS]/g, output: "$1 is" }, | |
{ regex: /([azAZ]*)\'[lL][lL]/g, output: "$1 will" }, | |
{ regex: /([azAZ]*)\'[rR][eE]/g, output: "$1 are" }, | |
{ regex: /([azAZ]*)\'[vV][eE]/g, output: "$1 have" }, | |
{ regex: /([azAZ]*)\'[dD]/g, output: "$1 would" } | |
]; | |
// Accepts a list of tokens to expand. | |
var normalize_tokens = function(tokens) { | |
if(typeof tokens === "string") { | |
tokens = [tokens]; | |
} | |
var results = []; | |
var rule_count = rules.length; | |
var num_tokens = tokens.length; | |
var i, token, r, rule; | |
for (i = 0; i < num_tokens; i++) { | |
token = tokens[i]; | |
// Check the conversion table | |
if (conversionTable[token.toLowerCase()]) { | |
results = results.concat(conversionTable[token.toLowerCase()].split(/\W+/)); | |
} | |
// Apply the rules | |
else { | |
var matched = false; | |
for ( r = 0; r < rule_count; r++) { | |
rule = rules[r]; | |
if (token.match(rule.regex)) { | |
results = results.concat(token.replace(rule.regex, rule.output).split(/\W+/)); | |
matched = true; | |
break; | |
} | |
} | |
if (!matched) { | |
results.push(token); | |
} | |
} | |
} | |
return results; | |
}; | |
// export the relevant stuff. | |
exports.normalize_tokens = normalize_tokens; | |
},{"../util/utils":42}],18:[function(require,module,exports){ | |
/* | |
Copyright (c) 2012, Alexy Maslennikov | |
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. | |
*/ | |
/** | |
* Script to remove diacritics. Original source was taken from | |
* http://lehelk.com/2011/05/06/script-to-remove-diacritics/ | |
*/ | |
var diacriticsRemovalMap = [ | |
{'base':'A', 'letters':/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g}, | |
{'base':'AA','letters':/[\uA732]/g}, | |
{'base':'AE','letters':/[\u00C6\u01FC\u01E2]/g}, | |
{'base':'AO','letters':/[\uA734]/g}, | |
{'base':'AU','letters':/[\uA736]/g}, | |
{'base':'AV','letters':/[\uA738\uA73A]/g}, | |
{'base':'AY','letters':/[\uA73C]/g}, | |
{'base':'B', 'letters':/[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g}, | |
{'base':'C', 'letters':/[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g}, | |
{'base':'D', 'letters':/[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g}, | |
{'base':'DZ','letters':/[\u01F1\u01C4]/g}, | |
{'base':'Dz','letters':/[\u01F2\u01C5]/g}, | |
{'base':'E', 'letters':/[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g}, | |
{'base':'F', 'letters':/[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g}, | |
{'base':'G', 'letters':/[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g}, | |
{'base':'H', 'letters':/[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g}, | |
{'base':'I', 'letters':/[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g}, | |
{'base':'J', 'letters':/[\u004A\u24BF\uFF2A\u0134\u0248]/g}, | |
{'base':'K', 'letters':/[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g}, | |
{'base':'L', 'letters':/[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g}, | |
{'base':'LJ','letters':/[\u01C7]/g}, | |
{'base':'Lj','letters':/[\u01C8]/g}, | |
{'base':'M', 'letters':/[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g}, | |
{'base':'N', 'letters':/[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g}, | |
{'base':'NJ','letters':/[\u01CA]/g}, | |
{'base':'Nj','letters':/[\u01CB]/g}, | |
{'base':'O', 'letters':/[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g}, | |
{'base':'OE','letters':/[\u0152]/g}, | |
{'base':'OI','letters':/[\u01A2]/g}, | |
{'base':'OO','letters':/[\uA74E]/g}, | |
{'base':'OU','letters':/[\u0222]/g}, | |
{'base':'P', 'letters':/[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g}, | |
{'base':'Q', 'letters':/[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g}, | |
{'base':'R', 'letters':/[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g}, | |
{'base':'S', 'letters':/[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g}, | |
{'base':'T', 'letters':/[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g}, | |
{'base':'TZ','letters':/[\uA728]/g}, | |
{'base':'U', 'letters':/[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g}, | |
{'base':'V', 'letters':/[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g}, | |
{'base':'VY','letters':/[\uA760]/g}, | |
{'base':'W', 'letters':/[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g}, | |
{'base':'X', 'letters':/[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g}, | |
{'base':'Y', 'letters':/[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g}, | |
{'base':'Z', 'letters':/[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g}, | |
{'base':'a', 'letters':/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g}, | |
{'base':'aa','letters':/[\uA733]/g}, | |
{'base':'ae','letters':/[\u00E6\u01FD\u01E3]/g}, | |
{'base':'ao','letters':/[\uA735]/g}, | |
{'base':'au','letters':/[\uA737]/g}, | |
{'base':'av','letters':/[\uA739\uA73B]/g}, | |
{'base':'ay','letters':/[\uA73D]/g}, | |
{'base':'b', 'letters':/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g}, | |
{'base':'c', 'letters':/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g}, | |
{'base':'d', 'letters':/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g}, | |
{'base':'dz','letters':/[\u01F3\u01C6]/g}, | |
{'base':'e', 'letters':/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g}, | |
{'base':'f', 'letters':/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g}, | |
{'base':'g', 'letters':/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g}, | |
{'base':'h', 'letters':/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g}, | |
{'base':'hv','letters':/[\u0195]/g}, | |
{'base':'i', 'letters':/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g}, | |
{'base':'j', 'letters':/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g}, | |
{'base':'k', 'letters':/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g}, | |
{'base':'l', 'letters':/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g}, | |
{'base':'lj','letters':/[\u01C9]/g}, | |
{'base':'m', 'letters':/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g}, | |
{'base':'n', 'letters':/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g}, | |
{'base':'nj','letters':/[\u01CC]/g}, | |
{'base':'o', 'letters':/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g}, | |
{'base':'oe','letters':/[\u0153]/g}, | |
{'base':'oi','letters':/[\u01A3]/g}, | |
{'base':'ou','letters':/[\u0223]/g}, | |
{'base':'oo','letters':/[\uA74F]/g}, | |
{'base':'p','letters':/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g}, | |
{'base':'q','letters':/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g}, | |
{'base':'r','letters':/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g}, | |
{'base':'s','letters':/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g}, | |
{'base':'t','letters':/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g}, | |
{'base':'tz','letters':/[\uA729]/g}, | |
{'base':'u','letters':/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g}, | |
{'base':'v','letters':/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g}, | |
{'base':'vy','letters':/[\uA761]/g}, | |
{'base':'w','letters':/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g}, | |
{'base':'x','letters':/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g}, | |
{'base':'y','letters':/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g}, | |
{'base':'z','letters':/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g} | |
]; | |
module.exports = function(str) { | |
var rules = diacriticsRemovalMap; | |
for (var i = 0; i < rules.length; i++) { | |
str = str.replace(rules[i].letters, rules[i].base); | |
} | |
return str; | |
}; | |
},{}],19:[function(require,module,exports){ | |
/* | |
Copyright (c) 2012, Alexy Maslenninkov | |
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. | |
*/ | |
/* | |
* Daitch-Mokotoff Soundex Coding | |
* | |
* The Daitch-Mokotoff Soundex System was created by Randy Daitch and Gary | |
* Mokotoff of the Jewish Genealogical Society because they concluded the system | |
* developed by Robert Russell in 1918, and in use today by the U.S. National | |
* Archives and Records Administration (NARA) does not apply well to many Slavic | |
* and Yiddish surnames. It also includes refinements that are independent of | |
* ethnic considerations. | |
* | |
* The rules for converting surnames into D-M Code numbers are listed below. | |
* They are followed by the coding chart. | |
* | |
* 1. Names are coded to six digits, each digit representing a sound listed in | |
* the coding chart (below). | |
* | |
* 2. When a name lacks enough coded sounds for six digits, use zeros to fill to | |
* six digits. GOLDEN which has only four coded sounds [G-L-D-N] is coded as | |
* 583600. | |
* | |
* 3. The letters A, E, I, O, U, J, and Y are always coded at the beginning of a | |
* name as in Alpert 087930. In any other situation, they are ignored except | |
* when two of them form a pair and the pair comes before a vowel, as in Breuer | |
* 791900 but not Freud. | |
* | |
* 4. The letter H is coded at the beginning of a name, as in Haber 579000, or | |
* preceding a vowel, as in Manheim 665600, otherwise it is not coded. | |
* | |
* 5. When adjacent sounds can combine to form a larger sound, they are given | |
* the code number of the larger sound. Mintz which is not coded MIN-T-Z but | |
* MIN-TZ 664000. | |
* | |
* 6. When adjacent letters have the same code number, they are coded as one | |
* sound, as in TOPF, which is not coded TO-P-F 377000 but TO-PF 370000. | |
* Exceptions to this rule are the letter combinations MN and NM, whose letters | |
* are coded separately, as in Kleinman, which is coded 586660 not 586600. | |
* | |
* 7. When a surname consists or more than one word, it is coded as if one word, | |
* such as Ben Aron which is treated as Benaron. | |
* | |
* 8. Several letter and letter combinations pose the problem that they may | |
* sound in one of two ways. The letter and letter combinations CH, CK, C, J, | |
* and RS are assigned two possible code numbers. | |
* | |
* For more info, see http://www.jewishgen.org/InfoFiles/soundex.html | |
*/ | |
/** | |
* D-M transformation table in the form of finite-state machine. | |
* Every element of the table having member with zero index represents | |
* legal FSM state; every non-zero key is the transition rule. | |
* | |
* Every legal state comprises tree values chosen according to the position | |
* of the letter combination in the word: | |
* 0: start of a word; | |
* 1: before a vowel; | |
* 2: any other situation. | |
*/ | |
var codes = { | |
A: { | |
0: [0, -1, -1], | |
I: [[0, 1, -1]], | |
J: [[0, 1, -1]], | |
Y: [[0, 1, -1]], | |
U: [[0, 7, -1]]}, | |
B: [[7, 7, 7]], | |
C: { | |
0: [5, 5, 5], | |
Z: {0: [4, 4, 4], S: [[4, 4, 4]]}, | |
S: {0: [4, 4, 4], Z: [[4, 4, 4]]}, | |
K: [[5, 5, 5], [45, 45, 45]], | |
H: {0: [5, 5, 5], S: [[5, 54, 54]]}}, | |
D: { | |
0: [3, 3, 3], | |
T: [[3, 3, 3]], | |
Z: {0: [4, 4, 4], H: [[4, 4, 4]], S: [[4, 4, 4]]}, | |
S: {0: [4, 4, 4], H: [[4, 4, 4]], Z: [[4, 4, 4]]}, | |
R: {S: [[4, 4, 4]], Z: [[4, 4, 4]]}}, | |
E: { | |
0: [0, -1, -1], | |
I: [[0, 1, -1]], | |
J: [[0, 1, -1]], | |
Y: [[0, 1, -1]], | |
U: [[1, 1, -1]], | |
W: [[1, 1, -1]]}, | |
F: { | |
0: [7, 7, 7], | |
B: [[7, 7, 7]]}, | |
G: [[5, 5, 5]], | |
H: [[5, 5, -1]], | |
I: { | |
0: [0, -1, -1], | |
A: [[1, -1, -1]], | |
E: [[1, -1, -1]], | |
O: [[1, -1, -1]], | |
U: [[1, -1, -1]]}, | |
J: [[4, 4, 4]], | |
K: { | |
0: [5, 5, 5], | |
H: [[5, 5, 5]], | |
S: [[5, 54, 54]]}, | |
L: [[8, 8, 8]], | |
M: { | |
0: [6, 6, 6], | |
N: [[66, 66, 66]]}, | |
N: { | |
0: [6, 6, 6], | |
M: [[66, 66, 66]]}, | |
O: { | |
0: [0, -1, -1], | |
I: [[0, 1, -1]], | |
J: [[0, 1, -1]], | |
Y: [[0, 1, -1]]}, | |
P: { | |
0: [7, 7, 7], | |
F: [[7, 7, 7]], | |
H: [[7, 7, 7]]}, | |
Q: [[5, 5, 5]], | |
R: { | |
0: [9, 9, 9], | |
Z: [[94, 94, 94], [94, 94, 94]], | |
S: [[94, 94, 94], [94, 94, 94]]}, | |
S: { | |
0: [4, 4, 4], | |
Z: {0: [4, 4, 4], T: [[2, 43, 43]], C: {Z: [[2, 4, 4]], S: [[2, 4, 4]]}, D: [[2, 43, 43]]}, | |
D: [[2, 43, 43]], | |
T: {0: [2, 43, 43], R: {Z: [[2, 4, 4]], S: [[2, 4, 4]]}, C: {H: [[2, 4, 4]]}, S: {H: [[2, 4, 4]], C: {H: [[2, 4, 4]]}}}, | |
C: {0: [2, 4, 4], H: {0: [4, 4, 4], T: {0: [2, 43, 43], S: {C: {H: [[2, 4, 4]]}, H: [[2, 4, 4]]}, C: {H: [[2, 4, 4]]}}, D: [[2, 43, 43]]}}, | |
H: {0: [4, 4, 4], T: {0: [2, 43, 43], C: {H: [[2, 4, 4]]}, S: {H: [[2, 4, 4]]}}, C: {H: [[2, 4, 4]]}, D: [[2, 43, 43]]}}, | |
T: { | |
0: [3, 3, 3], | |
C: {0: [4, 4, 4], H: [[4, 4, 4]]}, | |
Z: {0: [4, 4, 4], S: [[4, 4, 4]]}, | |
S: {0: [4, 4, 4], Z: [[4, 4, 4]], H: [[4, 4, 4]], C: {H: [[4, 4, 4]]}}, | |
T: {S: {0: [4, 4, 4], Z: [[4, 4, 4]], C: {H: [[4, 4, 4]]}}, C: {H: [[4, 4, 4]]}, Z: [[4, 4, 4]]}, | |
H: [[3, 3, 3]], | |
R: {Z: [[4, 4, 4]], S: [[4, 4, 4]]}}, | |
U: { | |
0: [0, -1, -1], | |
E: [[0, -1, -1]], | |
I: [[0, 1, -1]], | |
J: [[0, 1, -1]], | |
Y: [[0, 1, -1]]}, | |
V: [[7, 7, 7]], | |
W: [[7, 7, 7]], | |
X: [[5, 54, 54]], | |
Y: [[1, -1, -1]], | |
Z: { | |
0: [4, 4, 4], | |
D: {0: [2, 43, 43], Z: {0: [2, 4, 4], H: [[2, 4, 4]]}}, | |
H: {0: [4, 4, 4], D: {0: [2, 43, 43], Z: {H: [[2, 4, 4]]}}}, | |
S: {0: [4, 4, 4], H: [[4, 4, 4]], C: {H: [[4, 4, 4]]}}} | |
}; | |
function process(word, codeLength) { | |
codeLength = codeLength || 6; | |
word = word.toUpperCase(); | |
var output = ''; | |
var pos = 0, lastCode = -1; | |
while (pos < word.length) { | |
var substr = word.slice(pos); | |
var rules = findRules(substr); | |
var code; | |
if (pos == 0) { | |
// at the beginning of the word | |
code = rules.mapping[0]; | |
} else if (substr[rules.length] && findRules(substr[rules.length]).mapping[0] == 0) { | |
// before a vowel | |
code = rules.mapping[1]; | |
} else { | |
// any other situation | |
code = rules.mapping[2]; | |
} | |
if ((code != -1) && (code != lastCode)) output += code; | |
lastCode = code; | |
pos += rules.length; | |
} | |
return normalizeLength(output, codeLength); | |
} | |
function findRules(str) { | |
var state = codes[str[0]]; | |
var legalState = state || [[-1,-1,-1]], | |
charsInvolved = 1; | |
for (var offs = 1; offs < str.length; offs++) { | |
if (!state || !state[str[offs]]) break; | |
state = state[str[offs]]; | |
if (state[0]) { | |
legalState = state; | |
charsInvolved = offs + 1; | |
} | |
} | |
return { | |
length: charsInvolved, | |
mapping: legalState[0] | |
}; | |
} | |
/** | |
* Pad right with zeroes or cut excess symbols to fit length | |
*/ | |
function normalizeLength(token, length) { | |
length = length || 6; | |
if (token.length < length) { | |
token += (new Array(length - token.length + 1)).join('0'); | |
} | |
return token.slice(0, length); | |
} | |
var Phonetic = require('./phonetic'); | |
var soundex = new Phonetic(); | |
soundex.process = process; | |
module.exports = soundex; | |
},{"./phonetic":22}],20:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var Phonetic = require('./phonetic'); | |
var DoubleMetaphone = new Phonetic(); | |
module.exports = DoubleMetaphone; | |
function isVowel(c) { | |
return c && c.match(/[aeiouy]/i); | |
} | |
function truncate(string, length) { | |
if(string.length >= length) | |
string = string.substring(0, length); | |
return string; | |
} | |
function process(token, maxLength) { | |
token = token.toUpperCase(); | |
var primary = '', secondary = ''; | |
var pos = 0; | |
maxLength == maxLength || 32; | |
function subMatch(startOffset, stopOffset, terms) { | |
return subMatchAbsolute(pos + startOffset, pos + stopOffset, terms); | |
} | |
function subMatchAbsolute(startOffset, stopOffset, terms) { | |
return terms.indexOf(token.substring(startOffset, stopOffset)) > -1; | |
} | |
function addSecondary(primaryAppendage, secondaryAppendage) { | |
primary += primaryAppendage; | |
secondary += secondaryAppendage; | |
} | |
function add(primaryAppendage) { | |
addSecondary(primaryAppendage, primaryAppendage); | |
} | |
function addCompressedDouble(c, encoded) { | |
if(token[pos + 1] == c) | |
pos++; | |
add(encoded || c); | |
} | |
function handleC() { | |
if(pos >= 1 && !isVowel(token[pos - 2]) | |
&& token[pos - 1] == 'A' && token[pos + 1] == 'H' | |
&& token[pos + 2] != 'I' | |
|| subMatch(-2, 4, ['BACHER', 'MACHER'])) { | |
add('K'); | |
pos++; | |
} else if(pos == 0 && token.substring(1, 6) == 'EASAR') { | |
add('S'); | |
add('S'); | |
add('R'); | |
pos += 6; | |
} else if(token.substring(pos + 1, pos + 4) == 'HIA') { | |
add('K'); | |
pos++; | |
} else if(token[pos + 1] == 'H') { | |
if(pos > 0 && token.substring(pos + 2, pos + 4) == 'AE') { | |
addSecondary('K', 'X'); | |
pos++; | |
} else if(pos == 0 | |
&& (subMatch(1, 6, ['HARAC', 'HARIS']) | |
|| subMatch(1, 4, ['HOR', 'HUM', 'HIA', 'HEM'])) | |
&& token.substring(pos + 1, pos + 5) != 'HORE') { | |
add('K'); | |
pos++; | |
} else { | |
if((subMatchAbsolute(0, 3, ['VAN', 'VON']) || token.substring(0, 3) == 'SCH') | |
|| subMatch(-2, 4, ['ORCHES', 'ARCHIT', 'ORCHID']) | |
|| subMatch(2, 3, ['T', 'S']) | |
|| ((subMatch(-1, 0, ['A', 'O', 'U', 'E']) || pos == 0) | |
&& subMatch(2, 3, ['B', 'F', 'H', 'L', 'M', 'N', 'R', 'V', 'W']))) { | |
add('K'); | |
} else if(pos > 0) { | |
if(token.substring(0, 2) == 'MC') { | |
add('K'); | |
} else { | |
addSecondary('X', 'K'); | |
} | |
} else { | |
add('X'); | |
} | |
pos++; | |
} | |
} else if(token.substring(pos, pos + 2) == 'CZ' | |
&& token.substring(pos - 2, pos + 1) != 'WICZ') { | |
addSecondary('S', 'X'); | |
pos++; | |
} else if(token.substring(pos, pos + 3) == 'CIA') { | |
add('X'); | |
pos += 2; | |
} else if(token[pos + 1] == 'C' && pos != 1 && token[0] != 'M') { | |
if(['I', 'E', 'H'].indexOf(token[pos + 2]) > -1 | |
&& token.substring(pos + 2, pos + 4) != 'HU') { | |
if(pos == 1 && token[pos - 1] == 'A' | |
|| subMatch(-1, 4, ['UCCEE', 'UCCES'])) { | |
add('KS'); | |
} else { | |
add('X'); | |
} | |
pos +=2; | |
} else { | |
add('K'); | |
pos++; | |
} | |
} else if(['K', 'G', 'Q'].indexOf(token[pos + 1]) > -1) { | |
add('K'); | |
pos++; | |
} else if(['E', 'I', 'Y'].indexOf(token[pos + 1]) > -1) { | |
if(subMatch(1, 3, ['IA', 'IE', 'IO'])) { | |
addSecondary('S', 'X'); | |
} else { | |
add('S'); | |
} | |
pos++; | |
} else { | |
add('K'); | |
if(token[pos + 1] == ' ' && ['C', 'Q', 'G'].indexOf(token[pos + 2])) { | |
pos += 2; | |
} else if(['C', 'K', 'Q'].indexOf(token[pos + 1]) > -1 | |
&& !subMatch(1, 3, ['CE', 'CI'])) { | |
pos++; | |
} | |
} | |
} | |
function handleD() { | |
if(token[pos + 1] == 'G') { | |
if(['I', 'E', 'Y'].indexOf(token[pos + 2]) > -1) { | |
add('J'); | |
pos += 2; | |
} else { | |
add('TK'); | |
pos++; | |
} | |
} else if(token[pos + 1] == 'T') { | |
add('T'); | |
pos++; | |
} else | |
addCompressedDouble('D', 'T'); | |
} | |
function handleG() { | |
if(token[pos + 1] == 'H') { | |
if(pos > 0 && !isVowel(token[pos - 1])) { | |
add('K'); | |
pos++; | |
} else if(pos == 0) { | |
if(token[pos + 2] == 'I') { | |
add('J'); | |
} else { | |
add('K'); | |
} | |
pos++; | |
} else if(pos > 1 | |
&& (['B', 'H', 'D'].indexOf(token[pos - 2]) > -1 | |
|| ['B', 'H', 'D'].indexOf(token[pos - 3]) > -1 | |
|| ['B', 'H'].indexOf(token[pos - 4]) > -1)) { | |
pos++; | |
} else { | |
if(pos > 2 | |
&& token[pos - 1] == 'U' | |
&& ['C', 'G', 'L', 'R', 'T'].indexOf(token[pos - 3]) > -1) { | |
add('F'); | |
} else if(token[pos - 1] != 'I') { | |
add('K'); | |
} | |
pos++; | |
} | |
} else if(token[pos + 1] == 'N') { | |
if(pos == 1 && startsWithVowel && !slavoGermanic) { | |
addSecondary('KN', 'N'); | |
} else { | |
if(token.substring(pos + 2, pos + 4) != 'EY' | |
&& (token[pos + 1] != 'Y' | |
&& !slavoGermanic)) { | |
addSecondary('N', 'KN'); | |
} else | |
add('KN'); | |
} | |
pos++; | |
} else if(token.substring(pos + 1, pos + 3) == 'LI' && !slavoGermanic) { | |
addSecondary('KL', 'L'); | |
pos++; | |
} else if(pos == 0 && (token[pos + 1] == 'Y' | |
|| subMatch(1, 3, ['ES', 'EP', 'EB', 'EL', 'EY', 'IB', 'IL', 'IN', 'IE', 'EI', 'ER']))) { | |
addSecondary('K', 'J') | |
} else { | |
addCompressedDouble('G', 'K'); | |
} | |
} | |
function handleH() { | |
// keep if starts a word or is surrounded by vowels | |
if((pos == 0 || isVowel(token[pos - 1])) && isVowel(token[pos + 1])) { | |
add('H'); | |
pos++; | |
} | |
} | |
function handleJ() { | |
var jose = (token.substring(pos + 1, pos + 4) == 'OSE'); | |
if(san || jose) { | |
if((pos == 0 && token[pos + 4] == ' ') | |
|| san) { | |
add('H'); | |
} else | |
add('J', 'H'); | |
} else { | |
if(pos == 0/* && !jose*/) { | |
addSecondary('J', 'A'); | |
} else if(isVowel(token[pos - 1]) && !slavoGermanic | |
&& (token[pos + 1] == 'A' || token[pos + 1] == 'O')) { | |
addSecondary('J', 'H'); | |
} else if(pos == token.length - 1) { | |
addSecondary('J', ' '); | |
} else | |
addCompressedDouble('J'); | |
} | |
} | |
function handleL() { | |
if(token[pos + 1] == 'L') { | |
if(pos == token.length - 3 && ( | |
subMatch(-1, 3, ['ILLO', 'ILLA', 'ALLE']) || ( | |
token.substring(pos - 1, pos + 3) == 'ALLE' && | |
(subMatch(-2, -1, ['AS', 'OS']) > -1 || | |
['A', 'O'].indexOf(token[token.length - 1]) > -1)))) { | |
addSecondary('L', ''); | |
pos++; | |
return; | |
} | |
pos++; | |
} | |
add('L'); | |
} | |
function handleM() { | |
addCompressedDouble('M'); | |
if(token[pos - 1] == 'U' && token[pos + 1] == 'B' && | |
((pos == token.length - 2 || token.substring(pos + 2, pos + 4) == 'ER'))) | |
pos++; | |
} | |
function handleP() { | |
if(token[pos + 1] == 'H') { | |
add('F'); | |
pos++; | |
} else { | |
addCompressedDouble('P'); | |
if(token[pos + 1] == 'B') | |
pos++; | |
} | |
} | |
function handleR() { | |
if(pos == token.length - 1 && !slavoGermanic | |
&& token.substring(pos - 2, pos) == 'IE' | |
&& !subMatch(-4, -3, ['ME', 'MA'])) { | |
addSecondary('', 'R'); | |
} else | |
addCompressedDouble('R'); | |
} | |
function handleS() { | |
if(pos == 0 && token.substring(0, 5) == 'SUGAR') { | |
addSecondary('X', 'S'); | |
} else if(token[pos + 1] == 'H') { | |
if(subMatch(2, 5, ['EIM', 'OEK', 'OLM', 'OLZ'])) { | |
add('S'); | |
} else { | |
add('X'); | |
} | |
pos++; | |
} else if(subMatch(1, 3, ['IO', 'IA'])) { | |
if(slavoGermanic) { | |
add('S'); | |
} else { | |
addSecondary('S', 'X'); | |
} | |
pos++; | |
} else if((pos == 0 && ['M', 'N', 'L', 'W'].indexOf(token[pos + 1]) > -1) | |
|| token[pos + 1] == 'Z') { | |
addSecondary('S', 'X'); | |
if(token[pos + 1] == 'Z') | |
pos++; | |
} else if(token.substring(pos, pos + 2) == 'SC') { | |
if(token[pos + 2] == 'H') { | |
if(subMatch(3, 5, ['ER', 'EN'])) { | |
addSecondary('X', 'SK'); | |
} else if(subMatch(3, 5, ['OO', 'UY', 'ED', 'EM'])) { | |
add('SK'); | |
} else if(pos == 0 && !isVowel(token[3]) && token[3] != 'W') { | |
addSecondary('X', 'S'); | |
} else { | |
add('X'); | |
} | |
} else if(['I', 'E', 'Y'].indexOf(token[pos + 2]) > -1) { | |
add('S'); | |
} else { | |
add('SK'); | |
} | |
pos += 2; | |
} else if(pos == token.length - 1 | |
&& subMatch(-2, 0, ['AI', 'OI'])) { | |
addSecondary('', 'S'); | |
} else if(token[pos + 1] != 'L' && ( | |
token[pos - 1] != 'A' && token[pos - 1] != 'I')) { | |
addCompressedDouble('S'); | |
if(token[pos + 1] == 'Z') | |
pos++; | |
} | |
} | |
function handleT() { | |
if(token.substring(pos + 1, pos + 4) == 'ION') { | |
add('XN'); | |
pos += 3; | |
} else if(subMatch(1, 3, ['IA', 'CH'])) { | |
add('X'); | |
pos += 2; | |
} else if(token[pos + 1] == 'H' | |
|| token.substring(1, 2) == 'TH') { | |
if(subMatch(2, 4, ['OM', 'AM']) | |
|| ['VAN ', 'VON '].indexOf(token.substring(0, 4)) > -1 | |
|| token.substring(0, 3) == 'SCH') { | |
add('T'); | |
} else | |
addSecondary('0', 'T'); | |
pos++; | |
} else { | |
addCompressedDouble('T'); | |
if(token[pos + 1] == 'D') | |
pos++; | |
} | |
} | |
function handleX() { | |
if(pos == 0) { | |
add('S'); | |
} else if(!(pos == token.length - 1 | |
&& (['IAU', 'EAU', 'IEU'].indexOf(token.substring(pos - 3, pos)) > -1 | |
|| ['AU', 'OU'].indexOf(token.substring(pos - 2, pos)) > -1))) { | |
add('KS'); | |
} | |
} | |
function handleW() { | |
if(pos == 0) { | |
if(token[1] == 'H') { | |
add('A'); | |
} else if (isVowel(token[1])) { | |
addSecondary('A', 'F'); | |
} | |
} else if((pos == token.length - 1 && isVowel(token[pos - 1]) | |
|| subMatch(-1, 4, ['EWSKI', 'EWSKY', 'OWSKI', 'OWSKY']) | |
|| token.substring(0, 3) == 'SCH')) { | |
addSecondary('', 'F'); | |
pos++; | |
} else if(['ICZ', 'ITZ'].indexOf(token.substring(pos + 1, pos + 4)) > -1) { | |
addSecondary('TS', 'FX'); | |
pos += 3; | |
} | |
} | |
function handleZ() { | |
if(token[pos + 1] == 'H') { | |
add('J'); | |
pos++; | |
} else if(subMatch(1, 3, ['ZO', 'ZI', 'ZA']) | |
|| (slavoGermanic && pos > 0 && token[pos - 1] != 'T')) { | |
addSecondary('S', 'TS'); | |
pos++; | |
} else | |
addCompressedDouble('Z', 'S'); | |
} | |
var san = (token.substring(0, 3) == 'SAN'); | |
var startsWithVowel = isVowel(token[0]); | |
var slavoGermanic = token.match(/(W|K|CZ|WITZ)/); | |
if(subMatch(0, 2, ['GN', 'KN', 'PN', 'WR', 'PS'])) { | |
pos++; | |
} | |
while(pos < token.length) { | |
switch(token[pos]) { | |
case 'A': case 'E': case 'I': case 'O': case 'U': case 'Y': | |
case 'Ê': case 'É': case 'É': case'À': | |
if(pos == 0) | |
add('A'); | |
break; | |
case 'B': | |
addCompressedDouble('B', 'P'); | |
break; | |
case 'C': | |
handleC(); | |
break; | |
case 'Ç': | |
add("S"); | |
break; | |
case 'D': | |
handleD(); | |
break; | |
case 'F': case 'K': case 'N': | |
addCompressedDouble(token[pos]); | |
break; | |
case 'G': | |
handleG(); | |
break; | |
case 'H': | |
handleH(); | |
break; | |
case 'J': | |
handleJ(); | |
break; | |
case 'L': | |
handleL(); | |
break; | |
case 'M': | |
handleM(); | |
break; | |
case 'Ñ': | |
add('N'); | |
break; | |
case 'P': | |
handleP(); | |
break; | |
case 'Q': | |
addCompressedDouble('Q', 'K'); | |
break; | |
case 'R': | |
handleR(); | |
break; | |
case 'S': | |
handleS(); | |
break; | |
case 'T': | |
handleT(); | |
break; | |
case 'V': | |
addCompressedDouble('V', 'F'); | |
break; | |
case 'W': | |
handleW(); | |
break; | |
case 'X': | |
handleX(); | |
break; | |
case 'Z': | |
handleZ(); | |
break; | |
} | |
if(primary.length >= maxLength && secondary.length >= maxLength) { | |
break; | |
} | |
pos++; | |
} | |
return [truncate(primary, maxLength), truncate(secondary, maxLength)]; | |
} | |
function compare(stringA, stringB) { | |
var encodingsA = process(stringA), | |
encodingsB = process(stringB); | |
return encodingsA[0] == encodingsB[0] || | |
encodingsA[1] == encodingsB[1]; | |
}; | |
DoubleMetaphone.compare = compare | |
DoubleMetaphone.process = process; | |
DoubleMetaphone.isVowel = isVowel; | |
},{"./phonetic":22}],21:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var Phonetic = require('./phonetic'); | |
function dedup(token) { | |
return token.replace(/([^c])\1/g, '$1'); | |
} | |
function dropInitialLetters(token) { | |
if(token.match(/^(kn|gn|pn|ae|wr)/)) | |
return token.substr(1, token.length - 1); | |
return token; | |
} | |
function dropBafterMAtEnd(token) { | |
return token.replace(/mb$/, 'm'); | |
} | |
function cTransform(token) { | |
token = token.replace(/([^s]|^)(c)(h)/g, '$1x$3').trim(); | |
token = token.replace(/cia/g, 'xia'); | |
token = token.replace(/c(i|e|y)/g, 's$1'); | |
token = token.replace(/c/g, 'k'); | |
return token; | |
} | |
function dTransform(token) { | |
token = token.replace(/d(ge|gy|gi)/g, 'j$1'); | |
token = token.replace(/d/g, 't'); | |
return token; | |
} | |
function dropG(token) { | |
token = token.replace(/gh(^$|[^aeiou])/g, 'h$1'); | |
token = token.replace(/g(n|ned)$/g, '$1'); | |
return token; | |
} | |
function transformG(token) { | |
token = token.replace(/gh/g, 'f'); | |
token = token.replace(/([^g]|^)(g)(i|e|y)/g, '$1j$3'); | |
token = token.replace(/gg/g, 'g'); | |
token = token.replace(/g/g, 'k'); | |
return token; | |
} | |
function dropH(token) { | |
return token.replace(/([aeiou])h([^aeiou]|$)/g, '$1$2'); | |
} | |
function transformCK(token) { | |
return token.replace(/ck/g, 'k'); | |
} | |
function transformPH(token) { | |
return token.replace(/ph/g, 'f'); | |
} | |
function transformQ(token) { | |
return token.replace(/q/g, 'k'); | |
} | |
function transformS(token) { | |
return token.replace(/s(h|io|ia)/g, 'x$1'); | |
} | |
function transformT(token) { | |
token = token.replace(/t(ia|io)/g, 'x$1'); | |
token = token.replace(/th/, '0'); | |
return token; | |
} | |
function dropT(token) { | |
return token.replace(/tch/g, 'ch'); | |
} | |
function transformV(token) { | |
return token.replace(/v/g, 'f'); | |
} | |
function transformWH(token) { | |
return token.replace(/^wh/, 'w'); | |
} | |
function dropW(token) { | |
return token.replace(/w([^aeiou]|$)/g, '$1'); | |
} | |
function transformX(token) { | |
token = token.replace(/^x/, 's'); | |
token = token.replace(/x/g, 'ks'); | |
return token; | |
} | |
function dropY(token) { | |
return token.replace(/y([^aeiou]|$)/g, '$1'); | |
} | |
function transformZ(token) { | |
return token.replace(/z/, 's'); | |
} | |
function dropVowels(token) { | |
return token.charAt(0) + token.substr(1, token.length).replace(/[aeiou]/g, ''); | |
} | |
var Metaphone = new Phonetic(); | |
module.exports = Metaphone; | |
Metaphone.process = function(token, maxLength) { | |
maxLength == maxLength || 32; | |
token = token.toLowerCase(); | |
token = dedup(token); | |
token = dropInitialLetters(token); | |
token = dropBafterMAtEnd(token); | |
token = transformCK(token); | |
token = cTransform(token); | |
token = dTransform(token); | |
token = dropG(token); | |
token = transformG(token); | |
token = dropH(token); | |
token = transformPH(token); | |
token = transformQ(token); | |
token = transformS(token); | |
token = transformX(token); | |
token = transformT(token); | |
token = dropT(token); | |
token = transformV(token); | |
token = transformWH(token); | |
token = dropW(token); | |
token = dropY(token); | |
token = transformZ(token); | |
token = dropVowels(token); | |
token.toUpperCase(); | |
if(token.length >= maxLength) | |
token = token.substring(0, maxLength); | |
return token.toUpperCase(); | |
}; | |
// expose functions for testing | |
Metaphone.dedup = dedup; | |
Metaphone.dropInitialLetters = dropInitialLetters; | |
Metaphone.dropBafterMAtEnd = dropBafterMAtEnd; | |
Metaphone.cTransform = cTransform; | |
Metaphone.dTransform = dTransform; | |
Metaphone.dropG = dropG; | |
Metaphone.transformG = transformG; | |
Metaphone.dropH = dropH; | |
Metaphone.transformCK = transformCK; | |
Metaphone.transformPH = transformPH; | |
Metaphone.transformQ = transformQ; | |
Metaphone.transformS = transformS; | |
Metaphone.transformT = transformT; | |
Metaphone.dropT = dropT; | |
Metaphone.transformV = transformV; | |
Metaphone.transformWH = transformWH; | |
Metaphone.dropW = dropW; | |
Metaphone.transformX = transformX; | |
Metaphone.dropY = dropY; | |
Metaphone.transformZ = transformZ; | |
Metaphone.dropVowels = dropVowels; | |
},{"./phonetic":22}],22:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var stopwords = require('../util/stopwords'); | |
var Tokenizer = require('../tokenizers/aggressive_tokenizer'), | |
tokenizer = new Tokenizer(); | |
module.exports = function() { | |
this.compare = function(stringA, stringB) { | |
return this.process(stringA) == this.process(stringB); | |
}; | |
this.attach = function() { | |
var phonetic = this; | |
String.prototype.soundsLike = function(compareTo) { | |
return phonetic.compare(this, compareTo); | |
} | |
String.prototype.phonetics = function() { | |
return phonetic.process(this); | |
} | |
String.prototype.tokenizeAndPhoneticize = function(keepStops) { | |
var phoneticizedTokens = []; | |
tokenizer.tokenize(this).forEach(function(token) { | |
if(keepStops || stopwords.words.indexOf(token) < 0) | |
phoneticizedTokens.push(token.phonetics()); | |
}); | |
return phoneticizedTokens; | |
} | |
}; | |
}; | |
},{"../tokenizers/aggressive_tokenizer":29,"../util/stopwords":40}],23:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var Phonetic = require('./phonetic'); | |
function transformLipps(token) { | |
return token.replace(/[bfpv]/g, '1'); | |
} | |
function transformThroats(token) { | |
return token.replace(/[cgjkqsxz]/g, '2'); | |
} | |
function transformToungue(token) { | |
return token.replace(/[dt]/g, '3'); | |
} | |
function transformL(token) { | |
return token.replace(/l/g, '4'); | |
} | |
function transformHum(token) { | |
return token.replace(/[mn]/g, '5'); | |
} | |
function transformR(token) { | |
return token.replace(/r/g, '6'); | |
} | |
function condense(token) { | |
return token.replace(/(\d)?\1+/g, '$1'); | |
} | |
function padRight0(token) { | |
if(token.length < 4) | |
return token + Array(4 - token.length).join('0'); | |
else | |
return token; | |
} | |
function transform(token) { | |
return transformLipps(transformThroats( | |
transformToungue(transformL(transformHum(transformR(token)))))); | |
} | |
var SoundEx = new Phonetic(); | |
module.exports = SoundEx; | |
SoundEx.process = function(token, maxLength) { | |
token = token.toLowerCase(); | |
var transformed = condense(transform(token.substr(1, token.length - 1))); // anything that isn't a digit goes | |
// deal with duplicate INITIAL consonant SOUNDS | |
transformed = transformed.replace(new RegExp("^" + transform(token.charAt(0))), ''); | |
return token.charAt(0).toUpperCase() + padRight0(transformed.replace(/\D/g, '')).substr(0, (maxLength && maxLength - 1) || 3); | |
}; | |
// export for tests; | |
SoundEx.transformLipps = transformLipps; | |
SoundEx.transformThroats = transformThroats; | |
SoundEx.transformToungue = transformToungue; | |
SoundEx.transformL = transformL; | |
SoundEx.transformHum = transformHum; | |
SoundEx.transformR = transformR; | |
SoundEx.condense = condense; | |
SoundEx.padRight0 = padRight0; | |
},{"./phonetic":22}],24:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
exports.rules = { | |
"a": [ | |
{ | |
"continuation": false, | |
"intact": true, | |
"pattern": "ia", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": true, | |
"pattern": "a", | |
"size": "1" | |
} | |
], | |
"b": [ | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "bb", | |
"size": "1" | |
} | |
], | |
"c": [ | |
{ | |
"appendage": "s", | |
"continuation": false, | |
"intact": false, | |
"pattern": "ytic", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ic", | |
"size": "2" | |
}, | |
{ | |
"appendage": "t", | |
"continuation": true, | |
"intact": false, | |
"pattern": "nc", | |
"size": "1" | |
} | |
], | |
"d": [ | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "dd", | |
"size": "1" | |
}, | |
{ | |
"appendage": "y", | |
"continuation": true, | |
"intact": false, | |
"pattern": "ied", | |
"size": "3" | |
}, | |
{ | |
"appendage": "ss", | |
"continuation": false, | |
"intact": false, | |
"pattern": "ceed", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "eed", | |
"size": "1" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ed", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "hood", | |
"size": "4" | |
} | |
], | |
"e": [ | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "e", | |
"size": "1" | |
} | |
], | |
"f": [ | |
{ | |
"appendage": "v", | |
"continuation": false, | |
"intact": false, | |
"pattern": "lief", | |
"size": "1" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "if", | |
"size": "2" | |
} | |
], | |
"g": [ | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ing", | |
"size": "3" | |
}, | |
{ | |
"appendage": "y", | |
"continuation": false, | |
"intact": false, | |
"pattern": "iag", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ag", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "gg", | |
"size": "1" | |
} | |
], | |
"h": [ | |
{ | |
"continuation": false, | |
"intact": true, | |
"pattern": "th", | |
"size": "2" | |
}, | |
{ | |
"appendage": "ct", | |
"continuation": false, | |
"intact": false, | |
"pattern": "guish", | |
"size": "5" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ish", | |
"size": "3" | |
} | |
], | |
"i": [ | |
{ | |
"continuation": false, | |
"intact": true, | |
"pattern": "i", | |
"size": "1" | |
}, | |
{ | |
"appendage": "y", | |
"continuation": true, | |
"intact": false, | |
"pattern": "i", | |
"size": "1" | |
} | |
], | |
"j": [ | |
{ | |
"appendage": "d", | |
"continuation": false, | |
"intact": false, | |
"pattern": "ij", | |
"size": "1" | |
}, | |
{ | |
"appendage": "s", | |
"continuation": false, | |
"intact": false, | |
"pattern": "fuj", | |
"size": "1" | |
}, | |
{ | |
"appendage": "d", | |
"continuation": false, | |
"intact": false, | |
"pattern": "uj", | |
"size": "1" | |
}, | |
{ | |
"appendage": "d", | |
"continuation": false, | |
"intact": false, | |
"pattern": "oj", | |
"size": "1" | |
}, | |
{ | |
"appendage": "r", | |
"continuation": false, | |
"intact": false, | |
"pattern": "hej", | |
"size": "1" | |
}, | |
{ | |
"appendage": "t", | |
"continuation": false, | |
"intact": false, | |
"pattern": "verj", | |
"size": "1" | |
}, | |
{ | |
"appendage": "t", | |
"continuation": false, | |
"intact": false, | |
"pattern": "misj", | |
"size": "2" | |
}, | |
{ | |
"appendage": "d", | |
"continuation": false, | |
"intact": false, | |
"pattern": "nj", | |
"size": "1" | |
}, | |
{ | |
"appendage": "s", | |
"continuation": false, | |
"intact": false, | |
"pattern": "j", | |
"size": "1" | |
} | |
], | |
"l": [ | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ifiabl", | |
"size": "6" | |
}, | |
{ | |
"appendage": "y", | |
"continuation": false, | |
"intact": false, | |
"pattern": "iabl", | |
"size": "4" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "abl", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ibl", | |
"size": "3" | |
}, | |
{ | |
"appendage": "l", | |
"continuation": true, | |
"intact": false, | |
"pattern": "bil", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "cl", | |
"size": "1" | |
}, | |
{ | |
"appendage": "y", | |
"continuation": false, | |
"intact": false, | |
"pattern": "iful", | |
"size": "4" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ful", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ul", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ial", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ual", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "al", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ll", | |
"size": "1" | |
} | |
], | |
"m": [ | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ium", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": true, | |
"pattern": "um", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ism", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "mm", | |
"size": "1" | |
} | |
], | |
"n": [ | |
{ | |
"appendage": "j", | |
"continuation": true, | |
"intact": false, | |
"pattern": "sion", | |
"size": "4" | |
}, | |
{ | |
"appendage": "ct", | |
"continuation": false, | |
"intact": false, | |
"pattern": "xion", | |
"size": "4" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ion", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ian", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "an", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "een", | |
"size": "0" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "en", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "nn", | |
"size": "1" | |
} | |
], | |
"p": [ | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ship", | |
"size": "4" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "pp", | |
"size": "1" | |
} | |
], | |
"r": [ | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "er", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ear", | |
"size": "0" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ar", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "or", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ur", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "rr", | |
"size": "1" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "tr", | |
"size": "1" | |
}, | |
{ | |
"appendage": "y", | |
"continuation": true, | |
"intact": false, | |
"pattern": "ier", | |
"size": "3" | |
} | |
], | |
"s": [ | |
{ | |
"appendage": "y", | |
"continuation": true, | |
"intact": false, | |
"pattern": "ies", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "sis", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "is", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ness", | |
"size": "4" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ss", | |
"size": "0" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ous", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": true, | |
"pattern": "us", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": true, | |
"pattern": "s", | |
"size": "1" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "s", | |
"size": "0" | |
} | |
], | |
"t": [ | |
{ | |
"appendage": "y", | |
"continuation": false, | |
"intact": false, | |
"pattern": "plicat", | |
"size": "4" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "at", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ment", | |
"size": "4" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ent", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ant", | |
"size": "3" | |
}, | |
{ | |
"appendage": "b", | |
"continuation": false, | |
"intact": false, | |
"pattern": "ript", | |
"size": "2" | |
}, | |
{ | |
"appendage": "b", | |
"continuation": false, | |
"intact": false, | |
"pattern": "orpt", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "duct", | |
"size": "1" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "sumpt", | |
"size": "2" | |
}, | |
{ | |
"appendage": "iv", | |
"continuation": false, | |
"intact": false, | |
"pattern": "cept", | |
"size": "2" | |
}, | |
{ | |
"appendage": "v", | |
"continuation": false, | |
"intact": false, | |
"pattern": "olut", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "sist", | |
"size": "0" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ist", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "tt", | |
"size": "1" | |
} | |
], | |
"u": [ | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "iqu", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ogu", | |
"size": "1" | |
} | |
], | |
"v": [ | |
{ | |
"appendage": "j", | |
"continuation": true, | |
"intact": false, | |
"pattern": "siv", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "eiv", | |
"size": "0" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "iv", | |
"size": "2" | |
} | |
], | |
"y": [ | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "bly", | |
"size": "1" | |
}, | |
{ | |
"appendage": "y", | |
"continuation": true, | |
"intact": false, | |
"pattern": "ily", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ply", | |
"size": "0" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ly", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ogy", | |
"size": "1" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "phy", | |
"size": "1" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "omy", | |
"size": "1" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "opy", | |
"size": "1" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ity", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ety", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "lty", | |
"size": "2" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "istry", | |
"size": "5" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ary", | |
"size": "3" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "ory", | |
"size": "3" | |
}, | |
{ | |
"continuation": false, | |
"intact": false, | |
"pattern": "ify", | |
"size": "3" | |
}, | |
{ | |
"appendage": "t", | |
"continuation": true, | |
"intact": false, | |
"pattern": "ncy", | |
"size": "2" | |
}, | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "acy", | |
"size": "3" | |
} | |
], | |
"z": [ | |
{ | |
"continuation": true, | |
"intact": false, | |
"pattern": "iz", | |
"size": "2" | |
}, | |
{ | |
"appendage": "s", | |
"continuation": false, | |
"intact": false, | |
"pattern": "yz", | |
"size": "1" | |
} | |
] | |
}; | |
},{}],25:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var Stemmer = require('./stemmer'); | |
var ruleTable = require('./lancaster_rules').rules; | |
function acceptable(candidate) { | |
if (candidate.match(/^[aeiou]/)) | |
return (candidate.length > 1); | |
else | |
return (candidate.length > 2 && candidate.match(/[aeiouy]/)); | |
} | |
// take a token, look up the applicatble rule section and attempt some stemming! | |
function applyRuleSection(token, intact) { | |
var section = token.substr( - 1); | |
var rules = ruleTable[section]; | |
if (rules) { | |
for (var i = 0; i < rules.length; i++) { | |
if ((intact || !rules[i].intact) | |
// only apply intact rules to intact tokens | |
&& token.substr(0 - rules[i].pattern.length) == rules[i].pattern) { | |
// hack off only as much as the rule indicates | |
var result = token.substr(0, token.length - rules[i].size); | |
// if the rules wants us to apply an appendage do so | |
if (rules[i].appendage) | |
result += rules[i].appendage; | |
if (acceptable(result)) { | |
token = result; | |
// see what the rules wants to do next | |
if (rules[i].continuation) { | |
// this rule thinks there still might be stem left. keep at it. | |
// since we've applied a change we'll pass false in for intact | |
return applyRuleSection(result, false); | |
} else { | |
// the rule thinks we're done stemming. drop out. | |
return result; | |
} | |
} | |
} | |
} | |
} | |
return token; | |
} | |
var LancasterStemmer = new Stemmer(); | |
module.exports = LancasterStemmer; | |
LancasterStemmer.stem = function(token) { | |
return applyRuleSection(token.toLowerCase(), true); | |
} | |
},{"./lancaster_rules":24,"./stemmer":27}],26:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var Stemmer = require('./stemmer'); | |
// denote groups of consecutive consonants with a C and consecutive vowels | |
// with a V. | |
function categorizeGroups(token) { | |
return token.replace(/[^aeiouy]+y/g, 'CV').replace(/[aeiou]+/g, 'V').replace(/[^V]+/g, 'C'); | |
} | |
// denote single consonants with a C and single vowels with a V | |
function categorizeChars(token) { | |
return token.replace(/[^aeiouy]y/g, 'CV').replace(/[aeiou]/g, 'V').replace(/[^V]/g, 'C'); | |
} | |
// calculate the "measure" M of a word. M is the count of VC sequences dropping | |
// an initial C if it exists and a trailing V if it exists. | |
function measure(token) { | |
if(!token) | |
return -1; | |
return categorizeGroups(token).replace(/^C/, '').replace(/V$/, '').length / 2; | |
} | |
// determine if a token end with a double consonant i.e. happ | |
function endsWithDoublCons(token) { | |
return token.match(/([^aeiou])\1$/); | |
} | |
// replace a pattern in a word. if a replacement occurs an optional callback | |
// can be called to post-process the result. if no match is made NULL is | |
// returned. | |
function attemptReplace(token, pattern, replacement, callback) { | |
var result = null; | |
if((typeof pattern == 'string') && token.substr(0 - pattern.length) == pattern) | |
result = token.replace(new RegExp(pattern + '$'), replacement); | |
else if((pattern instanceof RegExp) && token.match(pattern)) | |
result = token.replace(pattern, replacement); | |
if(result && callback) | |
return callback(result); | |
else | |
return result; | |
} | |
// attempt to replace a list of patterns/replacements on a token for a minimum | |
// measure M. | |
function attemptReplacePatterns(token, replacements, measureThreshold) { | |
var replacement = token; | |
for(var i = 0; i < replacements.length; i++) { | |
if(measureThreshold == null || measure(attemptReplace(token, replacements[i][0], replacements[i][1])) > measureThreshold) { | |
replacement = attemptReplace(replacement, replacements[i][0], replacements[i][2]) || replacement; | |
} | |
} | |
return replacement; | |
} | |
// replace a list of patterns/replacements on a word. if no match is made return | |
// the original token. | |
function replacePatterns(token, replacements, measureThreshold) { | |
return attemptReplacePatterns(token, replacements, measureThreshold) || token; | |
} | |
// TODO: this should replace all of the messy replacement stuff above | |
function replaceRegex(token, regex, includeParts, minimumMeasure) { | |
var parts; | |
var result = ''; | |
if(regex.test(token)) { | |
parts = regex.exec(token); | |
includeParts.forEach(function(i) { | |
result += parts[i]; | |
}); | |
} | |
if(measure(result) > minimumMeasure) { | |
return result; | |
} | |
return null; | |
} | |
// step 1a as defined for the porter stemmer algorithm. | |
function step1a(token) { | |
if(token.match(/(ss|i)es$/)) { | |
return token.replace(/(ss|i)es$/, '$1'); | |
} | |
if(token.substr(-1) == 's' && token.substr(-2, 1) != 's' && token.length > 2) { | |
return token.replace(/s?$/, ''); | |
} | |
return token; | |
} | |
// step 1b as defined for the porter stemmer algorithm. | |
function step1b(token) { | |
if(token.substr(-3) == 'eed') { | |
if(measure(token.substr(0, token.length - 3)) > 0) | |
return token.replace(/eed$/, 'ee'); | |
} else { | |
var result = attemptReplace(token, /(ed|ing)$/, '', function(token) { | |
if(categorizeGroups(token).indexOf('V') >= 0) { | |
result = attemptReplacePatterns(token, [['at', '', 'ate'], ['bl', '', 'ble'], ['iz', '', 'ize']]); | |
if(result != token) { | |
return result; | |
} else { | |
if(endsWithDoublCons(token) && token.match(/[^lsz]$/)) { | |
return token.replace(/([^aeiou])\1$/, '$1'); | |
} | |
if(measure(token) == 1 && categorizeChars(token).substr(-3) == 'CVC' && token.match(/[^wxy]$/)) { | |
return token + 'e'; | |
} | |
} | |
return token; | |
} | |
return null; | |
}); | |
if(result) { | |
return result; | |
} | |
} | |
return token; | |
} | |
// step 1c as defined for the porter stemmer algorithm. | |
function step1c(token) { | |
var categorizedGroups = categorizeGroups(token); | |
if(token.substr(-1) == 'y' && categorizedGroups.substr(0, categorizedGroups.length - 1).indexOf('V') > -1) { | |
return token.replace(/y$/, 'i'); | |
} | |
return token; | |
} | |
// step 2 as defined for the porter stemmer algorithm. | |
function step2(token) { | |
token = replacePatterns(token, [['ational', '', 'ate'], ['tional', '', 'tion'], ['enci', '', 'ence'], ['anci', '', 'ance'], | |
['izer', '', 'ize'], ['abli', '', 'able'], ['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']], 0); | |
return token; | |
} | |
// step 3 as defined for the porter stemmer algorithm. | |
function step3(token) { | |
return replacePatterns(token, [['icate', '', 'ic'], ['ative', '', ''], ['alize', '', 'al'], | |
['iciti', '', 'ic'], ['ical', '', 'ic'], ['ful', '', ''], ['ness', '', '']], 0); | |
} | |
// step 4 as defined for the porter stemmer algorithm. | |
function step4(token) { | |
return replaceRegex(token, /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/, [1], 1) || | |
replaceRegex(token, /^(.+?)(s|t)(ion)$/, [1, 2], 1) || | |
token; | |
} | |
// step 5a as defined for the porter stemmer algorithm. | |
function step5a(token) { | |
var m = measure(token.replace(/e$/, '')); | |
if(m > 1 || (m == 1 && !(categorizeChars(token).substr(-4, 3) == 'CVC' && token.match(/[^wxy].$/)))) { | |
token = token.replace(/e$/, ''); | |
} | |
return token; | |
} | |
// step 5b as defined for the porter stemmer algorithm. | |
function step5b(token) { | |
if(measure(token) > 1) { | |
return token.replace(/ll$/, 'l'); | |
} | |
return token; | |
} | |
var PorterStemmer = new Stemmer(); | |
module.exports = PorterStemmer; | |
// perform full stemming algorithm on a single word | |
PorterStemmer.stem = function(token) { | |
if(token.length < 3) return token.toString(); | |
return step5b(step5a(step4(step3(step2(step1c(step1b(step1a(token.toLowerCase())))))))).toString(); | |
}; | |
//exports for tests | |
PorterStemmer.categorizeGroups = categorizeGroups; | |
PorterStemmer.measure = measure; | |
PorterStemmer.step1a = step1a; | |
PorterStemmer.step1b = step1b; | |
PorterStemmer.step1c = step1c; | |
PorterStemmer.step2 = step2; | |
PorterStemmer.step3 = step3; | |
PorterStemmer.step4 = step4; | |
PorterStemmer.step5a = step5a; | |
PorterStemmer.step5b = step5b; | |
},{"./stemmer":27}],27:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var stopwords = require('../util/stopwords'); | |
var Tokenizer = require('../tokenizers/aggressive_tokenizer'); | |
module.exports = function() { | |
var stemmer = this; | |
stemmer.stem = function(token) { | |
return token; | |
}; | |
stemmer.addStopWord = function(stopWord) { | |
stopwords.words.push(stopWord); | |
}; | |
stemmer.addStopWords = function(moreStopWords) { | |
stopwords.words = stopwords.words.concat(moreStopWords); | |
}; | |
stemmer.removeStopWord = function(stopWord) { | |
this.removeStopWords([stopWord]) | |
}; | |
stemmer.removeStopWords = function(moreStopWords) { | |
moreStopWords.forEach(function(stopWord){ | |
var idx = stopwords.words.indexOf(stopWord); | |
if (idx >= 0) { | |
stopwords.words.splice(idx, 1); | |
} | |
}); | |
}; | |
stemmer.tokenizeAndStem = function(text, keepStops) { | |
var stemmedTokens = []; | |
var lowercaseText = text.toLowerCase(); | |
var tokens = new Tokenizer().tokenize(lowercaseText); | |
if (keepStops) { | |
tokens.forEach(function(token) { | |
stemmedTokens.push(stemmer.stem(token)); | |
}); | |
} | |
else { | |
tokens.forEach(function(token) { | |
if (stopwords.words.indexOf(token) == -1) | |
stemmedTokens.push(stemmer.stem(token)); | |
}); | |
} | |
return stemmedTokens; | |
}; | |
stemmer.attach = function() { | |
String.prototype.stem = function() { | |
return stemmer.stem(this); | |
}; | |
String.prototype.tokenizeAndStem = function(keepStops) { | |
return stemmer.tokenizeAndStem(this, keepStops); | |
}; | |
}; | |
} | |
},{"../tokenizers/aggressive_tokenizer":29,"../util/stopwords":40}],28:[function(require,module,exports){ | |
(function (Buffer){(function (){ | |
/* | |
Copyright (c) 2011, Rob Ellis, Chris Umbel | |
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. | |
*/ | |
var _ = require("underscore"), | |
Tokenizer = require('../tokenizers/regexp_tokenizer').WordTokenizer, | |
tokenizer = new Tokenizer(), | |
stopwords = require('../util/stopwords').words, | |
fs = require('fs'); | |
function buildDocument(text, key) { | |
var stopOut; | |
if(typeof text === 'string') { | |
text = tokenizer.tokenize(text.toLowerCase()); | |
stopOut = true; | |
} else if(!_.isArray(text)) { | |
stopOut = false; | |
return text; | |
} | |
return text.reduce(function(document, term) { | |
// next line solves https://github.com/NaturalNode/natural/issues/119 | |
if(typeof document[term] === 'function') document[term] = 0; | |
if(!stopOut || stopwords.indexOf(term) < 0) | |
document[term] = (document[term] ? document[term] + 1 : 1); | |
return document; | |
}, {__key: key}); | |
} | |
function tf(term, document) { | |
return document[term] ? document[term]: 0; | |
} | |
function documentHasTerm(term, document) { | |
return document[term] && document[term] > 0; | |
} | |
function TfIdf(deserialized) { | |
if(deserialized) | |
this.documents = deserialized.documents; | |
else | |
this.documents = []; | |
this._idfCache = {}; | |
} | |
// backwards compatibility for < node 0.10 | |
function isEncoding(encoding) { | |
if (typeof Buffer.isEncoding !== 'undefined') | |
return Buffer.isEncoding(encoding); | |
switch ((encoding + '').toLowerCase()) { | |
case 'hex': | |
case 'utf8': | |
case 'utf-8': | |
case 'ascii': | |
case 'binary': | |
case 'base64': | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
case 'raw': | |
return true; | |
} | |
return false; | |
} | |
module.exports = TfIdf; | |
TfIdf.tf = tf; | |
TfIdf.prototype.idf = function(term, force) { | |
// Lookup the term in the New term-IDF caching, | |
// this will cut search times down exponentially on large document sets. | |
if(this._idfCache[term] && this._idfCache.hasOwnProperty(term) && force !== true) | |
return this._idfCache[term]; | |
var docsWithTerm = this.documents.reduce(function(count, document) { | |
return count + (documentHasTerm(term, document) ? 1 : 0); | |
}, 0); | |
var idf = 1 + Math.log((this.documents.length) / ( 1 + docsWithTerm )); | |
// Add the idf to the term cache and return it | |
this._idfCache[term] = idf; | |
return idf; | |
}; | |
// If restoreCache is set to true, all terms idf scores currently cached will be recomputed. | |
// Otherwise, the cache will just be wiped clean | |
TfIdf.prototype.addDocument = function(document, key, restoreCache) { | |
this.documents.push(buildDocument(document, key)); | |
// make sure the cache is invalidated when new documents arrive | |
if(restoreCache === true) { | |
for(var term in this._idfCache) { | |
// invoking idf with the force option set will | |
// force a recomputation of the idf, and it will | |
// automatically refresh the cache value. | |
this.idf(term, true); | |
} | |
} else { | |
this._idfCache = {}; | |
} | |
}; | |
// If restoreCache is set to true, all terms idf scores currently cached will be recomputed. | |
// Otherwise, the cache will just be wiped clean | |
TfIdf.prototype.addFileSync = function(path, encoding, key, restoreCache) { | |
if(!encoding) | |
encoding = 'utf8'; | |
if(!isEncoding(encoding)) | |
throw new Error('Invalid encoding: ' + encoding); | |
var document = fs.readFileSync(path, encoding); | |
this.documents.push(buildDocument(document, key)); | |
// make sure the cache is invalidated when new documents arrive | |
if(restoreCache === true) { | |
for(var term in this._idfCache) { | |
// invoking idf with the force option set will | |
// force a recomputation of the idf, and it will | |
// automatically refresh the cache value. | |
this.idf(term, true); | |
} | |
} | |
else { | |
this._idfCache = {}; | |
} | |
}; | |
TfIdf.prototype.tfidf = function(terms, d) { | |
var _this = this; | |
if(!_.isArray(terms)) { | |
terms = tokenizer.tokenize(terms.toString().toLowerCase()); | |
} | |
return terms.reduce(function(value, term) { | |
var idf = _this.idf(term); | |
idf = idf === Infinity ? 0 : idf; | |
return value + (tf(term, _this.documents[d]) * idf); | |
}, 0.0); | |
}; | |
TfIdf.prototype.listTerms = function(d) { | |
var terms = []; | |
var _this = this; | |
for(var term in this.documents[d]) { | |
if (this.documents[d]) { | |
if(term != '__key') { | |
terms.push({"term": term, | |
"tf": tf(term, _this.documents[d]), | |
"idf": _this.idf(term), | |
"tfidf": _this.tfidf(term, d)}); | |
} | |
} | |
} | |
return terms.sort(function(x, y) { return y.tfidf - x.tfidf; }); | |
}; | |
TfIdf.prototype.tfidfs = function(terms, callback) { | |
var tfidfs = new Array(this.documents.length); | |
for(var i = 0; i < this.documents.length; i++) { | |
tfidfs[i] = this.tfidf(terms, i); | |
if(callback) | |
callback(i, tfidfs[i], this.documents[i].__key); | |
} | |
return tfidfs; | |
}; | |
// Define a tokenizer other than the default "WordTokenizer" | |
TfIdf.prototype.setTokenizer = function(t) { | |
if(!_.isFunction(t.tokenize)) | |
throw new Error('Expected a valid Tokenizer'); | |
tokenizer = t; | |
}; | |
// Define a stopwords other than the default | |
TfIdf.prototype.setStopwords = function(customStopwords) { | |
if (!Array.isArray(customStopwords)) | |
return false; | |
customStopwords.forEach(stopword => { | |
if ((typeof stopword) != 'string') | |
return false; | |
}); | |
stopwords = customStopwords; | |
return true; | |
} | |
}).call(this)}).call(this,require("buffer").Buffer) | |
},{"../tokenizers/regexp_tokenizer":31,"../util/stopwords":40,"buffer":48,"fs":44,"underscore":43}],29:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var Tokenizer = require('./tokenizer'), | |
util = require('util'); | |
var AggressiveTokenizer = function() { | |
Tokenizer.call(this); | |
}; | |
util.inherits(AggressiveTokenizer, Tokenizer); | |
module.exports = AggressiveTokenizer; | |
AggressiveTokenizer.prototype.tokenize = function(text) { | |
// break a string up into an array of tokens by anything non-word | |
// underscore is considered to be non word character | |
return this.trim(text.split(/[\W|_]+/)); | |
}; | |
},{"./tokenizer":33,"util":68}],30:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
/*** | |
* RegExp definitions for tokenizing text in a specific language based | |
* on its alphabet. Each language is keyed by the two-letter code per | |
* ISO 639-1, and defines a RegExp that excludes alphabetic characters. | |
*/ | |
var matchers = { | |
fi: /[^A-Za-zÅåÄäÖö]/ | |
}; | |
module.exports = matchers; | |
},{}],31:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Rob Ellis, Chris Umbel | |
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. | |
*/ | |
var Tokenizer = require('./tokenizer'), | |
util = require("util"), | |
_ = require('underscore'); | |
// Base Class for RegExp Matching | |
var RegexpTokenizer = function(options) { | |
var options = options || {}; | |
this._pattern = options.pattern || this._pattern; | |
this.discardEmpty = options.discardEmpty || true; | |
// Match and split on GAPS not the actual WORDS | |
this._gaps = options.gaps; | |
if (this._gaps === undefined) { | |
this._gaps = true; | |
} | |
}; | |
util.inherits(RegexpTokenizer, Tokenizer); | |
RegexpTokenizer.prototype.tokenize = function(s) { | |
var results; | |
if (this._gaps) { | |
results = s.split(this._pattern); | |
return (this.discardEmpty) ? _.without(results,'',' ') : results; | |
} else { | |
return s.match(this._pattern); | |
} | |
}; | |
exports.RegexpTokenizer = RegexpTokenizer; | |
var orthographyMatchers = require('./orthography_matchers'); | |
/*** | |
* A tokenizer that accepts an alphabet definition. | |
* @param {string} options.language ISO 639-1 for the language, e.g. 'en' | |
*/ | |
var OrthographyTokenizer = function(options) { | |
var pattern = orthographyMatchers[options.language]; | |
if (!pattern) { | |
WordTokenizer.call(this, options); | |
} else { | |
this._pattern = pattern; | |
RegexpTokenizer.call(this, options); | |
} | |
}; | |
util.inherits(OrthographyTokenizer, RegexpTokenizer); | |
exports.OrthographyTokenizer = OrthographyTokenizer; | |
/*** | |
* A tokenizer that divides a text into sequences of alphabetic and | |
* non-alphabetic characters. E.g.: | |
* | |
* >>> WordTokenizer().tokenize("She said 'hello'.") | |
* ['She', 'said', 'hello'] | |
* | |
*/ | |
var WordTokenizer = function(options) { | |
this._pattern = /[^A-Za-zА-Яа-я0-9_]+/; | |
RegexpTokenizer.call(this,options) | |
}; | |
util.inherits(WordTokenizer, RegexpTokenizer); | |
exports.WordTokenizer = WordTokenizer; | |
/*** | |
* A tokenizer that divides a text into sequences of alphabetic and | |
* non-alphabetic characters. E.g.: | |
* | |
* >>> WordPunctTokenizer().tokenize("She said 'hello'.") | |
* ["She","said","'","hello","'","."] | |
* | |
*/ | |
var WordPunctTokenizer = function(options) { | |
this._pattern = new RegExp(/([A-zÀ-ÿ-]+|[0-9._]+|.|!|\?|'|"|:|;|,|-)/i); | |
RegexpTokenizer.call(this,options) | |
}; | |
util.inherits(WordPunctTokenizer, RegexpTokenizer); | |
exports.WordPunctTokenizer = WordPunctTokenizer; | |
},{"./orthography_matchers":30,"./tokenizer":33,"underscore":43,"util":68}],32:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
var Tokenizer = require('./tokenizer'), | |
util = require('util'); | |
const DEBUG = false; | |
var SentenceTokenizer = function() { | |
Tokenizer.call(this); | |
}; | |
util.inherits(SentenceTokenizer, Tokenizer); | |
SentenceTokenizer.prototype.tokenize = function(text) { | |
// break string up in to sentences based on punctation and quotation marks | |
var tokens = text.match(/(?<=\s+|^)[\"\'\‘\“\'\"\[\(\{\⟨](.*?[.?!])(\s[.?!])*[\"\'\’\”\'\"\]\)\}\⟩](?=\s+|$)|(?<=\s+|^)\S(.*?[.?!])(\s[.?!])*(?=\s+|$)/g); | |
DEBUG && console.log("SentenceTokenizer.tokenize: " + tokens); | |
if (!tokens) { | |
return [text]; | |
} | |
// remove unecessary white space | |
tokens = tokens.map(Function.prototype.call, String.prototype.trim); | |
DEBUG && console.log("SentenceTokenizer.tokenize: tokens after removing whitespace " + tokens); | |
return this.trim(tokens); | |
}; | |
module.exports = SentenceTokenizer; | |
},{"./tokenizer":33,"util":68}],33:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
/** | |
* \@todo Use .bind() in Tokenizer.prototype.attach(). | |
*/ | |
var Tokenizer = function() { | |
}; | |
Tokenizer.prototype.trim = function(array) { | |
while (array[array.length - 1] == '') | |
array.pop(); | |
while (array[0] == '') | |
array.shift(); | |
return array; | |
}; | |
// Expose an attach function that will patch String with new methods. | |
Tokenizer.prototype.attach = function() { | |
var self = this; | |
String.prototype.tokenize = function() { | |
return self.tokenize(this); | |
} | |
}; | |
Tokenizer.prototype.tokenize = function() {}; | |
module.exports = Tokenizer; | |
},{}],34:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel, Alex Langberg | |
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. | |
*/ | |
var Tokenizer = require('./tokenizer'), | |
util = require('util'), | |
CaseTokenizer = function() { | |
Tokenizer.call(this); | |
}; | |
util.inherits(CaseTokenizer, Tokenizer); | |
CaseTokenizer.prototype.attach = function() { | |
var self = this; | |
String.prototype.tokenize = function(preserveApostrophe) { | |
return self.tokenize(this, preserveApostrophe); | |
} | |
}; | |
// Idea from Seagull: http://stackoverflow.com/a/26482650 | |
CaseTokenizer.prototype.tokenize = function(text, preserveApostrophe) { | |
var whitelist = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; | |
var lower = text.toLowerCase(); | |
var upper = text.toUpperCase(); | |
var result = ''; | |
var i; | |
for (i = 0; i < lower.length; ++i) { | |
if (lower[i] !== upper[i] || whitelist.indexOf(lower[i]) > -1 || (text[i] === '\'' && preserveApostrophe)) { | |
result += text[i]; | |
} else { | |
result += ' '; | |
} | |
} | |
return this.trim(result.replace(/\s+/g, ' ').split(' ')); | |
}; | |
module.exports = CaseTokenizer; | |
},{"./tokenizer":33,"util":68}],35:[function(require,module,exports){ | |
/* | |
Copyright (c) 2014 Ken Koch | |
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. | |
*/ | |
/** | |
* The basis of the TRIE structure. | |
**/ | |
function Trie(caseSensitive) { | |
this.dictionary = {}; | |
this.$ = false; | |
if(typeof caseSensitive === "undefined") { | |
caseSensitive = true; | |
} | |
this.cs = caseSensitive; | |
} | |
/** | |
* Add a single string to the TRIE, returns true if the word was already in the | |
* trie. | |
**/ | |
Trie.prototype.addString = function(string) { | |
if(this.cs === false) { | |
string = string.toLowerCase(); | |
} | |
// If the string has only one letter, mark this as a word. | |
if(string.length === 0) { | |
var wasWord = this.$; | |
this.$ = true; | |
return wasWord; | |
} | |
// Make sure theres a Trie node in our dictionary | |
var next = this.dictionary[string[0]]; | |
if(!next) { | |
this.dictionary[string[0]] = new Trie(this.cs); | |
next = this.dictionary[string[0]]; | |
} | |
// Continue adding the string | |
return next.addString(string.substring(1)); | |
}; | |
/** | |
* Add multiple strings to the TRIE | |
**/ | |
Trie.prototype.addStrings = function(list) { | |
for(var i in list) { | |
this.addString(list[i]); | |
} | |
}; | |
/** | |
* A function to search the TRIE and return an array of | |
* words which have same prefix <prefix> | |
* for example if we had the following words in our database: | |
* a, ab, bc, cd, abc, abd | |
* and we search the string: a | |
* we will get : | |
* [a, ab, abc, abd] | |
**/ | |
Trie.prototype.keysWithPrefix = function(prefix) { | |
if(this.caseSensitive === false) { | |
prefix = prefix.toLowerCase(); | |
} | |
function isEmpty (object) { | |
for (var key in object) if (object.hasOwnProperty(key)) return false; | |
return true; | |
} | |
function get (node, word) { | |
if(!node) return null; | |
if(word.length == 0) return node; | |
return get(node.dictionary[word[0]], word.substring(1)); | |
} | |
function recurse ( node, stringAgg, resultsAgg) { | |
if (!node) return; | |
// Check if this is a word | |
if (node.$) { | |
resultsAgg.push(stringAgg); | |
} | |
if (isEmpty(node.dictionary)) { | |
return ; | |
} | |
for (var c in node.dictionary) { | |
recurse (node.dictionary[c],stringAgg + c, resultsAgg); | |
} | |
} | |
var results = []; | |
recurse (get(this, prefix), prefix, results); | |
return results; | |
}; | |
/** | |
* A function to search the given string and return true if it lands | |
* on on a word. Essentially testing if the word exists in the database. | |
**/ | |
Trie.prototype.contains = function(string) { | |
if(this.cs === false) { | |
string = string.toLowerCase(); | |
} | |
if(string.length === 0) { | |
return this.$; | |
} | |
// Otherwise, we need to continue searching | |
var firstLetter = string[0]; | |
var next = this.dictionary[firstLetter]; | |
// If we don't have a node, this isn't a word | |
if(!next) { | |
return false; | |
} | |
// Otherwise continue the search at the next node | |
return next.contains(string.substring(1)); | |
} | |
/** | |
* A function to search the TRIE and return an array of words which were encountered along the way. | |
* This will only return words with full prefix matches. | |
* for example if we had the following words in our database: | |
* a, ab, bc, cd, abc | |
* and we searched the string: abcd | |
* we would get only: | |
* [a, ab, abc] | |
**/ | |
Trie.prototype.findMatchesOnPath = function(search) { | |
if(this.cs === false) { | |
search = search.toLowerCase(); | |
} | |
function recurse(node, search, stringAgg, resultsAgg) { | |
// Check if this is a word. | |
if(node.$) { | |
resultsAgg.push(stringAgg); | |
} | |
// Check if the have completed the seearch | |
if(search.length === 0) { | |
return resultsAgg; | |
} | |
// Otherwise, continue searching | |
var next = node.dictionary[search[0]]; | |
if(!next) { | |
return resultsAgg; | |
} | |
return recurse(next, search.substring(1), stringAgg + search[0], resultsAgg); | |
}; | |
return recurse(this, search, "", []); | |
}; | |
/** | |
* Returns the longest match and the remaining part that could not be matched. | |
* inspired by [NLTK containers.trie.find_prefix](http://nltk.googlecode.com/svn-/trunk/doc/api/nltk.containers.Trie-class.html). | |
**/ | |
Trie.prototype.findPrefix = function(search) { | |
if(this.cs === false) { | |
search = search.toLowerCase(); | |
} | |
function recurse(node, search, stringAgg, lastWord) { | |
// Check if this is a word | |
if(node.$) { | |
lastWord = stringAgg; | |
} | |
// Check if we have no more to search | |
if(search.length === 0) { | |
return [lastWord, search]; | |
} | |
// Continue searching | |
var next = node.dictionary[search[0]]; | |
if(!next) { | |
return [lastWord, search]; | |
} | |
return recurse(next, search.substring(1), stringAgg + search[0], lastWord); | |
}; | |
return recurse(this, search, "", null); | |
}; | |
/** | |
* Computes the number of actual nodes from this node to the end. | |
* Note: This involves traversing the entire structure and may not be | |
* good for frequent use. | |
**/ | |
Trie.prototype.getSize = function() { | |
var total = 1; | |
for(var c in this.dictionary) { | |
total += this.dictionary[c].getSize(); | |
} | |
return total; | |
}; | |
/** | |
* EXPORT THE TRIE | |
**/ | |
module.exports = Trie; | |
},{}],36:[function(require,module,exports){ | |
/* | |
Copyright (c) 2014, Lee Wenzhu | |
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. | |
*/ | |
'use strict'; | |
function Bag() { | |
this.dictionary = []; | |
this.nElement = 0; | |
}; | |
Bag.prototype.add = function(element) { | |
this.dictionary.push(element); | |
this.nElement++; | |
return this; | |
}; | |
Bag.prototype.isEmpty = function() { | |
return this.nElement > 0; | |
}; | |
Bag.prototype.contains = function(item) { | |
return this.dictionary.indexOf(item) >= 0; | |
}; | |
/** | |
* unpack the bag , and get all items | |
*/ | |
Bag.prototype.unpack = function() { | |
// return a copy is better than original | |
return this.dictionary.slice(); | |
}; | |
module.exports = Bag; | |
},{}],37:[function(require,module,exports){ | |
/* | |
Copyright (c) 2014, Lee Wenzhu | |
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. | |
*/ | |
'use strict'; | |
var util = require('util'), | |
Bag = require('./bag'); | |
var DirectedEdge = function(start, end, weight) { | |
this.start = start; | |
this.end = end; | |
this.weight = weight; | |
}; | |
DirectedEdge.prototype.weight = function() { | |
return this.weight; | |
}; | |
DirectedEdge.prototype.from = function() { | |
return this.start; | |
}; | |
DirectedEdge.prototype.to = function() { | |
return this.end; | |
}; | |
DirectedEdge.prototype.toString = function() { | |
return util.format('%s -> %s, %s', this.start, this.end, this.weight); | |
}; | |
var EdgeWeightedDigraph = function() { | |
this.edgesNum = 0; | |
this.adj = []; // adjacency list | |
}; | |
/** | |
* the number of vertexs saved. | |
*/ | |
EdgeWeightedDigraph.prototype.v = function() { | |
return this.adj.length; | |
}; | |
/** | |
* the number of edges saved. | |
*/ | |
EdgeWeightedDigraph.prototype.e = function() { | |
return this.edgesNum; | |
}; | |
EdgeWeightedDigraph.prototype.add = function(start, end, weight) { | |
var e = new DirectedEdge(start, end, weight); | |
this.addEdge(e); | |
}; | |
EdgeWeightedDigraph.prototype.addEdge = function(e) { | |
if(!this.adj[e.from()]) { | |
this.adj[e.from()] = new Bag(); | |
} | |
this.adj[e.from()].add(e); | |
this.edgesNum++; | |
}; | |
/** | |
* use callback on all edges from v. | |
*/ | |
EdgeWeightedDigraph.prototype.getAdj = function(v) { | |
if(!this.adj[v]) return []; | |
return this.adj[v].unpack(); | |
}; | |
/** | |
* use callback on all edges. | |
*/ | |
EdgeWeightedDigraph.prototype.edges = function() { | |
var adj = this.adj; | |
var list = new Bag(); | |
for(var i in adj) { | |
adj[i].unpack().forEach(function(item) { | |
list.add(item); | |
}); | |
} | |
return list.unpack(); | |
}; | |
EdgeWeightedDigraph.prototype.toString = function() { | |
var result = []; | |
var list = this.edges(); | |
list.forEach(function(edge) { | |
result.push(edge.toString()); | |
}); | |
return result.join('\n'); | |
}; | |
module.exports = EdgeWeightedDigraph; | |
},{"./bag":36,"util":68}],38:[function(require,module,exports){ | |
/* | |
Copyright (c) 2014, Lee Wenzhu | |
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. | |
*/ | |
'use strict'; | |
var EdgeWeightedDigraph = require('./edge_weighted_digraph'), | |
Topological = require('./topological'); | |
/** | |
* The LongestPathTree represents a data type for solving the | |
* single-source longest paths problem in edge-weighted directed | |
* acyclic graphs (DAGs). The edge weights can be positive, negative, or zero. | |
* This implementation uses a topological-sort based algorithm. | |
* the distTo() and hasPathTo() methods take | |
* constant time and the pathTo() method takes time proportional to the | |
* number of edges in the longest path returned. | |
*/ | |
var LongestPathTree = function(digraph, start) { | |
var _this = this; | |
this.edgeTo = []; | |
this.distTo = []; | |
this.distTo[start] = 0.0; | |
this.start = start; | |
this.top = new Topological(digraph); | |
this.top.order().forEach(function(vertex){ | |
_this.relaxVertex(digraph, vertex, _this); | |
}); | |
}; | |
LongestPathTree.prototype.relaxEdge = function(e) { | |
var distTo = this.distTo, | |
edgeTo = this.edgeTo; | |
var v = e.from(), w = e.to(); | |
if (distTo[w] < distTo[v] + e.weight) { | |
distTo[w] = distTo[v] + e.weight; | |
edgeTo[w] = e; | |
} | |
}; | |
/** | |
* relax a vertex v in the specified digraph g | |
* @param {EdgeWeightedDigraph} the apecified digraph | |
* @param {Vertex} v vertex to be relaxed | |
*/ | |
LongestPathTree.prototype.relaxVertex = function(digraph, vertex, tree) { | |
var distTo = tree.distTo; | |
var edgeTo = tree.edgeTo; | |
digraph.getAdj(vertex).forEach(function(edge){ | |
var w = edge.to(); | |
distTo[w] = distTo[w] || 0.0; | |
distTo[vertex] = distTo[vertex] || 0.0; | |
if (distTo[w] < distTo[vertex] + edge.weight) { | |
// in case of the result of 0.28+0.34 is 0.62000001 | |
distTo[w] = parseFloat((distTo[vertex] + edge.weight).toFixed(2)); | |
edgeTo[w] = edge; | |
} | |
}); | |
}; | |
LongestPathTree.prototype.getDistTo = function(v) { | |
return this.distTo[v]; | |
}; | |
LongestPathTree.prototype.hasPathTo = function(v) { | |
return !!this.distTo[v]; | |
}; | |
LongestPathTree.prototype.pathTo = function(v) { | |
if (!this.hasPathTo(v)) return []; | |
var path = []; | |
var edgeTo = this.edgeTo; | |
for (var e = edgeTo[v]; !!e; e = edgeTo[e.from()]) { | |
path.push(e.to()); | |
} | |
path.push(this.start); | |
return path.reverse(); | |
}; | |
module.exports = LongestPathTree; | |
},{"./edge_weighted_digraph":37,"./topological":41}],39:[function(require,module,exports){ | |
/* | |
Copyright (c) 2014, Lee Wenzhu | |
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. | |
*/ | |
'use strict'; | |
var EdgeWeightedDigraph = require('./edge_weighted_digraph'), | |
Topological = require('./topological'); | |
/** | |
* The ShortestPathTree represents a data type for solving the | |
* single-source shortest paths problem in edge-weighted directed | |
* acyclic graphs (DAGs). The edge weights can be positive, negative, or zero. | |
* This implementation uses a topological-sort based algorithm. | |
* the distTo() and hasPathTo() methods take | |
* constant time and the pathTo() method takes time proportional to the | |
* number of edges in the longest path returned. | |
*/ | |
var ShortestPathTree = function(digraph, start) { | |
var _this = this; | |
this.edgeTo = []; | |
this.distTo = []; | |
this.distTo[start] = 0.0; | |
this.start = start; | |
this.top = new Topological(digraph); | |
this.top.order().forEach(function(vertex){ | |
_this.relaxVertex(digraph, vertex, _this); | |
}); | |
}; | |
ShortestPathTree.prototype.relaxEdge = function(e) { | |
var distTo = this.distTo, | |
edgeTo = this.edgeTo; | |
var v = e.from(), w = e.to(); | |
if (distTo[w] > distTo[v] + e.weight) { | |
distTo[w] = distTo[v] + e.weight; | |
edgeTo[w] = e; | |
} | |
}; | |
/** | |
* relax a vertex v in the specified digraph g | |
* @param {EdgeWeightedDigraph} the apecified digraph | |
* @param {Vertex} v vertex to be relaxed | |
*/ | |
ShortestPathTree.prototype.relaxVertex = function(digraph, vertex, tree) { | |
var distTo = tree.distTo; | |
var edgeTo = tree.edgeTo; | |
digraph.getAdj(vertex).forEach(function(edge){ | |
var w = edge.to(); | |
distTo[w] = /\d/.test(distTo[w]) ? distTo[w] : Number.MAX_VALUE; | |
distTo[vertex] = distTo[vertex] || 0; | |
if (distTo[w] > distTo[vertex] + edge.weight) { | |
// in case of the result of 0.28+0.34 is 0.62000001 | |
distTo[w] = parseFloat((distTo[vertex] + edge.weight).toFixed(2)); | |
edgeTo[w] = edge; | |
} | |
}); | |
}; | |
ShortestPathTree.prototype.getDistTo = function(v) { | |
return this.distTo[v]; | |
}; | |
ShortestPathTree.prototype.hasPathTo = function(v) { | |
var dist = this.distTo[v]; | |
if(v == this.start) return false; | |
return /\d/.test(dist) ? dist != Number.MAX_VALUE : false; | |
}; | |
ShortestPathTree.prototype.pathTo = function(v) { | |
if (!this.hasPathTo(v) || v == this.start) return []; | |
var path = []; | |
var edgeTo = this.edgeTo; | |
for (var e = edgeTo[v]; !!e; e = edgeTo[e.from()]) { | |
path.push(e.to()); | |
} | |
path.push(this.start); | |
return path.reverse(); | |
}; | |
module.exports = ShortestPathTree; | |
},{"./edge_weighted_digraph":37,"./topological":41}],40:[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
// a list of commonly used words that have little meaning and can be excluded | |
// from analysis. | |
var words = [ | |
'about', 'above', 'after', 'again', 'all', 'also', 'am', 'an', 'and', 'another', | |
'any', 'are', 'as', 'at', 'be', 'because', 'been', 'before', 'being', 'below', | |
'between', 'both', 'but', 'by', 'came', 'can', 'cannot', 'come', 'could', 'did', | |
'do', 'does', 'doing', 'during', 'each', 'few', 'for', 'from', 'further', 'get', | |
'got', 'has', 'had', 'he', 'have', 'her', 'here', 'him', 'himself', 'his', 'how', | |
'if', 'in', 'into', 'is', 'it', 'its', 'itself', 'like', 'make', 'many', 'me', | |
'might', 'more', 'most', 'much', 'must', 'my', 'myself', 'never', 'now', 'of', 'on', | |
'only', 'or', 'other', 'our', 'ours', 'ourselves', 'out', 'over', 'own', | |
'said', 'same', 'see', 'should', 'since', 'so', 'some', 'still', 'such', 'take', 'than', | |
'that', 'the', 'their', 'theirs', 'them', 'themselves', 'then', 'there', 'these', 'they', | |
'this', 'those', 'through', 'to', 'too', 'under', 'until', 'up', 'very', 'was', | |
'way', 'we', 'well', 'were', 'what', 'where', 'when', 'which', 'while', 'who', | |
'whom', 'with', 'would', 'why', 'you', 'your', 'yours', 'yourself', | |
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', | |
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '$', '1', | |
'2', '3', '4', '5', '6', '7', '8', '9', '0', '_']; | |
// tell the world about the noise words. | |
exports.words = words; | |
},{}],41:[function(require,module,exports){ | |
/* | |
Copyright (c) 2014, Lee Wenzhu | |
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. | |
*/ | |
'use strict'; | |
/** | |
* a topo sort for a digraph | |
* @param {Digraph} | |
*/ | |
var Topological = function(g) { | |
this.isDag = true; | |
this.sorted = topoSort(uniqueVertexs(g.edges()), g.edges()); | |
}; | |
Topological.prototype.isDAG = function() { | |
return this.isDag; | |
}; | |
/** | |
* get ordered vertexs of digraph | |
*/ | |
Topological.prototype.order = function() { | |
return this.sorted.slice(); | |
}; | |
/** | |
* @param {Array} all vertex in digraph | |
* @param {Object} all edges in the digraph | |
*/ | |
function topoSort(vertexs, edges) { | |
var sorted = []; | |
var cursor = vertexs.length, | |
visited = {}, | |
i = cursor; | |
while (i--) { | |
if (!visited[i]) visit(vertexs[i], i, []); | |
} | |
return sorted.reverse(); | |
function visit(vertex, i, predecessors) { | |
if(predecessors.indexOf(vertex) >= 0) { | |
throw new Error('Cyclic dependency:' + JSON.stringify(vertex)); | |
} | |
if(visited[i]) return; | |
visited[i] = true; | |
var outgoing = edges.filter(function(edge) { | |
return edge.to() === vertex; | |
}); | |
var preds = []; | |
if(outgoing.length > 0) { | |
preds = predecessors.concat(vertex); | |
} | |
var from; | |
outgoing.forEach(function(edge) { | |
from = edge.from(); | |
visit(from, vertexs.indexOf(from), preds); | |
}); | |
sorted[--cursor] = vertex; | |
}; | |
}; | |
function uniqueVertexs(edges) { | |
var vertexs = []; | |
var from, to; | |
edges.forEach(function(edge) { | |
from = edge.from(); | |
to = edge.to(); | |
if (vertexs.indexOf(from) < 0) vertexs.push(from); | |
if (vertexs.indexOf(to) < 0) vertexs.push(to); | |
}); | |
return vertexs; | |
}; | |
module.exports = Topological; | |
},{}],42:[function(require,module,exports){ | |
/* | |
Copyright (c) 2012, Guillaume Marty | |
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. | |
*/ | |
/** | |
* Generate a replacing function given a table of patterns. Inspired by: | |
* http://code.google.com/p/jslibs/wiki/JavascriptTips#String_converter | |
* The order of elements is significant. Longer elements should be listed first. | |
* @see Speed test http://jsperf.com/build-a-regexp-table | |
* | |
* @param {Object.<string, string>} translationTable The translation table of key value. | |
* @return {function(string): string} A translating function. | |
*/ | |
function replacer(translationTable) { | |
/** | |
* An array of translationTable keys. | |
* @type {Array.<string>} | |
*/ | |
var pattern = []; | |
/** | |
* The regular expression doing the replacement job. | |
* @type {RegExp} | |
*/ | |
var regExp; | |
/** | |
* Used to iterate over translationTable. | |
* @type {string} | |
*/ | |
var key; | |
for (key in translationTable) { | |
// Escaping regexp special chars. | |
// @see Speed test for type casting to string http://jsperf.com/string-type-casting/2 | |
// @see http://closure-library.googlecode.com/svn/docs/closure_goog_string_string.js.source.html#line956 | |
key = ('' + key).replace(/([-()\[\]{}+?*.$\^|,:#<!\\\/])/g, '\\$1'). | |
replace(/\x08/g, '\\x08'); | |
pattern.push(key); | |
} | |
regExp = new RegExp(pattern.join('|'), 'g'); | |
/** | |
* @param {string} str Input string. | |
* @return {string} The string replaced. | |
*/ | |
return function(str) { | |
return str.replace(regExp, function(str) { | |
return translationTable[str]; | |
}); | |
}; | |
} | |
/** | |
* Exchanges all keys with their associated values in an object. | |
* | |
* @param {Object.<string, string>} obj An object of strings. | |
* @return {Object.<string, string>} An object of strings. | |
*/ | |
function flip(obj) { | |
var newObj = Object.create(null), | |
key; | |
for (key in obj) { | |
newObj[obj[key]] = key; | |
} | |
return newObj; | |
} | |
/** | |
* Merge several objects. Properties from earlier objects are overwritten by | |
* laters's in case of conflict. | |
* | |
* @param {...Object.<string, string>} var_args One or more objects of strings. | |
* @return {!Object.<string, string>} An object of strings. | |
*/ | |
function merge(var_args) { | |
var args = [].slice.call(arguments), | |
newObj = Object.create(null), | |
id = 0, key; | |
while (args[id]) { | |
for (key in args[id]) { | |
newObj[key] = args[id][key]; | |
} | |
id++; | |
} | |
return newObj; | |
} | |
exports.replacer = replacer; | |
exports.flip = flip; | |
exports.merge = merge; | |
},{}],43:[function(require,module,exports){ | |
(function (global){(function (){ | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | |
typeof define === 'function' && define.amd ? define('underscore', factory) : | |
(global = global || self, (function () { | |
var current = global._; | |
var exports = global._ = factory(); | |
exports.noConflict = function () { global._ = current; return exports; }; | |
}())); | |
}(this, (function () { | |
// Underscore.js 1.12.0 | |
// https://underscorejs.org | |
// (c) 2009-2020 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors | |
// Underscore may be freely distributed under the MIT license. | |
// Current version. | |
var VERSION = '1.12.0'; | |
// Establish the root object, `window` (`self`) in the browser, `global` | |
// on the server, or `this` in some virtual machines. We use `self` | |
// instead of `window` for `WebWorker` support. | |
var root = typeof self == 'object' && self.self === self && self || | |
typeof global == 'object' && global.global === global && global || | |
Function('return this')() || | |
{}; | |
// Save bytes in the minified (but not gzipped) version: | |
var ArrayProto = Array.prototype, ObjProto = Object.prototype; | |
var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null; | |
// Create quick reference variables for speed access to core prototypes. | |
var push = ArrayProto.push, | |
slice = ArrayProto.slice, | |
toString = ObjProto.toString, | |
hasOwnProperty = ObjProto.hasOwnProperty; | |
// Modern feature detection. | |
var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined', | |
supportsDataView = typeof DataView !== 'undefined'; | |
// All **ECMAScript 5+** native function implementations that we hope to use | |
// are declared here. | |
var nativeIsArray = Array.isArray, | |
nativeKeys = Object.keys, | |
nativeCreate = Object.create, | |
nativeIsView = supportsArrayBuffer && ArrayBuffer.isView; | |
// Create references to these builtin functions because we override them. | |
var _isNaN = isNaN, | |
_isFinite = isFinite; | |
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. | |
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); | |
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', | |
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; | |
// The largest integer that can be represented exactly. | |
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; | |
// Some functions take a variable number of arguments, or a few expected | |
// arguments at the beginning and then a variable number of values to operate | |
// on. This helper accumulates all remaining arguments past the function’s | |
// argument length (or an explicit `startIndex`), into an array that becomes | |
// the last argument. Similar to ES6’s "rest parameter". | |
function restArguments(func, startIndex) { | |
startIndex = startIndex == null ? func.length - 1 : +startIndex; | |
return function() { | |
var length = Math.max(arguments.length - startIndex, 0), | |
rest = Array(length), | |
index = 0; | |
for (; index < length; index++) { | |
rest[index] = arguments[index + startIndex]; | |
} | |
switch (startIndex) { | |
case 0: return func.call(this, rest); | |
case 1: return func.call(this, arguments[0], rest); | |
case 2: return func.call(this, arguments[0], arguments[1], rest); | |
} | |
var args = Array(startIndex + 1); | |
for (index = 0; index < startIndex; index++) { | |
args[index] = arguments[index]; | |
} | |
args[startIndex] = rest; | |
return func.apply(this, args); | |
}; | |
} | |
// Is a given variable an object? | |
function isObject(obj) { | |
var type = typeof obj; | |
return type === 'function' || type === 'object' && !!obj; | |
} | |
// Is a given value equal to null? | |
function isNull(obj) { | |
return obj === null; | |
} | |
// Is a given variable undefined? | |
function isUndefined(obj) { | |
return obj === void 0; | |
} | |
// Is a given value a boolean? | |
function isBoolean(obj) { | |
return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; | |
} | |
// Is a given value a DOM element? | |
function isElement(obj) { | |
return !!(obj && obj.nodeType === 1); | |
} | |
// Internal function for creating a `toString`-based type tester. | |
function tagTester(name) { | |
var tag = '[object ' + name + ']'; | |
return function(obj) { | |
return toString.call(obj) === tag; | |
}; | |
} | |
var isString = tagTester('String'); | |
var isNumber = tagTester('Number'); | |
var isDate = tagTester('Date'); | |
var isRegExp = tagTester('RegExp'); | |
var isError = tagTester('Error'); | |
var isSymbol = tagTester('Symbol'); | |
var isArrayBuffer = tagTester('ArrayBuffer'); | |
var isFunction = tagTester('Function'); | |
// Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old | |
// v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236). | |
var nodelist = root.document && root.document.childNodes; | |
if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') { | |
isFunction = function(obj) { | |
return typeof obj == 'function' || false; | |
}; | |
} | |
var isFunction$1 = isFunction; | |
var hasObjectTag = tagTester('Object'); | |
// In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`. | |
// In IE 11, the most common among them, this problem also applies to | |
// `Map`, `WeakMap` and `Set`. | |
var hasStringTagBug = ( | |
supportsDataView && hasObjectTag(new DataView(new ArrayBuffer(8))) | |
), | |
isIE11 = (typeof Map !== 'undefined' && hasObjectTag(new Map)); | |
var isDataView = tagTester('DataView'); | |
// In IE 10 - Edge 13, we need a different heuristic | |
// to determine whether an object is a `DataView`. | |
function ie10IsDataView(obj) { | |
return obj != null && isFunction$1(obj.getInt8) && isArrayBuffer(obj.buffer); | |
} | |
var isDataView$1 = (hasStringTagBug ? ie10IsDataView : isDataView); | |
// Is a given value an array? | |
// Delegates to ECMA5's native `Array.isArray`. | |
var isArray = nativeIsArray || tagTester('Array'); | |
// Internal function to check whether `key` is an own property name of `obj`. | |
function has(obj, key) { | |
return obj != null && hasOwnProperty.call(obj, key); | |
} | |
var isArguments = tagTester('Arguments'); | |
// Define a fallback version of the method in browsers (ahem, IE < 9), where | |
// there isn't any inspectable "Arguments" type. | |
(function() { | |
if (!isArguments(arguments)) { | |
isArguments = function(obj) { | |
return has(obj, 'callee'); | |
}; | |
} | |
}()); | |
var isArguments$1 = isArguments; | |
// Is a given object a finite number? | |
function isFinite$1(obj) { | |
return !isSymbol(obj) && _isFinite(obj) && !isNaN(parseFloat(obj)); | |
} | |
// Is the given value `NaN`? | |
function isNaN$1(obj) { | |
return isNumber(obj) && _isNaN(obj); | |
} | |
// Predicate-generating function. Often useful outside of Underscore. | |
function constant(value) { | |
return function() { | |
return value; | |
}; | |
} | |
// Common internal logic for `isArrayLike` and `isBufferLike`. | |
function createSizePropertyCheck(getSizeProperty) { | |
return function(collection) { | |
var sizeProperty = getSizeProperty(collection); | |
return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= MAX_ARRAY_INDEX; | |
} | |
} | |
// Internal helper to generate a function to obtain property `key` from `obj`. | |
function shallowProperty(key) { | |
return function(obj) { | |
return obj == null ? void 0 : obj[key]; | |
}; | |
} | |
// Internal helper to obtain the `byteLength` property of an object. | |
var getByteLength = shallowProperty('byteLength'); | |
// Internal helper to determine whether we should spend extensive checks against | |
// `ArrayBuffer` et al. | |
var isBufferLike = createSizePropertyCheck(getByteLength); | |
// Is a given value a typed array? | |
var typedArrayPattern = /\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/; | |
function isTypedArray(obj) { | |
// `ArrayBuffer.isView` is the most future-proof, so use it when available. | |
// Otherwise, fall back on the above regular expression. | |
return nativeIsView ? (nativeIsView(obj) && !isDataView$1(obj)) : | |
isBufferLike(obj) && typedArrayPattern.test(toString.call(obj)); | |
} | |
var isTypedArray$1 = supportsArrayBuffer ? isTypedArray : constant(false); | |
// Internal helper to obtain the `length` property of an object. | |
var getLength = shallowProperty('length'); | |
// Internal helper to create a simple lookup structure. | |
// `collectNonEnumProps` used to depend on `_.contains`, but this led to | |
// circular imports. `emulatedSet` is a one-off solution that only works for | |
// arrays of strings. | |
function emulatedSet(keys) { | |
var hash = {}; | |
for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true; | |
return { | |
contains: function(key) { return hash[key]; }, | |
push: function(key) { | |
hash[key] = true; | |
return keys.push(key); | |
} | |
}; | |
} | |
// Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't | |
// be iterated by `for key in ...` and thus missed. Extends `keys` in place if | |
// needed. | |
function collectNonEnumProps(obj, keys) { | |
keys = emulatedSet(keys); | |
var nonEnumIdx = nonEnumerableProps.length; | |
var constructor = obj.constructor; | |
var proto = isFunction$1(constructor) && constructor.prototype || ObjProto; | |
// Constructor is a special case. | |
var prop = 'constructor'; | |
if (has(obj, prop) && !keys.contains(prop)) keys.push(prop); | |
while (nonEnumIdx--) { | |
prop = nonEnumerableProps[nonEnumIdx]; | |
if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) { | |
keys.push(prop); | |
} | |
} | |
} | |
// Retrieve the names of an object's own properties. | |
// Delegates to **ECMAScript 5**'s native `Object.keys`. | |
function keys(obj) { | |
if (!isObject(obj)) return []; | |
if (nativeKeys) return nativeKeys(obj); | |
var keys = []; | |
for (var key in obj) if (has(obj, key)) keys.push(key); | |
// Ahem, IE < 9. | |
if (hasEnumBug) collectNonEnumProps(obj, keys); | |
return keys; | |
} | |
// Is a given array, string, or object empty? | |
// An "empty" object has no enumerable own-properties. | |
function isEmpty(obj) { | |
if (obj == null) return true; | |
// Skip the more expensive `toString`-based type checks if `obj` has no | |
// `.length`. | |
var length = getLength(obj); | |
if (typeof length == 'number' && ( | |
isArray(obj) || isString(obj) || isArguments$1(obj) | |
)) return length === 0; | |
return getLength(keys(obj)) === 0; | |
} | |
// Returns whether an object has a given set of `key:value` pairs. | |
function isMatch(object, attrs) { | |
var _keys = keys(attrs), length = _keys.length; | |
if (object == null) return !length; | |
var obj = Object(object); | |
for (var i = 0; i < length; i++) { | |
var key = _keys[i]; | |
if (attrs[key] !== obj[key] || !(key in obj)) return false; | |
} | |
return true; | |
} | |
// If Underscore is called as a function, it returns a wrapped object that can | |
// be used OO-style. This wrapper holds altered versions of all functions added | |
// through `_.mixin`. Wrapped objects may be chained. | |
function _(obj) { | |
if (obj instanceof _) return obj; | |
if (!(this instanceof _)) return new _(obj); | |
this._wrapped = obj; | |
} | |
_.VERSION = VERSION; | |
// Extracts the result from a wrapped and chained object. | |
_.prototype.value = function() { | |
return this._wrapped; | |
}; | |
// Provide unwrapping proxies for some methods used in engine operations | |
// such as arithmetic and JSON stringification. | |
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value; | |
_.prototype.toString = function() { | |
return String(this._wrapped); | |
}; | |
// Internal function to wrap or shallow-copy an ArrayBuffer, | |
// typed array or DataView to a new view, reusing the buffer. | |
function toBufferView(bufferSource) { | |
return new Uint8Array( | |
bufferSource.buffer || bufferSource, | |
bufferSource.byteOffset || 0, | |
getByteLength(bufferSource) | |
); | |
} | |
// We use this string twice, so give it a name for minification. | |
var tagDataView = '[object DataView]'; | |
// Internal recursive comparison function for `_.isEqual`. | |
function eq(a, b, aStack, bStack) { | |
// Identical objects are equal. `0 === -0`, but they aren't identical. | |
// See the [Harmony `egal` proposal](https://wiki.ecmascript.org/doku.php?id=harmony:egal). | |
if (a === b) return a !== 0 || 1 / a === 1 / b; | |
// `null` or `undefined` only equal to itself (strict comparison). | |
if (a == null || b == null) return false; | |
// `NaN`s are equivalent, but non-reflexive. | |
if (a !== a) return b !== b; | |
// Exhaust primitive checks | |
var type = typeof a; | |
if (type !== 'function' && type !== 'object' && typeof b != 'object') return false; | |
return deepEq(a, b, aStack, bStack); | |
} | |
// Internal recursive comparison function for `_.isEqual`. | |
function deepEq(a, b, aStack, bStack) { | |
// Unwrap any wrapped objects. | |
if (a instanceof _) a = a._wrapped; | |
if (b instanceof _) b = b._wrapped; | |
// Compare `[[Class]]` names. | |
var className = toString.call(a); | |
if (className !== toString.call(b)) return false; | |
// Work around a bug in IE 10 - Edge 13. | |
if (hasStringTagBug && className == '[object Object]' && isDataView$1(a)) { | |
if (!isDataView$1(b)) return false; | |
className = tagDataView; | |
} | |
switch (className) { | |
// These types are compared by value. | |
case '[object RegExp]': | |
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') | |
case '[object String]': | |
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is | |
// equivalent to `new String("5")`. | |
return '' + a === '' + b; | |
case '[object Number]': | |
// `NaN`s are equivalent, but non-reflexive. | |
// Object(NaN) is equivalent to NaN. | |
if (+a !== +a) return +b !== +b; | |
// An `egal` comparison is performed for other numeric values. | |
return +a === 0 ? 1 / +a === 1 / b : +a === +b; | |
case '[object Date]': | |
case '[object Boolean]': | |
// Coerce dates and booleans to numeric primitive values. Dates are compared by their | |
// millisecond representations. Note that invalid dates with millisecond representations | |
// of `NaN` are not equivalent. | |
return +a === +b; | |
case '[object Symbol]': | |
return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b); | |
case '[object ArrayBuffer]': | |
case tagDataView: | |
// Coerce to typed array so we can fall through. | |
return deepEq(toBufferView(a), toBufferView(b), aStack, bStack); | |
} | |
var areArrays = className === '[object Array]'; | |
if (!areArrays && isTypedArray$1(a)) { | |
var byteLength = getByteLength(a); | |
if (byteLength !== getByteLength(b)) return false; | |
if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) return true; | |
areArrays = true; | |
} | |
if (!areArrays) { | |
if (typeof a != 'object' || typeof b != 'object') return false; | |
// Objects with different constructors are not equivalent, but `Object`s or `Array`s | |
// from different frames are. | |
var aCtor = a.constructor, bCtor = b.constructor; | |
if (aCtor !== bCtor && !(isFunction$1(aCtor) && aCtor instanceof aCtor && | |
isFunction$1(bCtor) && bCtor instanceof bCtor) | |
&& ('constructor' in a && 'constructor' in b)) { | |
return false; | |
} | |
} | |
// Assume equality for cyclic structures. The algorithm for detecting cyclic | |
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. | |
// Initializing stack of traversed objects. | |
// It's done here since we only need them for objects and arrays comparison. | |
aStack = aStack || []; | |
bStack = bStack || []; | |
var length = aStack.length; | |
while (length--) { | |
// Linear search. Performance is inversely proportional to the number of | |
// unique nested structures. | |
if (aStack[length] === a) return bStack[length] === b; | |
} | |
// Add the first object to the stack of traversed objects. | |
aStack.push(a); | |
bStack.push(b); | |
// Recursively compare objects and arrays. | |
if (areArrays) { | |
// Compare array lengths to determine if a deep comparison is necessary. | |
length = a.length; | |
if (length !== b.length) return false; | |
// Deep compare the contents, ignoring non-numeric properties. | |
while (length--) { | |
if (!eq(a[length], b[length], aStack, bStack)) return false; | |
} | |
} else { | |
// Deep compare objects. | |
var _keys = keys(a), key; | |
length = _keys.length; | |
// Ensure that both objects contain the same number of properties before comparing deep equality. | |
if (keys(b).length !== length) return false; | |
while (length--) { | |
// Deep compare each member | |
key = _keys[length]; | |
if (!(has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; | |
} | |
} | |
// Remove the first object from the stack of traversed objects. | |
aStack.pop(); | |
bStack.pop(); | |
return true; | |
} | |
// Perform a deep comparison to check if two objects are equal. | |
function isEqual(a, b) { | |
return eq(a, b); | |
} | |
// Retrieve all the enumerable property names of an object. | |
function allKeys(obj) { | |
if (!isObject(obj)) return []; | |
var keys = []; | |
for (var key in obj) keys.push(key); | |
// Ahem, IE < 9. | |
if (hasEnumBug) collectNonEnumProps(obj, keys); | |
return keys; | |
} | |
// Since the regular `Object.prototype.toString` type tests don't work for | |
// some types in IE 11, we use a fingerprinting heuristic instead, based | |
// on the methods. It's not great, but it's the best we got. | |
// The fingerprint method lists are defined below. | |
function ie11fingerprint(methods) { | |
var length = getLength(methods); | |
return function(obj) { | |
if (obj == null) return false; | |
// `Map`, `WeakMap` and `Set` have no enumerable keys. | |
var keys = allKeys(obj); | |
if (getLength(keys)) return false; | |
for (var i = 0; i < length; i++) { | |
if (!isFunction$1(obj[methods[i]])) return false; | |
} | |
// If we are testing against `WeakMap`, we need to ensure that | |
// `obj` doesn't have a `forEach` method in order to distinguish | |
// it from a regular `Map`. | |
return methods !== weakMapMethods || !isFunction$1(obj[forEachName]); | |
}; | |
} | |
// In the interest of compact minification, we write | |
// each string in the fingerprints only once. | |
var forEachName = 'forEach', | |
hasName = 'has', | |
commonInit = ['clear', 'delete'], | |
mapTail = ['get', hasName, 'set']; | |
// `Map`, `WeakMap` and `Set` each have slightly different | |
// combinations of the above sublists. | |
var mapMethods = commonInit.concat(forEachName, mapTail), | |
weakMapMethods = commonInit.concat(mapTail), | |
setMethods = ['add'].concat(commonInit, forEachName, hasName); | |
var isMap = isIE11 ? ie11fingerprint(mapMethods) : tagTester('Map'); | |
var isWeakMap = isIE11 ? ie11fingerprint(weakMapMethods) : tagTester('WeakMap'); | |
var isSet = isIE11 ? ie11fingerprint(setMethods) : tagTester('Set'); | |
var isWeakSet = tagTester('WeakSet'); | |
// Retrieve the values of an object's properties. | |
function values(obj) { | |
var _keys = keys(obj); | |
var length = _keys.length; | |
var values = Array(length); | |
for (var i = 0; i < length; i++) { | |
values[i] = obj[_keys[i]]; | |
} | |
return values; | |
} | |
// Convert an object into a list of `[key, value]` pairs. | |
// The opposite of `_.object` with one argument. | |
function pairs(obj) { | |
var _keys = keys(obj); | |
var length = _keys.length; | |
var pairs = Array(length); | |
for (var i = 0; i < length; i++) { | |
pairs[i] = [_keys[i], obj[_keys[i]]]; | |
} | |
return pairs; | |
} | |
// Invert the keys and values of an object. The values must be serializable. | |
function invert(obj) { | |
var result = {}; | |
var _keys = keys(obj); | |
for (var i = 0, length = _keys.length; i < length; i++) { | |
result[obj[_keys[i]]] = _keys[i]; | |
} | |
return result; | |
} | |
// Return a sorted list of the function names available on the object. | |
function functions(obj) { | |
var names = []; | |
for (var key in obj) { | |
if (isFunction$1(obj[key])) names.push(key); | |
} | |
return names.sort(); | |
} | |
// An internal function for creating assigner functions. | |
function createAssigner(keysFunc, defaults) { | |
return function(obj) { | |
var length = arguments.length; | |
if (defaults) obj = Object(obj); | |
if (length < 2 || obj == null) return obj; | |
for (var index = 1; index < length; index++) { | |
var source = arguments[index], | |
keys = keysFunc(source), | |
l = keys.length; | |
for (var i = 0; i < l; i++) { | |
var key = keys[i]; | |
if (!defaults || obj[key] === void 0) obj[key] = source[key]; | |
} | |
} | |
return obj; | |
}; | |
} | |
// Extend a given object with all the properties in passed-in object(s). | |
var extend = createAssigner(allKeys); | |
// Assigns a given object with all the own properties in the passed-in | |
// object(s). | |
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) | |
var extendOwn = createAssigner(keys); | |
// Fill in a given object with default properties. | |
var defaults = createAssigner(allKeys, true); | |
// Create a naked function reference for surrogate-prototype-swapping. | |
function ctor() { | |
return function(){}; | |
} | |
// An internal function for creating a new object that inherits from another. | |
function baseCreate(prototype) { | |
if (!isObject(prototype)) return {}; | |
if (nativeCreate) return nativeCreate(prototype); | |
var Ctor = ctor(); | |
Ctor.prototype = prototype; | |
var result = new Ctor; | |
Ctor.prototype = null; | |
return result; | |
} | |
// Creates an object that inherits from the given prototype object. | |
// If additional properties are provided then they will be added to the | |
// created object. | |
function create(prototype, props) { | |
var result = baseCreate(prototype); | |
if (props) extendOwn(result, props); | |
return result; | |
} | |
// Create a (shallow-cloned) duplicate of an object. | |
function clone(obj) { | |
if (!isObject(obj)) return obj; | |
return isArray(obj) ? obj.slice() : extend({}, obj); | |
} | |
// Invokes `interceptor` with the `obj` and then returns `obj`. | |
// The primary purpose of this method is to "tap into" a method chain, in | |
// order to perform operations on intermediate results within the chain. | |
function tap(obj, interceptor) { | |
interceptor(obj); | |
return obj; | |
} | |
// Normalize a (deep) property `path` to array. | |
// Like `_.iteratee`, this function can be customized. | |
function toPath(path) { | |
return isArray(path) ? path : [path]; | |
} | |
_.toPath = toPath; | |
// Internal wrapper for `_.toPath` to enable minification. | |
// Similar to `cb` for `_.iteratee`. | |
function toPath$1(path) { | |
return _.toPath(path); | |
} | |
// Internal function to obtain a nested property in `obj` along `path`. | |
function deepGet(obj, path) { | |
var length = path.length; | |
for (var i = 0; i < length; i++) { | |
if (obj == null) return void 0; | |
obj = obj[path[i]]; | |
} | |
return length ? obj : void 0; | |
} | |
// Get the value of the (deep) property on `path` from `object`. | |
// If any property in `path` does not exist or if the value is | |
// `undefined`, return `defaultValue` instead. | |
// The `path` is normalized through `_.toPath`. | |
function get(object, path, defaultValue) { | |
var value = deepGet(object, toPath$1(path)); | |
return isUndefined(value) ? defaultValue : value; | |
} | |
// Shortcut function for checking if an object has a given property directly on | |
// itself (in other words, not on a prototype). Unlike the internal `has` | |
// function, this public version can also traverse nested properties. | |
function has$1(obj, path) { | |
path = toPath$1(path); | |
var length = path.length; | |
for (var i = 0; i < length; i++) { | |
var key = path[i]; | |
if (!has(obj, key)) return false; | |
obj = obj[key]; | |
} | |
return !!length; | |
} | |
// Keep the identity function around for default iteratees. | |
function identity(value) { | |
return value; | |
} | |
// Returns a predicate for checking whether an object has a given set of | |
// `key:value` pairs. | |
function matcher(attrs) { | |
attrs = extendOwn({}, attrs); | |
return function(obj) { | |
return isMatch(obj, attrs); | |
}; | |
} | |
// Creates a function that, when passed an object, will traverse that object’s | |
// properties down the given `path`, specified as an array of keys or indices. | |
function property(path) { | |
path = toPath$1(path); | |
return function(obj) { | |
return deepGet(obj, path); | |
}; | |
} | |
// Internal function that returns an efficient (for current engines) version | |
// of the passed-in callback, to be repeatedly applied in other Underscore | |
// functions. | |
function optimizeCb(func, context, argCount) { | |
if (context === void 0) return func; | |
switch (argCount == null ? 3 : argCount) { | |
case 1: return function(value) { | |
return func.call(context, value); | |
}; | |
// The 2-argument case is omitted because we’re not using it. | |
case 3: return function(value, index, collection) { | |
return func.call(context, value, index, collection); | |
}; | |
case 4: return function(accumulator, value, index, collection) { | |
return func.call(context, accumulator, value, index, collection); | |
}; | |
} | |
return function() { | |
return func.apply(context, arguments); | |
}; | |
} | |
// An internal function to generate callbacks that can be applied to each | |
// element in a collection, returning the desired result — either `_.identity`, | |
// an arbitrary callback, a property matcher, or a property accessor. | |
function baseIteratee(value, context, argCount) { | |
if (value == null) return identity; | |
if (isFunction$1(value)) return optimizeCb(value, context, argCount); | |
if (isObject(value) && !isArray(value)) return matcher(value); | |
return property(value); | |
} | |
// External wrapper for our callback generator. Users may customize | |
// `_.iteratee` if they want additional predicate/iteratee shorthand styles. | |
// This abstraction hides the internal-only `argCount` argument. | |
function iteratee(value, context) { | |
return baseIteratee(value, context, Infinity); | |
} | |
_.iteratee = iteratee; | |
// The function we call internally to generate a callback. It invokes | |
// `_.iteratee` if overridden, otherwise `baseIteratee`. | |
function cb(value, context, argCount) { | |
if (_.iteratee !== iteratee) return _.iteratee(value, context); | |
return baseIteratee(value, context, argCount); | |
} | |
// Returns the results of applying the `iteratee` to each element of `obj`. | |
// In contrast to `_.map` it returns an object. | |
function mapObject(obj, iteratee, context) { | |
iteratee = cb(iteratee, context); | |
var _keys = keys(obj), | |
length = _keys.length, | |
results = {}; | |
for (var index = 0; index < length; index++) { | |
var currentKey = _keys[index]; | |
results[currentKey] = iteratee(obj[currentKey], currentKey, obj); | |
} | |
return results; | |
} | |
// Predicate-generating function. Often useful outside of Underscore. | |
function noop(){} | |
// Generates a function for a given object that returns a given property. | |
function propertyOf(obj) { | |
if (obj == null) return noop; | |
return function(path) { | |
return get(obj, path); | |
}; | |
} | |
// Run a function **n** times. | |
function times(n, iteratee, context) { | |
var accum = Array(Math.max(0, n)); | |
iteratee = optimizeCb(iteratee, context, 1); | |
for (var i = 0; i < n; i++) accum[i] = iteratee(i); | |
return accum; | |
} | |
// Return a random integer between `min` and `max` (inclusive). | |
function random(min, max) { | |
if (max == null) { | |
max = min; | |
min = 0; | |
} | |
return min + Math.floor(Math.random() * (max - min + 1)); | |
} | |
// A (possibly faster) way to get the current timestamp as an integer. | |
var now = Date.now || function() { | |
return new Date().getTime(); | |
}; | |
// Internal helper to generate functions for escaping and unescaping strings | |
// to/from HTML interpolation. | |
function createEscaper(map) { | |
var escaper = function(match) { | |
return map[match]; | |
}; | |
// Regexes for identifying a key that needs to be escaped. | |
var source = '(?:' + keys(map).join('|') + ')'; | |
var testRegexp = RegExp(source); | |
var replaceRegexp = RegExp(source, 'g'); | |
return function(string) { | |
string = string == null ? '' : '' + string; | |
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; | |
}; | |
} | |
// Internal list of HTML entities for escaping. | |
var escapeMap = { | |
'&': '&', | |
'<': '<', | |
'>': '>', | |
'"': '"', | |
"'": ''', | |
'`': '`' | |
}; | |
// Function for escaping strings to HTML interpolation. | |
var _escape = createEscaper(escapeMap); | |
// Internal list of HTML entities for unescaping. | |
var unescapeMap = invert(escapeMap); | |
// Function for unescaping strings from HTML interpolation. | |
var _unescape = createEscaper(unescapeMap); | |
// By default, Underscore uses ERB-style template delimiters. Change the | |
// following template settings to use alternative delimiters. | |
var templateSettings = _.templateSettings = { | |
evaluate: /<%([\s\S]+?)%>/g, | |
interpolate: /<%=([\s\S]+?)%>/g, | |
escape: /<%-([\s\S]+?)%>/g | |
}; | |
// When customizing `_.templateSettings`, if you don't want to define an | |
// interpolation, evaluation or escaping regex, we need one that is | |
// guaranteed not to match. | |
var noMatch = /(.)^/; | |
// Certain characters need to be escaped so that they can be put into a | |
// string literal. | |
var escapes = { | |
"'": "'", | |
'\\': '\\', | |
'\r': 'r', | |
'\n': 'n', | |
'\u2028': 'u2028', | |
'\u2029': 'u2029' | |
}; | |
var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g; | |
function escapeChar(match) { | |
return '\\' + escapes[match]; | |
} | |
// JavaScript micro-templating, similar to John Resig's implementation. | |
// Underscore templating handles arbitrary delimiters, preserves whitespace, | |
// and correctly escapes quotes within interpolated code. | |
// NB: `oldSettings` only exists for backwards compatibility. | |
function template(text, settings, oldSettings) { | |
if (!settings && oldSettings) settings = oldSettings; | |
settings = defaults({}, settings, _.templateSettings); | |
// Combine delimiters into one regular expression via alternation. | |
var matcher = RegExp([ | |
(settings.escape || noMatch).source, | |
(settings.interpolate || noMatch).source, | |
(settings.evaluate || noMatch).source | |
].join('|') + '|$', 'g'); | |
// Compile the template source, escaping string literals appropriately. | |
var index = 0; | |
var source = "__p+='"; | |
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { | |
source += text.slice(index, offset).replace(escapeRegExp, escapeChar); | |
index = offset + match.length; | |
if (escape) { | |
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; | |
} else if (interpolate) { | |
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; | |
} else if (evaluate) { | |
source += "';\n" + evaluate + "\n__p+='"; | |
} | |
// Adobe VMs need the match returned to produce the correct offset. | |
return match; | |
}); | |
source += "';\n"; | |
// If a variable is not specified, place data values in local scope. | |
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; | |
source = "var __t,__p='',__j=Array.prototype.join," + | |
"print=function(){__p+=__j.call(arguments,'');};\n" + | |
source + 'return __p;\n'; | |
var render; | |
try { | |
render = new Function(settings.variable || 'obj', '_', source); | |
} catch (e) { | |
e.source = source; | |
throw e; | |
} | |
var template = function(data) { | |
return render.call(this, data, _); | |
}; | |
// Provide the compiled source as a convenience for precompilation. | |
var argument = settings.variable || 'obj'; | |
template.source = 'function(' + argument + '){\n' + source + '}'; | |
return template; | |
} | |
// Traverses the children of `obj` along `path`. If a child is a function, it | |
// is invoked with its parent as context. Returns the value of the final | |
// child, or `fallback` if any child is undefined. | |
function result(obj, path, fallback) { | |
path = toPath$1(path); | |
var length = path.length; | |
if (!length) { | |
return isFunction$1(fallback) ? fallback.call(obj) : fallback; | |
} | |
for (var i = 0; i < length; i++) { | |
var prop = obj == null ? void 0 : obj[path[i]]; | |
if (prop === void 0) { | |
prop = fallback; | |
i = length; // Ensure we don't continue iterating. | |
} | |
obj = isFunction$1(prop) ? prop.call(obj) : prop; | |
} | |
return obj; | |
} | |
// Generate a unique integer id (unique within the entire client session). | |
// Useful for temporary DOM ids. | |
var idCounter = 0; | |
function uniqueId(prefix) { | |
var id = ++idCounter + ''; | |
return prefix ? prefix + id : id; | |
} | |
// Start chaining a wrapped Underscore object. | |
function chain(obj) { | |
var instance = _(obj); | |
instance._chain = true; | |
return instance; | |
} | |
// Internal function to execute `sourceFunc` bound to `context` with optional | |
// `args`. Determines whether to execute a function as a constructor or as a | |
// normal function. | |
function executeBound(sourceFunc, boundFunc, context, callingContext, args) { | |
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); | |
var self = baseCreate(sourceFunc.prototype); | |
var result = sourceFunc.apply(self, args); | |
if (isObject(result)) return result; | |
return self; | |
} | |
// Partially apply a function by creating a version that has had some of its | |
// arguments pre-filled, without changing its dynamic `this` context. `_` acts | |
// as a placeholder by default, allowing any combination of arguments to be | |
// pre-filled. Set `_.partial.placeholder` for a custom placeholder argument. | |
var partial = restArguments(function(func, boundArgs) { | |
var placeholder = partial.placeholder; | |
var bound = function() { | |
var position = 0, length = boundArgs.length; | |
var args = Array(length); | |
for (var i = 0; i < length; i++) { | |
args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i]; | |
} | |
while (position < arguments.length) args.push(arguments[position++]); | |
return executeBound(func, bound, this, this, args); | |
}; | |
return bound; | |
}); | |
partial.placeholder = _; | |
// Create a function bound to a given object (assigning `this`, and arguments, | |
// optionally). | |
var bind = restArguments(function(func, context, args) { | |
if (!isFunction$1(func)) throw new TypeError('Bind must be called on a function'); | |
var bound = restArguments(function(callArgs) { | |
return executeBound(func, bound, context, this, args.concat(callArgs)); | |
}); | |
return bound; | |
}); | |
// Internal helper for collection methods to determine whether a collection | |
// should be iterated as an array or as an object. | |
// Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength | |
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 | |
var isArrayLike = createSizePropertyCheck(getLength); | |
// Internal implementation of a recursive `flatten` function. | |
function flatten(input, depth, strict, output) { | |
output = output || []; | |
if (!depth && depth !== 0) { | |
depth = Infinity; | |
} else if (depth <= 0) { | |
return output.concat(input); | |
} | |
var idx = output.length; | |
for (var i = 0, length = getLength(input); i < length; i++) { | |
var value = input[i]; | |
if (isArrayLike(value) && (isArray(value) || isArguments$1(value))) { | |
// Flatten current level of array or arguments object. | |
if (depth > 1) { | |
flatten(value, depth - 1, strict, output); | |
idx = output.length; | |
} else { | |
var j = 0, len = value.length; | |
while (j < len) output[idx++] = value[j++]; | |
} | |
} else if (!strict) { | |
output[idx++] = value; | |
} | |
} | |
return output; | |
} | |
// Bind a number of an object's methods to that object. Remaining arguments | |
// are the method names to be bound. Useful for ensuring that all callbacks | |
// defined on an object belong to it. | |
var bindAll = restArguments(function(obj, keys) { | |
keys = flatten(keys, false, false); | |
var index = keys.length; | |
if (index < 1) throw new Error('bindAll must be passed function names'); | |
while (index--) { | |
var key = keys[index]; | |
obj[key] = bind(obj[key], obj); | |
} | |
return obj; | |
}); | |
// Memoize an expensive function by storing its results. | |
function memoize(func, hasher) { | |
var memoize = function(key) { | |
var cache = memoize.cache; | |
var address = '' + (hasher ? hasher.apply(this, arguments) : key); | |
if (!has(cache, address)) cache[address] = func.apply(this, arguments); | |
return cache[address]; | |
}; | |
memoize.cache = {}; | |
return memoize; | |
} | |
// Delays a function for the given number of milliseconds, and then calls | |
// it with the arguments supplied. | |
var delay = restArguments(function(func, wait, args) { | |
return setTimeout(function() { | |
return func.apply(null, args); | |
}, wait); | |
}); | |
// Defers a function, scheduling it to run after the current call stack has | |
// cleared. | |
var defer = partial(delay, _, 1); | |
// Returns a function, that, when invoked, will only be triggered at most once | |
// during a given window of time. Normally, the throttled function will run | |
// as much as it can, without ever going more than once per `wait` duration; | |
// but if you'd like to disable the execution on the leading edge, pass | |
// `{leading: false}`. To disable execution on the trailing edge, ditto. | |
function throttle(func, wait, options) { | |
var timeout, context, args, result; | |
var previous = 0; | |
if (!options) options = {}; | |
var later = function() { | |
previous = options.leading === false ? 0 : now(); | |
timeout = null; | |
result = func.apply(context, args); | |
if (!timeout) context = args = null; | |
}; | |
var throttled = function() { | |
var _now = now(); | |
if (!previous && options.leading === false) previous = _now; | |
var remaining = wait - (_now - previous); | |
context = this; | |
args = arguments; | |
if (remaining <= 0 || remaining > wait) { | |
if (timeout) { | |
clearTimeout(timeout); | |
timeout = null; | |
} | |
previous = _now; | |
result = func.apply(context, args); | |
if (!timeout) context = args = null; | |
} else if (!timeout && options.trailing !== false) { | |
timeout = setTimeout(later, remaining); | |
} | |
return result; | |
}; | |
throttled.cancel = function() { | |
clearTimeout(timeout); | |
previous = 0; | |
timeout = context = args = null; | |
}; | |
return throttled; | |
} | |
// When a sequence of calls of the returned function ends, the argument | |
// function is triggered. The end of a sequence is defined by the `wait` | |
// parameter. If `immediate` is passed, the argument function will be | |
// triggered at the beginning of the sequence instead of at the end. | |
function debounce(func, wait, immediate) { | |
var timeout, result; | |
var later = function(context, args) { | |
timeout = null; | |
if (args) result = func.apply(context, args); | |
}; | |
var debounced = restArguments(function(args) { | |
if (timeout) clearTimeout(timeout); | |
if (immediate) { | |
var callNow = !timeout; | |
timeout = setTimeout(later, wait); | |
if (callNow) result = func.apply(this, args); | |
} else { | |
timeout = delay(later, wait, this, args); | |
} | |
return result; | |
}); | |
debounced.cancel = function() { | |
clearTimeout(timeout); | |
timeout = null; | |
}; | |
return debounced; | |
} | |
// Returns the first function passed as an argument to the second, | |
// allowing you to adjust arguments, run code before and after, and | |
// conditionally execute the original function. | |
function wrap(func, wrapper) { | |
return partial(wrapper, func); | |
} | |
// Returns a negated version of the passed-in predicate. | |
function negate(predicate) { | |
return function() { | |
return !predicate.apply(this, arguments); | |
}; | |
} | |
// Returns a function that is the composition of a list of functions, each | |
// consuming the return value of the function that follows. | |
function compose() { | |
var args = arguments; | |
var start = args.length - 1; | |
return function() { | |
var i = start; | |
var result = args[start].apply(this, arguments); | |
while (i--) result = args[i].call(this, result); | |
return result; | |
}; | |
} | |
// Returns a function that will only be executed on and after the Nth call. | |
function after(times, func) { | |
return function() { | |
if (--times < 1) { | |
return func.apply(this, arguments); | |
} | |
}; | |
} | |
// Returns a function that will only be executed up to (but not including) the | |
// Nth call. | |
function before(times, func) { | |
var memo; | |
return function() { | |
if (--times > 0) { | |
memo = func.apply(this, arguments); | |
} | |
if (times <= 1) func = null; | |
return memo; | |
}; | |
} | |
// Returns a function that will be executed at most one time, no matter how | |
// often you call it. Useful for lazy initialization. | |
var once = partial(before, 2); | |
// Returns the first key on an object that passes a truth test. | |
function findKey(obj, predicate, context) { | |
predicate = cb(predicate, context); | |
var _keys = keys(obj), key; | |
for (var i = 0, length = _keys.length; i < length; i++) { | |
key = _keys[i]; | |
if (predicate(obj[key], key, obj)) return key; | |
} | |
} | |
// Internal function to generate `_.findIndex` and `_.findLastIndex`. | |
function createPredicateIndexFinder(dir) { | |
return function(array, predicate, context) { | |
predicate = cb(predicate, context); | |
var length = getLength(array); | |
var index = dir > 0 ? 0 : length - 1; | |
for (; index >= 0 && index < length; index += dir) { | |
if (predicate(array[index], index, array)) return index; | |
} | |
return -1; | |
}; | |
} | |
// Returns the first index on an array-like that passes a truth test. | |
var findIndex = createPredicateIndexFinder(1); | |
// Returns the last index on an array-like that passes a truth test. | |
var findLastIndex = createPredicateIndexFinder(-1); | |
// Use a comparator function to figure out the smallest index at which | |
// an object should be inserted so as to maintain order. Uses binary search. | |
function sortedIndex(array, obj, iteratee, context) { | |
iteratee = cb(iteratee, context, 1); | |
var value = iteratee(obj); | |
var low = 0, high = getLength(array); | |
while (low < high) { | |
var mid = Math.floor((low + high) / 2); | |
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; | |
} | |
return low; | |
} | |
// Internal function to generate the `_.indexOf` and `_.lastIndexOf` functions. | |
function createIndexFinder(dir, predicateFind, sortedIndex) { | |
return function(array, item, idx) { | |
var i = 0, length = getLength(array); | |
if (typeof idx == 'number') { | |
if (dir > 0) { | |
i = idx >= 0 ? idx : Math.max(idx + length, i); | |
} else { | |
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; | |
} | |
} else if (sortedIndex && idx && length) { | |
idx = sortedIndex(array, item); | |
return array[idx] === item ? idx : -1; | |
} | |
if (item !== item) { | |
idx = predicateFind(slice.call(array, i, length), isNaN$1); | |
return idx >= 0 ? idx + i : -1; | |
} | |
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { | |
if (array[idx] === item) return idx; | |
} | |
return -1; | |
}; | |
} | |
// Return the position of the first occurrence of an item in an array, | |
// or -1 if the item is not included in the array. | |
// If the array is large and already in sort order, pass `true` | |
// for **isSorted** to use binary search. | |
var indexOf = createIndexFinder(1, findIndex, sortedIndex); | |
// Return the position of the last occurrence of an item in an array, | |
// or -1 if the item is not included in the array. | |
var lastIndexOf = createIndexFinder(-1, findLastIndex); | |
// Return the first value which passes a truth test. | |
function find(obj, predicate, context) { | |
var keyFinder = isArrayLike(obj) ? findIndex : findKey; | |
var key = keyFinder(obj, predicate, context); | |
if (key !== void 0 && key !== -1) return obj[key]; | |
} | |
// Convenience version of a common use case of `_.find`: getting the first | |
// object containing specific `key:value` pairs. | |
function findWhere(obj, attrs) { | |
return find(obj, matcher(attrs)); | |
} | |
// The cornerstone for collection functions, an `each` | |
// implementation, aka `forEach`. | |
// Handles raw objects in addition to array-likes. Treats all | |
// sparse array-likes as if they were dense. | |
function each(obj, iteratee, context) { | |
iteratee = optimizeCb(iteratee, context); | |
var i, length; | |
if (isArrayLike(obj)) { | |
for (i = 0, length = obj.length; i < length; i++) { | |
iteratee(obj[i], i, obj); | |
} | |
} else { | |
var _keys = keys(obj); | |
for (i = 0, length = _keys.length; i < length; i++) { | |
iteratee(obj[_keys[i]], _keys[i], obj); | |
} | |
} | |
return obj; | |
} | |
// Return the results of applying the iteratee to each element. | |
function map(obj, iteratee, context) { | |
iteratee = cb(iteratee, context); | |
var _keys = !isArrayLike(obj) && keys(obj), | |
length = (_keys || obj).length, | |
results = Array(length); | |
for (var index = 0; index < length; index++) { | |
var currentKey = _keys ? _keys[index] : index; | |
results[index] = iteratee(obj[currentKey], currentKey, obj); | |
} | |
return results; | |
} | |
// Internal helper to create a reducing function, iterating left or right. | |
function createReduce(dir) { | |
// Wrap code that reassigns argument variables in a separate function than | |
// the one that accesses `arguments.length` to avoid a perf hit. (#1991) | |
var reducer = function(obj, iteratee, memo, initial) { | |
var _keys = !isArrayLike(obj) && keys(obj), | |
length = (_keys || obj).length, | |
index = dir > 0 ? 0 : length - 1; | |
if (!initial) { | |
memo = obj[_keys ? _keys[index] : index]; | |
index += dir; | |
} | |
for (; index >= 0 && index < length; index += dir) { | |
var currentKey = _keys ? _keys[index] : index; | |
memo = iteratee(memo, obj[currentKey], currentKey, obj); | |
} | |
return memo; | |
}; | |
return function(obj, iteratee, memo, context) { | |
var initial = arguments.length >= 3; | |
return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial); | |
}; | |
} | |
// **Reduce** builds up a single result from a list of values, aka `inject`, | |
// or `foldl`. | |
var reduce = createReduce(1); | |
// The right-associative version of reduce, also known as `foldr`. | |
var reduceRight = createReduce(-1); | |
// Return all the elements that pass a truth test. | |
function filter(obj, predicate, context) { | |
var results = []; | |
predicate = cb(predicate, context); | |
each(obj, function(value, index, list) { | |
if (predicate(value, index, list)) results.push(value); | |
}); | |
return results; | |
} | |
// Return all the elements for which a truth test fails. | |
function reject(obj, predicate, context) { | |
return filter(obj, negate(cb(predicate)), context); | |
} | |
// Determine whether all of the elements pass a truth test. | |
function every(obj, predicate, context) { | |
predicate = cb(predicate, context); | |
var _keys = !isArrayLike(obj) && keys(obj), | |
length = (_keys || obj).length; | |
for (var index = 0; index < length; index++) { | |
var currentKey = _keys ? _keys[index] : index; | |
if (!predicate(obj[currentKey], currentKey, obj)) return false; | |
} | |
return true; | |
} | |
// Determine if at least one element in the object passes a truth test. | |
function some(obj, predicate, context) { | |
predicate = cb(predicate, context); | |
var _keys = !isArrayLike(obj) && keys(obj), | |
length = (_keys || obj).length; | |
for (var index = 0; index < length; index++) { | |
var currentKey = _keys ? _keys[index] : index; | |
if (predicate(obj[currentKey], currentKey, obj)) return true; | |
} | |
return false; | |
} | |
// Determine if the array or object contains a given item (using `===`). | |
function contains(obj, item, fromIndex, guard) { | |
if (!isArrayLike(obj)) obj = values(obj); | |
if (typeof fromIndex != 'number' || guard) fromIndex = 0; | |
return indexOf(obj, item, fromIndex) >= 0; | |
} | |
// Invoke a method (with arguments) on every item in a collection. | |
var invoke = restArguments(function(obj, path, args) { | |
var contextPath, func; | |
if (isFunction$1(path)) { | |
func = path; | |
} else { | |
path = toPath$1(path); | |
contextPath = path.slice(0, -1); | |
path = path[path.length - 1]; | |
} | |
return map(obj, function(context) { | |
var method = func; | |
if (!method) { | |
if (contextPath && contextPath.length) { | |
context = deepGet(context, contextPath); | |
} | |
if (context == null) return void 0; | |
method = context[path]; | |
} | |
return method == null ? method : method.apply(context, args); | |
}); | |
}); | |
// Convenience version of a common use case of `_.map`: fetching a property. | |
function pluck(obj, key) { | |
return map(obj, property(key)); | |
} | |
// Convenience version of a common use case of `_.filter`: selecting only | |
// objects containing specific `key:value` pairs. | |
function where(obj, attrs) { | |
return filter(obj, matcher(attrs)); | |
} | |
// Return the maximum element (or element-based computation). | |
function max(obj, iteratee, context) { | |
var result = -Infinity, lastComputed = -Infinity, | |
value, computed; | |
if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) { | |
obj = isArrayLike(obj) ? obj : values(obj); | |
for (var i = 0, length = obj.length; i < length; i++) { | |
value = obj[i]; | |
if (value != null && value > result) { | |
result = value; | |
} | |
} | |
} else { | |
iteratee = cb(iteratee, context); | |
each(obj, function(v, index, list) { | |
computed = iteratee(v, index, list); | |
if (computed > lastComputed || computed === -Infinity && result === -Infinity) { | |
result = v; | |
lastComputed = computed; | |
} | |
}); | |
} | |
return result; | |
} | |
// Return the minimum element (or element-based computation). | |
function min(obj, iteratee, context) { | |
var result = Infinity, lastComputed = Infinity, | |
value, computed; | |
if (iteratee == null || typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null) { | |
obj = isArrayLike(obj) ? obj : values(obj); | |
for (var i = 0, length = obj.length; i < length; i++) { | |
value = obj[i]; | |
if (value != null && value < result) { | |
result = value; | |
} | |
} | |
} else { | |
iteratee = cb(iteratee, context); | |
each(obj, function(v, index, list) { | |
computed = iteratee(v, index, list); | |
if (computed < lastComputed || computed === Infinity && result === Infinity) { | |
result = v; | |
lastComputed = computed; | |
} | |
}); | |
} | |
return result; | |
} | |
// Sample **n** random values from a collection using the modern version of the | |
// [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle). | |
// If **n** is not specified, returns a single random element. | |
// The internal `guard` argument allows it to work with `_.map`. | |
function sample(obj, n, guard) { | |
if (n == null || guard) { | |
if (!isArrayLike(obj)) obj = values(obj); | |
return obj[random(obj.length - 1)]; | |
} | |
var sample = isArrayLike(obj) ? clone(obj) : values(obj); | |
var length = getLength(sample); | |
n = Math.max(Math.min(n, length), 0); | |
var last = length - 1; | |
for (var index = 0; index < n; index++) { | |
var rand = random(index, last); | |
var temp = sample[index]; | |
sample[index] = sample[rand]; | |
sample[rand] = temp; | |
} | |
return sample.slice(0, n); | |
} | |
// Shuffle a collection. | |
function shuffle(obj) { | |
return sample(obj, Infinity); | |
} | |
// Sort the object's values by a criterion produced by an iteratee. | |
function sortBy(obj, iteratee, context) { | |
var index = 0; | |
iteratee = cb(iteratee, context); | |
return pluck(map(obj, function(value, key, list) { | |
return { | |
value: value, | |
index: index++, | |
criteria: iteratee(value, key, list) | |
}; | |
}).sort(function(left, right) { | |
var a = left.criteria; | |
var b = right.criteria; | |
if (a !== b) { | |
if (a > b || a === void 0) return 1; | |
if (a < b || b === void 0) return -1; | |
} | |
return left.index - right.index; | |
}), 'value'); | |
} | |
// An internal function used for aggregate "group by" operations. | |
function group(behavior, partition) { | |
return function(obj, iteratee, context) { | |
var result = partition ? [[], []] : {}; | |
iteratee = cb(iteratee, context); | |
each(obj, function(value, index) { | |
var key = iteratee(value, index, obj); | |
behavior(result, value, key); | |
}); | |
return result; | |
}; | |
} | |
// Groups the object's values by a criterion. Pass either a string attribute | |
// to group by, or a function that returns the criterion. | |
var groupBy = group(function(result, value, key) { | |
if (has(result, key)) result[key].push(value); else result[key] = [value]; | |
}); | |
// Indexes the object's values by a criterion, similar to `_.groupBy`, but for | |
// when you know that your index values will be unique. | |
var indexBy = group(function(result, value, key) { | |
result[key] = value; | |
}); | |
// Counts instances of an object that group by a certain criterion. Pass | |
// either a string attribute to count by, or a function that returns the | |
// criterion. | |
var countBy = group(function(result, value, key) { | |
if (has(result, key)) result[key]++; else result[key] = 1; | |
}); | |
// Split a collection into two arrays: one whose elements all pass the given | |
// truth test, and one whose elements all do not pass the truth test. | |
var partition = group(function(result, value, pass) { | |
result[pass ? 0 : 1].push(value); | |
}, true); | |
// Safely create a real, live array from anything iterable. | |
var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g; | |
function toArray(obj) { | |
if (!obj) return []; | |
if (isArray(obj)) return slice.call(obj); | |
if (isString(obj)) { | |
// Keep surrogate pair characters together. | |
return obj.match(reStrSymbol); | |
} | |
if (isArrayLike(obj)) return map(obj, identity); | |
return values(obj); | |
} | |
// Return the number of elements in a collection. | |
function size(obj) { | |
if (obj == null) return 0; | |
return isArrayLike(obj) ? obj.length : keys(obj).length; | |
} | |
// Internal `_.pick` helper function to determine whether `key` is an enumerable | |
// property name of `obj`. | |
function keyInObj(value, key, obj) { | |
return key in obj; | |
} | |
// Return a copy of the object only containing the allowed properties. | |
var pick = restArguments(function(obj, keys) { | |
var result = {}, iteratee = keys[0]; | |
if (obj == null) return result; | |
if (isFunction$1(iteratee)) { | |
if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]); | |
keys = allKeys(obj); | |
} else { | |
iteratee = keyInObj; | |
keys = flatten(keys, false, false); | |
obj = Object(obj); | |
} | |
for (var i = 0, length = keys.length; i < length; i++) { | |
var key = keys[i]; | |
var value = obj[key]; | |
if (iteratee(value, key, obj)) result[key] = value; | |
} | |
return result; | |
}); | |
// Return a copy of the object without the disallowed properties. | |
var omit = restArguments(function(obj, keys) { | |
var iteratee = keys[0], context; | |
if (isFunction$1(iteratee)) { | |
iteratee = negate(iteratee); | |
if (keys.length > 1) context = keys[1]; | |
} else { | |
keys = map(flatten(keys, false, false), String); | |
iteratee = function(value, key) { | |
return !contains(keys, key); | |
}; | |
} | |
return pick(obj, iteratee, context); | |
}); | |
// Returns everything but the last entry of the array. Especially useful on | |
// the arguments object. Passing **n** will return all the values in | |
// the array, excluding the last N. | |
function initial(array, n, guard) { | |
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); | |
} | |
// Get the first element of an array. Passing **n** will return the first N | |
// values in the array. The **guard** check allows it to work with `_.map`. | |
function first(array, n, guard) { | |
if (array == null || array.length < 1) return n == null || guard ? void 0 : []; | |
if (n == null || guard) return array[0]; | |
return initial(array, array.length - n); | |
} | |
// Returns everything but the first entry of the `array`. Especially useful on | |
// the `arguments` object. Passing an **n** will return the rest N values in the | |
// `array`. | |
function rest(array, n, guard) { | |
return slice.call(array, n == null || guard ? 1 : n); | |
} | |
// Get the last element of an array. Passing **n** will return the last N | |
// values in the array. | |
function last(array, n, guard) { | |
if (array == null || array.length < 1) return n == null || guard ? void 0 : []; | |
if (n == null || guard) return array[array.length - 1]; | |
return rest(array, Math.max(0, array.length - n)); | |
} | |
// Trim out all falsy values from an array. | |
function compact(array) { | |
return filter(array, Boolean); | |
} | |
// Flatten out an array, either recursively (by default), or up to `depth`. | |
// Passing `true` or `false` as `depth` means `1` or `Infinity`, respectively. | |
function flatten$1(array, depth) { | |
return flatten(array, depth, false); | |
} | |
// Take the difference between one array and a number of other arrays. | |
// Only the elements present in just the first array will remain. | |
var difference = restArguments(function(array, rest) { | |
rest = flatten(rest, true, true); | |
return filter(array, function(value){ | |
return !contains(rest, value); | |
}); | |
}); | |
// Return a version of the array that does not contain the specified value(s). | |
var without = restArguments(function(array, otherArrays) { | |
return difference(array, otherArrays); | |
}); | |
// Produce a duplicate-free version of the array. If the array has already | |
// been sorted, you have the option of using a faster algorithm. | |
// The faster algorithm will not work with an iteratee if the iteratee | |
// is not a one-to-one function, so providing an iteratee will disable | |
// the faster algorithm. | |
function uniq(array, isSorted, iteratee, context) { | |
if (!isBoolean(isSorted)) { | |
context = iteratee; | |
iteratee = isSorted; | |
isSorted = false; | |
} | |
if (iteratee != null) iteratee = cb(iteratee, context); | |
var result = []; | |
var seen = []; | |
for (var i = 0, length = getLength(array); i < length; i++) { | |
var value = array[i], | |
computed = iteratee ? iteratee(value, i, array) : value; | |
if (isSorted && !iteratee) { | |
if (!i || seen !== computed) result.push(value); | |
seen = computed; | |
} else if (iteratee) { | |
if (!contains(seen, computed)) { | |
seen.push(computed); | |
result.push(value); | |
} | |
} else if (!contains(result, value)) { | |
result.push(value); | |
} | |
} | |
return result; | |
} | |
// Produce an array that contains the union: each distinct element from all of | |
// the passed-in arrays. | |
var union = restArguments(function(arrays) { | |
return uniq(flatten(arrays, true, true)); | |
}); | |
// Produce an array that contains every item shared between all the | |
// passed-in arrays. | |
function intersection(array) { | |
var result = []; | |
var argsLength = arguments.length; | |
for (var i = 0, length = getLength(array); i < length; i++) { | |
var item = array[i]; | |
if (contains(result, item)) continue; | |
var j; | |
for (j = 1; j < argsLength; j++) { | |
if (!contains(arguments[j], item)) break; | |
} | |
if (j === argsLength) result.push(item); | |
} | |
return result; | |
} | |
// Complement of zip. Unzip accepts an array of arrays and groups | |
// each array's elements on shared indices. | |
function unzip(array) { | |
var length = array && max(array, getLength).length || 0; | |
var result = Array(length); | |
for (var index = 0; index < length; index++) { | |
result[index] = pluck(array, index); | |
} | |
return result; | |
} | |
// Zip together multiple lists into a single array -- elements that share | |
// an index go together. | |
var zip = restArguments(unzip); | |
// Converts lists into objects. Pass either a single array of `[key, value]` | |
// pairs, or two parallel arrays of the same length -- one of keys, and one of | |
// the corresponding values. Passing by pairs is the reverse of `_.pairs`. | |
function object(list, values) { | |
var result = {}; | |
for (var i = 0, length = getLength(list); i < length; i++) { | |
if (values) { | |
result[list[i]] = values[i]; | |
} else { | |
result[list[i][0]] = list[i][1]; | |
} | |
} | |
return result; | |
} | |
// Generate an integer Array containing an arithmetic progression. A port of | |
// the native Python `range()` function. See | |
// [the Python documentation](https://docs.python.org/library/functions.html#range). | |
function range(start, stop, step) { | |
if (stop == null) { | |
stop = start || 0; | |
start = 0; | |
} | |
if (!step) { | |
step = stop < start ? -1 : 1; | |
} | |
var length = Math.max(Math.ceil((stop - start) / step), 0); | |
var range = Array(length); | |
for (var idx = 0; idx < length; idx++, start += step) { | |
range[idx] = start; | |
} | |
return range; | |
} | |
// Chunk a single array into multiple arrays, each containing `count` or fewer | |
// items. | |
function chunk(array, count) { | |
if (count == null || count < 1) return []; | |
var result = []; | |
var i = 0, length = array.length; | |
while (i < length) { | |
result.push(slice.call(array, i, i += count)); | |
} | |
return result; | |
} | |
// Helper function to continue chaining intermediate results. | |
function chainResult(instance, obj) { | |
return instance._chain ? _(obj).chain() : obj; | |
} | |
// Add your own custom functions to the Underscore object. | |
function mixin(obj) { | |
each(functions(obj), function(name) { | |
var func = _[name] = obj[name]; | |
_.prototype[name] = function() { | |
var args = [this._wrapped]; | |
push.apply(args, arguments); | |
return chainResult(this, func.apply(_, args)); | |
}; | |
}); | |
return _; | |
} | |
// Add all mutator `Array` functions to the wrapper. | |
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { | |
var method = ArrayProto[name]; | |
_.prototype[name] = function() { | |
var obj = this._wrapped; | |
if (obj != null) { | |
method.apply(obj, arguments); | |
if ((name === 'shift' || name === 'splice') && obj.length === 0) { | |
delete obj[0]; | |
} | |
} | |
return chainResult(this, obj); | |
}; | |
}); | |
// Add all accessor `Array` functions to the wrapper. | |
each(['concat', 'join', 'slice'], function(name) { | |
var method = ArrayProto[name]; | |
_.prototype[name] = function() { | |
var obj = this._wrapped; | |
if (obj != null) obj = method.apply(obj, arguments); | |
return chainResult(this, obj); | |
}; | |
}); | |
// Named Exports | |
var allExports = { | |
__proto__: null, | |
VERSION: VERSION, | |
restArguments: restArguments, | |
isObject: isObject, | |
isNull: isNull, | |
isUndefined: isUndefined, | |
isBoolean: isBoolean, | |
isElement: isElement, | |
isString: isString, | |
isNumber: isNumber, | |
isDate: isDate, | |
isRegExp: isRegExp, | |
isError: isError, | |
isSymbol: isSymbol, | |
isArrayBuffer: isArrayBuffer, | |
isDataView: isDataView$1, | |
isArray: isArray, | |
isFunction: isFunction$1, | |
isArguments: isArguments$1, | |
isFinite: isFinite$1, | |
isNaN: isNaN$1, | |
isTypedArray: isTypedArray$1, | |
isEmpty: isEmpty, | |
isMatch: isMatch, | |
isEqual: isEqual, | |
isMap: isMap, | |
isWeakMap: isWeakMap, | |
isSet: isSet, | |
isWeakSet: isWeakSet, | |
keys: keys, | |
allKeys: allKeys, | |
values: values, | |
pairs: pairs, | |
invert: invert, | |
functions: functions, | |
methods: functions, | |
extend: extend, | |
extendOwn: extendOwn, | |
assign: extendOwn, | |
defaults: defaults, | |
create: create, | |
clone: clone, | |
tap: tap, | |
get: get, | |
has: has$1, | |
mapObject: mapObject, | |
identity: identity, | |
constant: constant, | |
noop: noop, | |
toPath: toPath, | |
property: property, | |
propertyOf: propertyOf, | |
matcher: matcher, | |
matches: matcher, | |
times: times, | |
random: random, | |
now: now, | |
escape: _escape, | |
unescape: _unescape, | |
templateSettings: templateSettings, | |
template: template, | |
result: result, | |
uniqueId: uniqueId, | |
chain: chain, | |
iteratee: iteratee, | |
partial: partial, | |
bind: bind, | |
bindAll: bindAll, | |
memoize: memoize, | |
delay: delay, | |
defer: defer, | |
throttle: throttle, | |
debounce: debounce, | |
wrap: wrap, | |
negate: negate, | |
compose: compose, | |
after: after, | |
before: before, | |
once: once, | |
findKey: findKey, | |
findIndex: findIndex, | |
findLastIndex: findLastIndex, | |
sortedIndex: sortedIndex, | |
indexOf: indexOf, | |
lastIndexOf: lastIndexOf, | |
find: find, | |
detect: find, | |
findWhere: findWhere, | |
each: each, | |
forEach: each, | |
map: map, | |
collect: map, | |
reduce: reduce, | |
foldl: reduce, | |
inject: reduce, | |
reduceRight: reduceRight, | |
foldr: reduceRight, | |
filter: filter, | |
select: filter, | |
reject: reject, | |
every: every, | |
all: every, | |
some: some, | |
any: some, | |
contains: contains, | |
includes: contains, | |
include: contains, | |
invoke: invoke, | |
pluck: pluck, | |
where: where, | |
max: max, | |
min: min, | |
shuffle: shuffle, | |
sample: sample, | |
sortBy: sortBy, | |
groupBy: groupBy, | |
indexBy: indexBy, | |
countBy: countBy, | |
partition: partition, | |
toArray: toArray, | |
size: size, | |
pick: pick, | |
omit: omit, | |
first: first, | |
head: first, | |
take: first, | |
initial: initial, | |
last: last, | |
rest: rest, | |
tail: rest, | |
drop: rest, | |
compact: compact, | |
flatten: flatten$1, | |
without: without, | |
uniq: uniq, | |
unique: uniq, | |
union: union, | |
intersection: intersection, | |
difference: difference, | |
unzip: unzip, | |
transpose: unzip, | |
zip: zip, | |
object: object, | |
range: range, | |
chunk: chunk, | |
mixin: mixin, | |
'default': _ | |
}; | |
// Default Export | |
// Add all of the Underscore functions to the wrapper object. | |
var _$1 = mixin(allExports); | |
// Legacy Node.js API. | |
_$1._ = _$1; | |
return _$1; | |
}))); | |
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{}],44:[function(require,module,exports){ | |
},{}],45:[function(require,module,exports){ | |
/** | |
* Array#filter. | |
* | |
* @param {Array} arr | |
* @param {Function} fn | |
* @param {Object=} self | |
* @return {Array} | |
* @throw TypeError | |
*/ | |
module.exports = function (arr, fn, self) { | |
if (arr.filter) return arr.filter(fn, self); | |
if (void 0 === arr || null === arr) throw new TypeError; | |
if ('function' != typeof fn) throw new TypeError; | |
var ret = []; | |
for (var i = 0; i < arr.length; i++) { | |
if (!hasOwn.call(arr, i)) continue; | |
var val = arr[i]; | |
if (fn.call(self, val, i, arr)) ret.push(val); | |
} | |
return ret; | |
}; | |
var hasOwn = Object.prototype.hasOwnProperty; | |
},{}],46:[function(require,module,exports){ | |
(function (global){(function (){ | |
'use strict'; | |
var filter = require('array-filter'); | |
module.exports = function availableTypedArrays() { | |
return filter([ | |
'BigInt64Array', | |
'BigUint64Array', | |
'Float32Array', | |
'Float64Array', | |
'Int16Array', | |
'Int32Array', | |
'Int8Array', | |
'Uint16Array', | |
'Uint32Array', | |
'Uint8Array', | |
'Uint8ClampedArray' | |
], function (typedArray) { | |
return typeof global[typedArray] === 'function'; | |
}); | |
}; | |
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"array-filter":45}],47:[function(require,module,exports){ | |
'use strict' | |
exports.byteLength = byteLength | |
exports.toByteArray = toByteArray | |
exports.fromByteArray = fromByteArray | |
var lookup = [] | |
var revLookup = [] | |
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array | |
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | |
for (var i = 0, len = code.length; i < len; ++i) { | |
lookup[i] = code[i] | |
revLookup[code.charCodeAt(i)] = i | |
} | |
// Support decoding URL-safe base64 strings, as Node.js does. | |
// See: https://en.wikipedia.org/wiki/Base64#URL_applications | |
revLookup['-'.charCodeAt(0)] = 62 | |
revLookup['_'.charCodeAt(0)] = 63 | |
function getLens (b64) { | |
var len = b64.length | |
if (len % 4 > 0) { | |
throw new Error('Invalid string. Length must be a multiple of 4') | |
} | |
// Trim off extra bytes after placeholder bytes are found | |
// See: https://github.com/beatgammit/base64-js/issues/42 | |
var validLen = b64.indexOf('=') | |
if (validLen === -1) validLen = len | |
var placeHoldersLen = validLen === len | |
? 0 | |
: 4 - (validLen % 4) | |
return [validLen, placeHoldersLen] | |
} | |
// base64 is 4/3 + up to two characters of the original data | |
function byteLength (b64) { | |
var lens = getLens(b64) | |
var validLen = lens[0] | |
var placeHoldersLen = lens[1] | |
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen | |
} | |
function _byteLength (b64, validLen, placeHoldersLen) { | |
return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen | |
} | |
function toByteArray (b64) { | |
var tmp | |
var lens = getLens(b64) | |
var validLen = lens[0] | |
var placeHoldersLen = lens[1] | |
var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) | |
var curByte = 0 | |
// if there are placeholders, only get up to the last complete 4 chars | |
var len = placeHoldersLen > 0 | |
? validLen - 4 | |
: validLen | |
var i | |
for (i = 0; i < len; i += 4) { | |
tmp = | |
(revLookup[b64.charCodeAt(i)] << 18) | | |
(revLookup[b64.charCodeAt(i + 1)] << 12) | | |
(revLookup[b64.charCodeAt(i + 2)] << 6) | | |
revLookup[b64.charCodeAt(i + 3)] | |
arr[curByte++] = (tmp >> 16) & 0xFF | |
arr[curByte++] = (tmp >> 8) & 0xFF | |
arr[curByte++] = tmp & 0xFF | |
} | |
if (placeHoldersLen === 2) { | |
tmp = | |
(revLookup[b64.charCodeAt(i)] << 2) | | |
(revLookup[b64.charCodeAt(i + 1)] >> 4) | |
arr[curByte++] = tmp & 0xFF | |
} | |
if (placeHoldersLen === 1) { | |
tmp = | |
(revLookup[b64.charCodeAt(i)] << 10) | | |
(revLookup[b64.charCodeAt(i + 1)] << 4) | | |
(revLookup[b64.charCodeAt(i + 2)] >> 2) | |
arr[curByte++] = (tmp >> 8) & 0xFF | |
arr[curByte++] = tmp & 0xFF | |
} | |
return arr | |
} | |
function tripletToBase64 (num) { | |
return lookup[num >> 18 & 0x3F] + | |
lookup[num >> 12 & 0x3F] + | |
lookup[num >> 6 & 0x3F] + | |
lookup[num & 0x3F] | |
} | |
function encodeChunk (uint8, start, end) { | |
var tmp | |
var output = [] | |
for (var i = start; i < end; i += 3) { | |
tmp = | |
((uint8[i] << 16) & 0xFF0000) + | |
((uint8[i + 1] << 8) & 0xFF00) + | |
(uint8[i + 2] & 0xFF) | |
output.push(tripletToBase64(tmp)) | |
} | |
return output.join('') | |
} | |
function fromByteArray (uint8) { | |
var tmp | |
var len = uint8.length | |
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes | |
var parts = [] | |
var maxChunkLength = 16383 // must be multiple of 3 | |
// go through the array every three bytes, we'll deal with trailing stuff later | |
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { | |
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) | |
} | |
// pad the end with zeros, but make sure to not forget the extra bytes | |
if (extraBytes === 1) { | |
tmp = uint8[len - 1] | |
parts.push( | |
lookup[tmp >> 2] + | |
lookup[(tmp << 4) & 0x3F] + | |
'==' | |
) | |
} else if (extraBytes === 2) { | |
tmp = (uint8[len - 2] << 8) + uint8[len - 1] | |
parts.push( | |
lookup[tmp >> 10] + | |
lookup[(tmp >> 4) & 0x3F] + | |
lookup[(tmp << 2) & 0x3F] + | |
'=' | |
) | |
} | |
return parts.join('') | |
} | |
},{}],48:[function(require,module,exports){ | |
(function (Buffer){(function (){ | |
/*! | |
* The buffer module from node.js, for the browser. | |
* | |
* @author Feross Aboukhadijeh <https://feross.org> | |
* @license MIT | |
*/ | |
/* eslint-disable no-proto */ | |
'use strict' | |
var base64 = require('base64-js') | |
var ieee754 = require('ieee754') | |
exports.Buffer = Buffer | |
exports.SlowBuffer = SlowBuffer | |
exports.INSPECT_MAX_BYTES = 50 | |
var K_MAX_LENGTH = 0x7fffffff | |
exports.kMaxLength = K_MAX_LENGTH | |
/** | |
* If `Buffer.TYPED_ARRAY_SUPPORT`: | |
* === true Use Uint8Array implementation (fastest) | |
* === false Print warning and recommend using `buffer` v4.x which has an Object | |
* implementation (most compatible, even IE6) | |
* | |
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, | |
* Opera 11.6+, iOS 4.2+. | |
* | |
* We report that the browser does not support typed arrays if the are not subclassable | |
* using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` | |
* (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support | |
* for __proto__ and has a buggy typed array implementation. | |
*/ | |
Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() | |
if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && | |
typeof console.error === 'function') { | |
console.error( | |
'This browser lacks typed array (Uint8Array) support which is required by ' + | |
'`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' | |
) | |
} | |
function typedArraySupport () { | |
// Can typed array instances can be augmented? | |
try { | |
var arr = new Uint8Array(1) | |
arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } } | |
return arr.foo() === 42 | |
} catch (e) { | |
return false | |
} | |
} | |
Object.defineProperty(Buffer.prototype, 'parent', { | |
enumerable: true, | |
get: function () { | |
if (!Buffer.isBuffer(this)) return undefined | |
return this.buffer | |
} | |
}) | |
Object.defineProperty(Buffer.prototype, 'offset', { | |
enumerable: true, | |
get: function () { | |
if (!Buffer.isBuffer(this)) return undefined | |
return this.byteOffset | |
} | |
}) | |
function createBuffer (length) { | |
if (length > K_MAX_LENGTH) { | |
throw new RangeError('The value "' + length + '" is invalid for option "size"') | |
} | |
// Return an augmented `Uint8Array` instance | |
var buf = new Uint8Array(length) | |
buf.__proto__ = Buffer.prototype | |
return buf | |
} | |
/** | |
* The Buffer constructor returns instances of `Uint8Array` that have their | |
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of | |
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods | |
* and the `Uint8Array` methods. Square bracket notation works as expected -- it | |
* returns a single octet. | |
* | |
* The `Uint8Array` prototype remains unmodified. | |
*/ | |
function Buffer (arg, encodingOrOffset, length) { | |
// Common case. | |
if (typeof arg === 'number') { | |
if (typeof encodingOrOffset === 'string') { | |
throw new TypeError( | |
'The "string" argument must be of type string. Received type number' | |
) | |
} | |
return allocUnsafe(arg) | |
} | |
return from(arg, encodingOrOffset, length) | |
} | |
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 | |
if (typeof Symbol !== 'undefined' && Symbol.species != null && | |
Buffer[Symbol.species] === Buffer) { | |
Object.defineProperty(Buffer, Symbol.species, { | |
value: null, | |
configurable: true, | |
enumerable: false, | |
writable: false | |
}) | |
} | |
Buffer.poolSize = 8192 // not used by this implementation | |
function from (value, encodingOrOffset, length) { | |
if (typeof value === 'string') { | |
return fromString(value, encodingOrOffset) | |
} | |
if (ArrayBuffer.isView(value)) { | |
return fromArrayLike(value) | |
} | |
if (value == null) { | |
throw TypeError( | |
'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + | |
'or Array-like Object. Received type ' + (typeof value) | |
) | |
} | |
if (isInstance(value, ArrayBuffer) || | |
(value && isInstance(value.buffer, ArrayBuffer))) { | |
return fromArrayBuffer(value, encodingOrOffset, length) | |
} | |
if (typeof value === 'number') { | |
throw new TypeError( | |
'The "value" argument must not be of type number. Received type number' | |
) | |
} | |
var valueOf = value.valueOf && value.valueOf() | |
if (valueOf != null && valueOf !== value) { | |
return Buffer.from(valueOf, encodingOrOffset, length) | |
} | |
var b = fromObject(value) | |
if (b) return b | |
if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && | |
typeof value[Symbol.toPrimitive] === 'function') { | |
return Buffer.from( | |
value[Symbol.toPrimitive]('string'), encodingOrOffset, length | |
) | |
} | |
throw new TypeError( | |
'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + | |
'or Array-like Object. Received type ' + (typeof value) | |
) | |
} | |
/** | |
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError | |
* if value is a number. | |
* Buffer.from(str[, encoding]) | |
* Buffer.from(array) | |
* Buffer.from(buffer) | |
* Buffer.from(arrayBuffer[, byteOffset[, length]]) | |
**/ | |
Buffer.from = function (value, encodingOrOffset, length) { | |
return from(value, encodingOrOffset, length) | |
} | |
// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: | |
// https://github.com/feross/buffer/pull/148 | |
Buffer.prototype.__proto__ = Uint8Array.prototype | |
Buffer.__proto__ = Uint8Array | |
function assertSize (size) { | |
if (typeof size !== 'number') { | |
throw new TypeError('"size" argument must be of type number') | |
} else if (size < 0) { | |
throw new RangeError('The value "' + size + '" is invalid for option "size"') | |
} | |
} | |
function alloc (size, fill, encoding) { | |
assertSize(size) | |
if (size <= 0) { | |
return createBuffer(size) | |
} | |
if (fill !== undefined) { | |
// Only pay attention to encoding if it's a string. This | |
// prevents accidentally sending in a number that would | |
// be interpretted as a start offset. | |
return typeof encoding === 'string' | |
? createBuffer(size).fill(fill, encoding) | |
: createBuffer(size).fill(fill) | |
} | |
return createBuffer(size) | |
} | |
/** | |
* Creates a new filled Buffer instance. | |
* alloc(size[, fill[, encoding]]) | |
**/ | |
Buffer.alloc = function (size, fill, encoding) { | |
return alloc(size, fill, encoding) | |
} | |
function allocUnsafe (size) { | |
assertSize(size) | |
return createBuffer(size < 0 ? 0 : checked(size) | 0) | |
} | |
/** | |
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. | |
* */ | |
Buffer.allocUnsafe = function (size) { | |
return allocUnsafe(size) | |
} | |
/** | |
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. | |
*/ | |
Buffer.allocUnsafeSlow = function (size) { | |
return allocUnsafe(size) | |
} | |
function fromString (string, encoding) { | |
if (typeof encoding !== 'string' || encoding === '') { | |
encoding = 'utf8' | |
} | |
if (!Buffer.isEncoding(encoding)) { | |
throw new TypeError('Unknown encoding: ' + encoding) | |
} | |
var length = byteLength(string, encoding) | 0 | |
var buf = createBuffer(length) | |
var actual = buf.write(string, encoding) | |
if (actual !== length) { | |
// Writing a hex string, for example, that contains invalid characters will | |
// cause everything after the first invalid character to be ignored. (e.g. | |
// 'abxxcd' will be treated as 'ab') | |
buf = buf.slice(0, actual) | |
} | |
return buf | |
} | |
function fromArrayLike (array) { | |
var length = array.length < 0 ? 0 : checked(array.length) | 0 | |
var buf = createBuffer(length) | |
for (var i = 0; i < length; i += 1) { | |
buf[i] = array[i] & 255 | |
} | |
return buf | |
} | |
function fromArrayBuffer (array, byteOffset, length) { | |
if (byteOffset < 0 || array.byteLength < byteOffset) { | |
throw new RangeError('"offset" is outside of buffer bounds') | |
} | |
if (array.byteLength < byteOffset + (length || 0)) { | |
throw new RangeError('"length" is outside of buffer bounds') | |
} | |
var buf | |
if (byteOffset === undefined && length === undefined) { | |
buf = new Uint8Array(array) | |
} else if (length === undefined) { | |
buf = new Uint8Array(array, byteOffset) | |
} else { | |
buf = new Uint8Array(array, byteOffset, length) | |
} | |
// Return an augmented `Uint8Array` instance | |
buf.__proto__ = Buffer.prototype | |
return buf | |
} | |
function fromObject (obj) { | |
if (Buffer.isBuffer(obj)) { | |
var len = checked(obj.length) | 0 | |
var buf = createBuffer(len) | |
if (buf.length === 0) { | |
return buf | |
} | |
obj.copy(buf, 0, 0, len) | |
return buf | |
} | |
if (obj.length !== undefined) { | |
if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { | |
return createBuffer(0) | |
} | |
return fromArrayLike(obj) | |
} | |
if (obj.type === 'Buffer' && Array.isArray(obj.data)) { | |
return fromArrayLike(obj.data) | |
} | |
} | |
function checked (length) { | |
// Note: cannot use `length < K_MAX_LENGTH` here because that fails when | |
// length is NaN (which is otherwise coerced to zero.) | |
if (length >= K_MAX_LENGTH) { | |
throw new RangeError('Attempt to allocate Buffer larger than maximum ' + | |
'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') | |
} | |
return length | 0 | |
} | |
function SlowBuffer (length) { | |
if (+length != length) { // eslint-disable-line eqeqeq | |
length = 0 | |
} | |
return Buffer.alloc(+length) | |
} | |
Buffer.isBuffer = function isBuffer (b) { | |
return b != null && b._isBuffer === true && | |
b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false | |
} | |
Buffer.compare = function compare (a, b) { | |
if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) | |
if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) | |
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { | |
throw new TypeError( | |
'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' | |
) | |
} | |
if (a === b) return 0 | |
var x = a.length | |
var y = b.length | |
for (var i = 0, len = Math.min(x, y); i < len; ++i) { | |
if (a[i] !== b[i]) { | |
x = a[i] | |
y = b[i] | |
break | |
} | |
} | |
if (x < y) return -1 | |
if (y < x) return 1 | |
return 0 | |
} | |
Buffer.isEncoding = function isEncoding (encoding) { | |
switch (String(encoding).toLowerCase()) { | |
case 'hex': | |
case 'utf8': | |
case 'utf-8': | |
case 'ascii': | |
case 'latin1': | |
case 'binary': | |
case 'base64': | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return true | |
default: | |
return false | |
} | |
} | |
Buffer.concat = function concat (list, length) { | |
if (!Array.isArray(list)) { | |
throw new TypeError('"list" argument must be an Array of Buffers') | |
} | |
if (list.length === 0) { | |
return Buffer.alloc(0) | |
} | |
var i | |
if (length === undefined) { | |
length = 0 | |
for (i = 0; i < list.length; ++i) { | |
length += list[i].length | |
} | |
} | |
var buffer = Buffer.allocUnsafe(length) | |
var pos = 0 | |
for (i = 0; i < list.length; ++i) { | |
var buf = list[i] | |
if (isInstance(buf, Uint8Array)) { | |
buf = Buffer.from(buf) | |
} | |
if (!Buffer.isBuffer(buf)) { | |
throw new TypeError('"list" argument must be an Array of Buffers') | |
} | |
buf.copy(buffer, pos) | |
pos += buf.length | |
} | |
return buffer | |
} | |
function byteLength (string, encoding) { | |
if (Buffer.isBuffer(string)) { | |
return string.length | |
} | |
if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { | |
return string.byteLength | |
} | |
if (typeof string !== 'string') { | |
throw new TypeError( | |
'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + | |
'Received type ' + typeof string | |
) | |
} | |
var len = string.length | |
var mustMatch = (arguments.length > 2 && arguments[2] === true) | |
if (!mustMatch && len === 0) return 0 | |
// Use a for loop to avoid recursion | |
var loweredCase = false | |
for (;;) { | |
switch (encoding) { | |
case 'ascii': | |
case 'latin1': | |
case 'binary': | |
return len | |
case 'utf8': | |
case 'utf-8': | |
return utf8ToBytes(string).length | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return len * 2 | |
case 'hex': | |
return len >>> 1 | |
case 'base64': | |
return base64ToBytes(string).length | |
default: | |
if (loweredCase) { | |
return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 | |
} | |
encoding = ('' + encoding).toLowerCase() | |
loweredCase = true | |
} | |
} | |
} | |
Buffer.byteLength = byteLength | |
function slowToString (encoding, start, end) { | |
var loweredCase = false | |
// No need to verify that "this.length <= MAX_UINT32" since it's a read-only | |
// property of a typed array. | |
// This behaves neither like String nor Uint8Array in that we set start/end | |
// to their upper/lower bounds if the value passed is out of range. | |
// undefined is handled specially as per ECMA-262 6th Edition, | |
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. | |
if (start === undefined || start < 0) { | |
start = 0 | |
} | |
// Return early if start > this.length. Done here to prevent potential uint32 | |
// coercion fail below. | |
if (start > this.length) { | |
return '' | |
} | |
if (end === undefined || end > this.length) { | |
end = this.length | |
} | |
if (end <= 0) { | |
return '' | |
} | |
// Force coersion to uint32. This will also coerce falsey/NaN values to 0. | |
end >>>= 0 | |
start >>>= 0 | |
if (end <= start) { | |
return '' | |
} | |
if (!encoding) encoding = 'utf8' | |
while (true) { | |
switch (encoding) { | |
case 'hex': | |
return hexSlice(this, start, end) | |
case 'utf8': | |
case 'utf-8': | |
return utf8Slice(this, start, end) | |
case 'ascii': | |
return asciiSlice(this, start, end) | |
case 'latin1': | |
case 'binary': | |
return latin1Slice(this, start, end) | |
case 'base64': | |
return base64Slice(this, start, end) | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return utf16leSlice(this, start, end) | |
default: | |
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) | |
encoding = (encoding + '').toLowerCase() | |
loweredCase = true | |
} | |
} | |
} | |
// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) | |
// to detect a Buffer instance. It's not possible to use `instanceof Buffer` | |
// reliably in a browserify context because there could be multiple different | |
// copies of the 'buffer' package in use. This method works even for Buffer | |
// instances that were created from another copy of the `buffer` package. | |
// See: https://github.com/feross/buffer/issues/154 | |
Buffer.prototype._isBuffer = true | |
function swap (b, n, m) { | |
var i = b[n] | |
b[n] = b[m] | |
b[m] = i | |
} | |
Buffer.prototype.swap16 = function swap16 () { | |
var len = this.length | |
if (len % 2 !== 0) { | |
throw new RangeError('Buffer size must be a multiple of 16-bits') | |
} | |
for (var i = 0; i < len; i += 2) { | |
swap(this, i, i + 1) | |
} | |
return this | |
} | |
Buffer.prototype.swap32 = function swap32 () { | |
var len = this.length | |
if (len % 4 !== 0) { | |
throw new RangeError('Buffer size must be a multiple of 32-bits') | |
} | |
for (var i = 0; i < len; i += 4) { | |
swap(this, i, i + 3) | |
swap(this, i + 1, i + 2) | |
} | |
return this | |
} | |
Buffer.prototype.swap64 = function swap64 () { | |
var len = this.length | |
if (len % 8 !== 0) { | |
throw new RangeError('Buffer size must be a multiple of 64-bits') | |
} | |
for (var i = 0; i < len; i += 8) { | |
swap(this, i, i + 7) | |
swap(this, i + 1, i + 6) | |
swap(this, i + 2, i + 5) | |
swap(this, i + 3, i + 4) | |
} | |
return this | |
} | |
Buffer.prototype.toString = function toString () { | |
var length = this.length | |
if (length === 0) return '' | |
if (arguments.length === 0) return utf8Slice(this, 0, length) | |
return slowToString.apply(this, arguments) | |
} | |
Buffer.prototype.toLocaleString = Buffer.prototype.toString | |
Buffer.prototype.equals = function equals (b) { | |
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') | |
if (this === b) return true | |
return Buffer.compare(this, b) === 0 | |
} | |
Buffer.prototype.inspect = function inspect () { | |
var str = '' | |
var max = exports.INSPECT_MAX_BYTES | |
str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() | |
if (this.length > max) str += ' ... ' | |
return '<Buffer ' + str + '>' | |
} | |
Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { | |
if (isInstance(target, Uint8Array)) { | |
target = Buffer.from(target, target.offset, target.byteLength) | |
} | |
if (!Buffer.isBuffer(target)) { | |
throw new TypeError( | |
'The "target" argument must be one of type Buffer or Uint8Array. ' + | |
'Received type ' + (typeof target) | |
) | |
} | |
if (start === undefined) { | |
start = 0 | |
} | |
if (end === undefined) { | |
end = target ? target.length : 0 | |
} | |
if (thisStart === undefined) { | |
thisStart = 0 | |
} | |
if (thisEnd === undefined) { | |
thisEnd = this.length | |
} | |
if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { | |
throw new RangeError('out of range index') | |
} | |
if (thisStart >= thisEnd && start >= end) { | |
return 0 | |
} | |
if (thisStart >= thisEnd) { | |
return -1 | |
} | |
if (start >= end) { | |
return 1 | |
} | |
start >>>= 0 | |
end >>>= 0 | |
thisStart >>>= 0 | |
thisEnd >>>= 0 | |
if (this === target) return 0 | |
var x = thisEnd - thisStart | |
var y = end - start | |
var len = Math.min(x, y) | |
var thisCopy = this.slice(thisStart, thisEnd) | |
var targetCopy = target.slice(start, end) | |
for (var i = 0; i < len; ++i) { | |
if (thisCopy[i] !== targetCopy[i]) { | |
x = thisCopy[i] | |
y = targetCopy[i] | |
break | |
} | |
} | |
if (x < y) return -1 | |
if (y < x) return 1 | |
return 0 | |
} | |
// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, | |
// OR the last index of `val` in `buffer` at offset <= `byteOffset`. | |
// | |
// Arguments: | |
// - buffer - a Buffer to search | |
// - val - a string, Buffer, or number | |
// - byteOffset - an index into `buffer`; will be clamped to an int32 | |
// - encoding - an optional encoding, relevant is val is a string | |
// - dir - true for indexOf, false for lastIndexOf | |
function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { | |
// Empty buffer means no match | |
if (buffer.length === 0) return -1 | |
// Normalize byteOffset | |
if (typeof byteOffset === 'string') { | |
encoding = byteOffset | |
byteOffset = 0 | |
} else if (byteOffset > 0x7fffffff) { | |
byteOffset = 0x7fffffff | |
} else if (byteOffset < -0x80000000) { | |
byteOffset = -0x80000000 | |
} | |
byteOffset = +byteOffset // Coerce to Number. | |
if (numberIsNaN(byteOffset)) { | |
// byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer | |
byteOffset = dir ? 0 : (buffer.length - 1) | |
} | |
// Normalize byteOffset: negative offsets start from the end of the buffer | |
if (byteOffset < 0) byteOffset = buffer.length + byteOffset | |
if (byteOffset >= buffer.length) { | |
if (dir) return -1 | |
else byteOffset = buffer.length - 1 | |
} else if (byteOffset < 0) { | |
if (dir) byteOffset = 0 | |
else return -1 | |
} | |
// Normalize val | |
if (typeof val === 'string') { | |
val = Buffer.from(val, encoding) | |
} | |
// Finally, search either indexOf (if dir is true) or lastIndexOf | |
if (Buffer.isBuffer(val)) { | |
// Special case: looking for empty string/buffer always fails | |
if (val.length === 0) { | |
return -1 | |
} | |
return arrayIndexOf(buffer, val, byteOffset, encoding, dir) | |
} else if (typeof val === 'number') { | |
val = val & 0xFF // Search for a byte value [0-255] | |
if (typeof Uint8Array.prototype.indexOf === 'function') { | |
if (dir) { | |
return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) | |
} else { | |
return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) | |
} | |
} | |
return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) | |
} | |
throw new TypeError('val must be string, number or Buffer') | |
} | |
function arrayIndexOf (arr, val, byteOffset, encoding, dir) { | |
var indexSize = 1 | |
var arrLength = arr.length | |
var valLength = val.length | |
if (encoding !== undefined) { | |
encoding = String(encoding).toLowerCase() | |
if (encoding === 'ucs2' || encoding === 'ucs-2' || | |
encoding === 'utf16le' || encoding === 'utf-16le') { | |
if (arr.length < 2 || val.length < 2) { | |
return -1 | |
} | |
indexSize = 2 | |
arrLength /= 2 | |
valLength /= 2 | |
byteOffset /= 2 | |
} | |
} | |
function read (buf, i) { | |
if (indexSize === 1) { | |
return buf[i] | |
} else { | |
return buf.readUInt16BE(i * indexSize) | |
} | |
} | |
var i | |
if (dir) { | |
var foundIndex = -1 | |
for (i = byteOffset; i < arrLength; i++) { | |
if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { | |
if (foundIndex === -1) foundIndex = i | |
if (i - foundIndex + 1 === valLength) return foundIndex * indexSize | |
} else { | |
if (foundIndex !== -1) i -= i - foundIndex | |
foundIndex = -1 | |
} | |
} | |
} else { | |
if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength | |
for (i = byteOffset; i >= 0; i--) { | |
var found = true | |
for (var j = 0; j < valLength; j++) { | |
if (read(arr, i + j) !== read(val, j)) { | |
found = false | |
break | |
} | |
} | |
if (found) return i | |
} | |
} | |
return -1 | |
} | |
Buffer.prototype.includes = function includes (val, byteOffset, encoding) { | |
return this.indexOf(val, byteOffset, encoding) !== -1 | |
} | |
Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { | |
return bidirectionalIndexOf(this, val, byteOffset, encoding, true) | |
} | |
Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { | |
return bidirectionalIndexOf(this, val, byteOffset, encoding, false) | |
} | |
function hexWrite (buf, string, offset, length) { | |
offset = Number(offset) || 0 | |
var remaining = buf.length - offset | |
if (!length) { | |
length = remaining | |
} else { | |
length = Number(length) | |
if (length > remaining) { | |
length = remaining | |
} | |
} | |
var strLen = string.length | |
if (length > strLen / 2) { | |
length = strLen / 2 | |
} | |
for (var i = 0; i < length; ++i) { | |
var parsed = parseInt(string.substr(i * 2, 2), 16) | |
if (numberIsNaN(parsed)) return i | |
buf[offset + i] = parsed | |
} | |
return i | |
} | |
function utf8Write (buf, string, offset, length) { | |
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) | |
} | |
function asciiWrite (buf, string, offset, length) { | |
return blitBuffer(asciiToBytes(string), buf, offset, length) | |
} | |
function latin1Write (buf, string, offset, length) { | |
return asciiWrite(buf, string, offset, length) | |
} | |
function base64Write (buf, string, offset, length) { | |
return blitBuffer(base64ToBytes(string), buf, offset, length) | |
} | |
function ucs2Write (buf, string, offset, length) { | |
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) | |
} | |
Buffer.prototype.write = function write (string, offset, length, encoding) { | |
// Buffer#write(string) | |
if (offset === undefined) { | |
encoding = 'utf8' | |
length = this.length | |
offset = 0 | |
// Buffer#write(string, encoding) | |
} else if (length === undefined && typeof offset === 'string') { | |
encoding = offset | |
length = this.length | |
offset = 0 | |
// Buffer#write(string, offset[, length][, encoding]) | |
} else if (isFinite(offset)) { | |
offset = offset >>> 0 | |
if (isFinite(length)) { | |
length = length >>> 0 | |
if (encoding === undefined) encoding = 'utf8' | |
} else { | |
encoding = length | |
length = undefined | |
} | |
} else { | |
throw new Error( | |
'Buffer.write(string, encoding, offset[, length]) is no longer supported' | |
) | |
} | |
var remaining = this.length - offset | |
if (length === undefined || length > remaining) length = remaining | |
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { | |
throw new RangeError('Attempt to write outside buffer bounds') | |
} | |
if (!encoding) encoding = 'utf8' | |
var loweredCase = false | |
for (;;) { | |
switch (encoding) { | |
case 'hex': | |
return hexWrite(this, string, offset, length) | |
case 'utf8': | |
case 'utf-8': | |
return utf8Write(this, string, offset, length) | |
case 'ascii': | |
return asciiWrite(this, string, offset, length) | |
case 'latin1': | |
case 'binary': | |
return latin1Write(this, string, offset, length) | |
case 'base64': | |
// Warning: maxLength not taken into account in base64Write | |
return base64Write(this, string, offset, length) | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return ucs2Write(this, string, offset, length) | |
default: | |
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) | |
encoding = ('' + encoding).toLowerCase() | |
loweredCase = true | |
} | |
} | |
} | |
Buffer.prototype.toJSON = function toJSON () { | |
return { | |
type: 'Buffer', | |
data: Array.prototype.slice.call(this._arr || this, 0) | |
} | |
} | |
function base64Slice (buf, start, end) { | |
if (start === 0 && end === buf.length) { | |
return base64.fromByteArray(buf) | |
} else { | |
return base64.fromByteArray(buf.slice(start, end)) | |
} | |
} | |
function utf8Slice (buf, start, end) { | |
end = Math.min(buf.length, end) | |
var res = [] | |
var i = start | |
while (i < end) { | |
var firstByte = buf[i] | |
var codePoint = null | |
var bytesPerSequence = (firstByte > 0xEF) ? 4 | |
: (firstByte > 0xDF) ? 3 | |
: (firstByte > 0xBF) ? 2 | |
: 1 | |
if (i + bytesPerSequence <= end) { | |
var secondByte, thirdByte, fourthByte, tempCodePoint | |
switch (bytesPerSequence) { | |
case 1: | |
if (firstByte < 0x80) { | |
codePoint = firstByte | |
} | |
break | |
case 2: | |
secondByte = buf[i + 1] | |
if ((secondByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) | |
if (tempCodePoint > 0x7F) { | |
codePoint = tempCodePoint | |
} | |
} | |
break | |
case 3: | |
secondByte = buf[i + 1] | |
thirdByte = buf[i + 2] | |
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) | |
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { | |
codePoint = tempCodePoint | |
} | |
} | |
break | |
case 4: | |
secondByte = buf[i + 1] | |
thirdByte = buf[i + 2] | |
fourthByte = buf[i + 3] | |
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { | |
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) | |
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { | |
codePoint = tempCodePoint | |
} | |
} | |
} | |
} | |
if (codePoint === null) { | |
// we did not generate a valid codePoint so insert a | |
// replacement char (U+FFFD) and advance only 1 byte | |
codePoint = 0xFFFD | |
bytesPerSequence = 1 | |
} else if (codePoint > 0xFFFF) { | |
// encode to utf16 (surrogate pair dance) | |
codePoint -= 0x10000 | |
res.push(codePoint >>> 10 & 0x3FF | 0xD800) | |
codePoint = 0xDC00 | codePoint & 0x3FF | |
} | |
res.push(codePoint) | |
i += bytesPerSequence | |
} | |
return decodeCodePointsArray(res) | |
} | |
// Based on http://stackoverflow.com/a/22747272/680742, the browser with | |
// the lowest limit is Chrome, with 0x10000 args. | |
// We go 1 magnitude less, for safety | |
var MAX_ARGUMENTS_LENGTH = 0x1000 | |
function decodeCodePointsArray (codePoints) { | |
var len = codePoints.length | |
if (len <= MAX_ARGUMENTS_LENGTH) { | |
return String.fromCharCode.apply(String, codePoints) // avoid extra slice() | |
} | |
// Decode in chunks to avoid "call stack size exceeded". | |
var res = '' | |
var i = 0 | |
while (i < len) { | |
res += String.fromCharCode.apply( | |
String, | |
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) | |
) | |
} | |
return res | |
} | |
function asciiSlice (buf, start, end) { | |
var ret = '' | |
end = Math.min(buf.length, end) | |
for (var i = start; i < end; ++i) { | |
ret += String.fromCharCode(buf[i] & 0x7F) | |
} | |
return ret | |
} | |
function latin1Slice (buf, start, end) { | |
var ret = '' | |
end = Math.min(buf.length, end) | |
for (var i = start; i < end; ++i) { | |
ret += String.fromCharCode(buf[i]) | |
} | |
return ret | |
} | |
function hexSlice (buf, start, end) { | |
var len = buf.length | |
if (!start || start < 0) start = 0 | |
if (!end || end < 0 || end > len) end = len | |
var out = '' | |
for (var i = start; i < end; ++i) { | |
out += toHex(buf[i]) | |
} | |
return out | |
} | |
function utf16leSlice (buf, start, end) { | |
var bytes = buf.slice(start, end) | |
var res = '' | |
for (var i = 0; i < bytes.length; i += 2) { | |
res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) | |
} | |
return res | |
} | |
Buffer.prototype.slice = function slice (start, end) { | |
var len = this.length | |
start = ~~start | |
end = end === undefined ? len : ~~end | |
if (start < 0) { | |
start += len | |
if (start < 0) start = 0 | |
} else if (start > len) { | |
start = len | |
} | |
if (end < 0) { | |
end += len | |
if (end < 0) end = 0 | |
} else if (end > len) { | |
end = len | |
} | |
if (end < start) end = start | |
var newBuf = this.subarray(start, end) | |
// Return an augmented `Uint8Array` instance | |
newBuf.__proto__ = Buffer.prototype | |
return newBuf | |
} | |
/* | |
* Need to make sure that buffer isn't trying to write out of bounds. | |
*/ | |
function checkOffset (offset, ext, length) { | |
if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') | |
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') | |
} | |
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var val = this[offset] | |
var mul = 1 | |
var i = 0 | |
while (++i < byteLength && (mul *= 0x100)) { | |
val += this[offset + i] * mul | |
} | |
return val | |
} | |
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) { | |
checkOffset(offset, byteLength, this.length) | |
} | |
var val = this[offset + --byteLength] | |
var mul = 1 | |
while (byteLength > 0 && (mul *= 0x100)) { | |
val += this[offset + --byteLength] * mul | |
} | |
return val | |
} | |
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 1, this.length) | |
return this[offset] | |
} | |
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
return this[offset] | (this[offset + 1] << 8) | |
} | |
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
return (this[offset] << 8) | this[offset + 1] | |
} | |
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ((this[offset]) | | |
(this[offset + 1] << 8) | | |
(this[offset + 2] << 16)) + | |
(this[offset + 3] * 0x1000000) | |
} | |
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset] * 0x1000000) + | |
((this[offset + 1] << 16) | | |
(this[offset + 2] << 8) | | |
this[offset + 3]) | |
} | |
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var val = this[offset] | |
var mul = 1 | |
var i = 0 | |
while (++i < byteLength && (mul *= 0x100)) { | |
val += this[offset + i] * mul | |
} | |
mul *= 0x80 | |
if (val >= mul) val -= Math.pow(2, 8 * byteLength) | |
return val | |
} | |
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) checkOffset(offset, byteLength, this.length) | |
var i = byteLength | |
var mul = 1 | |
var val = this[offset + --i] | |
while (i > 0 && (mul *= 0x100)) { | |
val += this[offset + --i] * mul | |
} | |
mul *= 0x80 | |
if (val >= mul) val -= Math.pow(2, 8 * byteLength) | |
return val | |
} | |
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 1, this.length) | |
if (!(this[offset] & 0x80)) return (this[offset]) | |
return ((0xff - this[offset] + 1) * -1) | |
} | |
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
var val = this[offset] | (this[offset + 1] << 8) | |
return (val & 0x8000) ? val | 0xFFFF0000 : val | |
} | |
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 2, this.length) | |
var val = this[offset + 1] | (this[offset] << 8) | |
return (val & 0x8000) ? val | 0xFFFF0000 : val | |
} | |
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset]) | | |
(this[offset + 1] << 8) | | |
(this[offset + 2] << 16) | | |
(this[offset + 3] << 24) | |
} | |
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return (this[offset] << 24) | | |
(this[offset + 1] << 16) | | |
(this[offset + 2] << 8) | | |
(this[offset + 3]) | |
} | |
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ieee754.read(this, offset, true, 23, 4) | |
} | |
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 4, this.length) | |
return ieee754.read(this, offset, false, 23, 4) | |
} | |
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 8, this.length) | |
return ieee754.read(this, offset, true, 52, 8) | |
} | |
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { | |
offset = offset >>> 0 | |
if (!noAssert) checkOffset(offset, 8, this.length) | |
return ieee754.read(this, offset, false, 52, 8) | |
} | |
function checkInt (buf, value, offset, ext, max, min) { | |
if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') | |
if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') | |
if (offset + ext > buf.length) throw new RangeError('Index out of range') | |
} | |
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) { | |
var maxBytes = Math.pow(2, 8 * byteLength) - 1 | |
checkInt(this, value, offset, byteLength, maxBytes, 0) | |
} | |
var mul = 1 | |
var i = 0 | |
this[offset] = value & 0xFF | |
while (++i < byteLength && (mul *= 0x100)) { | |
this[offset + i] = (value / mul) & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
byteLength = byteLength >>> 0 | |
if (!noAssert) { | |
var maxBytes = Math.pow(2, 8 * byteLength) - 1 | |
checkInt(this, value, offset, byteLength, maxBytes, 0) | |
} | |
var i = byteLength - 1 | |
var mul = 1 | |
this[offset + i] = value & 0xFF | |
while (--i >= 0 && (mul *= 0x100)) { | |
this[offset + i] = (value / mul) & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) | |
this[offset] = (value & 0xff) | |
return offset + 1 | |
} | |
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
return offset + 2 | |
} | |
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) | |
this[offset] = (value >>> 8) | |
this[offset + 1] = (value & 0xff) | |
return offset + 2 | |
} | |
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) | |
this[offset + 3] = (value >>> 24) | |
this[offset + 2] = (value >>> 16) | |
this[offset + 1] = (value >>> 8) | |
this[offset] = (value & 0xff) | |
return offset + 4 | |
} | |
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) | |
this[offset] = (value >>> 24) | |
this[offset + 1] = (value >>> 16) | |
this[offset + 2] = (value >>> 8) | |
this[offset + 3] = (value & 0xff) | |
return offset + 4 | |
} | |
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) { | |
var limit = Math.pow(2, (8 * byteLength) - 1) | |
checkInt(this, value, offset, byteLength, limit - 1, -limit) | |
} | |
var i = 0 | |
var mul = 1 | |
var sub = 0 | |
this[offset] = value & 0xFF | |
while (++i < byteLength && (mul *= 0x100)) { | |
if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { | |
sub = 1 | |
} | |
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) { | |
var limit = Math.pow(2, (8 * byteLength) - 1) | |
checkInt(this, value, offset, byteLength, limit - 1, -limit) | |
} | |
var i = byteLength - 1 | |
var mul = 1 | |
var sub = 0 | |
this[offset + i] = value & 0xFF | |
while (--i >= 0 && (mul *= 0x100)) { | |
if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { | |
sub = 1 | |
} | |
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF | |
} | |
return offset + byteLength | |
} | |
Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) | |
if (value < 0) value = 0xff + value + 1 | |
this[offset] = (value & 0xff) | |
return offset + 1 | |
} | |
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
return offset + 2 | |
} | |
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) | |
this[offset] = (value >>> 8) | |
this[offset + 1] = (value & 0xff) | |
return offset + 2 | |
} | |
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) | |
this[offset] = (value & 0xff) | |
this[offset + 1] = (value >>> 8) | |
this[offset + 2] = (value >>> 16) | |
this[offset + 3] = (value >>> 24) | |
return offset + 4 | |
} | |
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) | |
if (value < 0) value = 0xffffffff + value + 1 | |
this[offset] = (value >>> 24) | |
this[offset + 1] = (value >>> 16) | |
this[offset + 2] = (value >>> 8) | |
this[offset + 3] = (value & 0xff) | |
return offset + 4 | |
} | |
function checkIEEE754 (buf, value, offset, ext, max, min) { | |
if (offset + ext > buf.length) throw new RangeError('Index out of range') | |
if (offset < 0) throw new RangeError('Index out of range') | |
} | |
function writeFloat (buf, value, offset, littleEndian, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) { | |
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) | |
} | |
ieee754.write(buf, value, offset, littleEndian, 23, 4) | |
return offset + 4 | |
} | |
Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { | |
return writeFloat(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { | |
return writeFloat(this, value, offset, false, noAssert) | |
} | |
function writeDouble (buf, value, offset, littleEndian, noAssert) { | |
value = +value | |
offset = offset >>> 0 | |
if (!noAssert) { | |
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) | |
} | |
ieee754.write(buf, value, offset, littleEndian, 52, 8) | |
return offset + 8 | |
} | |
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { | |
return writeDouble(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { | |
return writeDouble(this, value, offset, false, noAssert) | |
} | |
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) | |
Buffer.prototype.copy = function copy (target, targetStart, start, end) { | |
if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') | |
if (!start) start = 0 | |
if (!end && end !== 0) end = this.length | |
if (targetStart >= target.length) targetStart = target.length | |
if (!targetStart) targetStart = 0 | |
if (end > 0 && end < start) end = start | |
// Copy 0 bytes; we're done | |
if (end === start) return 0 | |
if (target.length === 0 || this.length === 0) return 0 | |
// Fatal error conditions | |
if (targetStart < 0) { | |
throw new RangeError('targetStart out of bounds') | |
} | |
if (start < 0 || start >= this.length) throw new RangeError('Index out of range') | |
if (end < 0) throw new RangeError('sourceEnd out of bounds') | |
// Are we oob? | |
if (end > this.length) end = this.length | |
if (target.length - targetStart < end - start) { | |
end = target.length - targetStart + start | |
} | |
var len = end - start | |
if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { | |
// Use built-in when available, missing from IE11 | |
this.copyWithin(targetStart, start, end) | |
} else if (this === target && start < targetStart && targetStart < end) { | |
// descending copy from end | |
for (var i = len - 1; i >= 0; --i) { | |
target[i + targetStart] = this[i + start] | |
} | |
} else { | |
Uint8Array.prototype.set.call( | |
target, | |
this.subarray(start, end), | |
targetStart | |
) | |
} | |
return len | |
} | |
// Usage: | |
// buffer.fill(number[, offset[, end]]) | |
// buffer.fill(buffer[, offset[, end]]) | |
// buffer.fill(string[, offset[, end]][, encoding]) | |
Buffer.prototype.fill = function fill (val, start, end, encoding) { | |
// Handle string cases: | |
if (typeof val === 'string') { | |
if (typeof start === 'string') { | |
encoding = start | |
start = 0 | |
end = this.length | |
} else if (typeof end === 'string') { | |
encoding = end | |
end = this.length | |
} | |
if (encoding !== undefined && typeof encoding !== 'string') { | |
throw new TypeError('encoding must be a string') | |
} | |
if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { | |
throw new TypeError('Unknown encoding: ' + encoding) | |
} | |
if (val.length === 1) { | |
var code = val.charCodeAt(0) | |
if ((encoding === 'utf8' && code < 128) || | |
encoding === 'latin1') { | |
// Fast path: If `val` fits into a single byte, use that numeric value. | |
val = code | |
} | |
} | |
} else if (typeof val === 'number') { | |
val = val & 255 | |
} | |
// Invalid ranges are not set to a default, so can range check early. | |
if (start < 0 || this.length < start || this.length < end) { | |
throw new RangeError('Out of range index') | |
} | |
if (end <= start) { | |
return this | |
} | |
start = start >>> 0 | |
end = end === undefined ? this.length : end >>> 0 | |
if (!val) val = 0 | |
var i | |
if (typeof val === 'number') { | |
for (i = start; i < end; ++i) { | |
this[i] = val | |
} | |
} else { | |
var bytes = Buffer.isBuffer(val) | |
? val | |
: Buffer.from(val, encoding) | |
var len = bytes.length | |
if (len === 0) { | |
throw new TypeError('The value "' + val + | |
'" is invalid for argument "value"') | |
} | |
for (i = 0; i < end - start; ++i) { | |
this[i + start] = bytes[i % len] | |
} | |
} | |
return this | |
} | |
// HELPER FUNCTIONS | |
// ================ | |
var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g | |
function base64clean (str) { | |
// Node takes equal signs as end of the Base64 encoding | |
str = str.split('=')[0] | |
// Node strips out invalid characters like \n and \t from the string, base64-js does not | |
str = str.trim().replace(INVALID_BASE64_RE, '') | |
// Node converts strings with length < 2 to '' | |
if (str.length < 2) return '' | |
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not | |
while (str.length % 4 !== 0) { | |
str = str + '=' | |
} | |
return str | |
} | |
function toHex (n) { | |
if (n < 16) return '0' + n.toString(16) | |
return n.toString(16) | |
} | |
function utf8ToBytes (string, units) { | |
units = units || Infinity | |
var codePoint | |
var length = string.length | |
var leadSurrogate = null | |
var bytes = [] | |
for (var i = 0; i < length; ++i) { | |
codePoint = string.charCodeAt(i) | |
// is surrogate component | |
if (codePoint > 0xD7FF && codePoint < 0xE000) { | |
// last char was a lead | |
if (!leadSurrogate) { | |
// no lead yet | |
if (codePoint > 0xDBFF) { | |
// unexpected trail | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
continue | |
} else if (i + 1 === length) { | |
// unpaired lead | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
continue | |
} | |
// valid lead | |
leadSurrogate = codePoint | |
continue | |
} | |
// 2 leads in a row | |
if (codePoint < 0xDC00) { | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
leadSurrogate = codePoint | |
continue | |
} | |
// valid surrogate pair | |
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 | |
} else if (leadSurrogate) { | |
// valid bmp char, but last char was a lead | |
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) | |
} | |
leadSurrogate = null | |
// encode utf8 | |
if (codePoint < 0x80) { | |
if ((units -= 1) < 0) break | |
bytes.push(codePoint) | |
} else if (codePoint < 0x800) { | |
if ((units -= 2) < 0) break | |
bytes.push( | |
codePoint >> 0x6 | 0xC0, | |
codePoint & 0x3F | 0x80 | |
) | |
} else if (codePoint < 0x10000) { | |
if ((units -= 3) < 0) break | |
bytes.push( | |
codePoint >> 0xC | 0xE0, | |
codePoint >> 0x6 & 0x3F | 0x80, | |
codePoint & 0x3F | 0x80 | |
) | |
} else if (codePoint < 0x110000) { | |
if ((units -= 4) < 0) break | |
bytes.push( | |
codePoint >> 0x12 | 0xF0, | |
codePoint >> 0xC & 0x3F | 0x80, | |
codePoint >> 0x6 & 0x3F | 0x80, | |
codePoint & 0x3F | 0x80 | |
) | |
} else { | |
throw new Error('Invalid code point') | |
} | |
} | |
return bytes | |
} | |
function asciiToBytes (str) { | |
var byteArray = [] | |
for (var i = 0; i < str.length; ++i) { | |
// Node's code seems to be doing this and not & 0x7F.. | |
byteArray.push(str.charCodeAt(i) & 0xFF) | |
} | |
return byteArray | |
} | |
function utf16leToBytes (str, units) { | |
var c, hi, lo | |
var byteArray = [] | |
for (var i = 0; i < str.length; ++i) { | |
if ((units -= 2) < 0) break | |
c = str.charCodeAt(i) | |
hi = c >> 8 | |
lo = c % 256 | |
byteArray.push(lo) | |
byteArray.push(hi) | |
} | |
return byteArray | |
} | |
function base64ToBytes (str) { | |
return base64.toByteArray(base64clean(str)) | |
} | |
function blitBuffer (src, dst, offset, length) { | |
for (var i = 0; i < length; ++i) { | |
if ((i + offset >= dst.length) || (i >= src.length)) break | |
dst[i + offset] = src[i] | |
} | |
return i | |
} | |
// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass | |
// the `instanceof` check but they should be treated as of that type. | |
// See: https://github.com/feross/buffer/issues/166 | |
function isInstance (obj, type) { | |
return obj instanceof type || | |
(obj != null && obj.constructor != null && obj.constructor.name != null && | |
obj.constructor.name === type.name) | |
} | |
function numberIsNaN (obj) { | |
// For IE11 support | |
return obj !== obj // eslint-disable-line no-self-compare | |
} | |
}).call(this)}).call(this,require("buffer").Buffer) | |
},{"base64-js":47,"buffer":48,"ieee754":59}],49:[function(require,module,exports){ | |
'use strict'; | |
/* globals | |
Atomics, | |
SharedArrayBuffer, | |
*/ | |
var undefined; | |
var $TypeError = TypeError; | |
var $gOPD = Object.getOwnPropertyDescriptor; | |
if ($gOPD) { | |
try { | |
$gOPD({}, ''); | |
} catch (e) { | |
$gOPD = null; // this is IE 8, which has a broken gOPD | |
} | |
} | |
var throwTypeError = function () { throw new $TypeError(); }; | |
var ThrowTypeError = $gOPD | |
? (function () { | |
try { | |
// eslint-disable-next-line no-unused-expressions, no-caller, no-restricted-properties | |
arguments.callee; // IE 8 does not throw here | |
return throwTypeError; | |
} catch (calleeThrows) { | |
try { | |
// IE 8 throws on Object.getOwnPropertyDescriptor(arguments, '') | |
return $gOPD(arguments, 'callee').get; | |
} catch (gOPDthrows) { | |
return throwTypeError; | |
} | |
} | |
}()) | |
: throwTypeError; | |
var hasSymbols = require('has-symbols')(); | |
var getProto = Object.getPrototypeOf || function (x) { return x.__proto__; }; // eslint-disable-line no-proto | |
var generator; // = function * () {}; | |
var generatorFunction = generator ? getProto(generator) : undefined; | |
var asyncFn; // async function() {}; | |
var asyncFunction = asyncFn ? asyncFn.constructor : undefined; | |
var asyncGen; // async function * () {}; | |
var asyncGenFunction = asyncGen ? getProto(asyncGen) : undefined; | |
var asyncGenIterator = asyncGen ? asyncGen() : undefined; | |
var TypedArray = typeof Uint8Array === 'undefined' ? undefined : getProto(Uint8Array); | |
var INTRINSICS = { | |
'%Array%': Array, | |
'%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer, | |
'%ArrayBufferPrototype%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer.prototype, | |
'%ArrayIteratorPrototype%': hasSymbols ? getProto([][Symbol.iterator]()) : undefined, | |
'%ArrayPrototype%': Array.prototype, | |
'%ArrayProto_entries%': Array.prototype.entries, | |
'%ArrayProto_forEach%': Array.prototype.forEach, | |
'%ArrayProto_keys%': Array.prototype.keys, | |
'%ArrayProto_values%': Array.prototype.values, | |
'%AsyncFromSyncIteratorPrototype%': undefined, | |
'%AsyncFunction%': asyncFunction, | |
'%AsyncFunctionPrototype%': asyncFunction ? asyncFunction.prototype : undefined, | |
'%AsyncGenerator%': asyncGen ? getProto(asyncGenIterator) : undefined, | |
'%AsyncGeneratorFunction%': asyncGenFunction, | |
'%AsyncGeneratorPrototype%': asyncGenFunction ? asyncGenFunction.prototype : undefined, | |
'%AsyncIteratorPrototype%': asyncGenIterator && hasSymbols && Symbol.asyncIterator ? asyncGenIterator[Symbol.asyncIterator]() : undefined, | |
'%Atomics%': typeof Atomics === 'undefined' ? undefined : Atomics, | |
'%Boolean%': Boolean, | |
'%BooleanPrototype%': Boolean.prototype, | |
'%DataView%': typeof DataView === 'undefined' ? undefined : DataView, | |
'%DataViewPrototype%': typeof DataView === 'undefined' ? undefined : DataView.prototype, | |
'%Date%': Date, | |
'%DatePrototype%': Date.prototype, | |
'%decodeURI%': decodeURI, | |
'%decodeURIComponent%': decodeURIComponent, | |
'%encodeURI%': encodeURI, | |
'%encodeURIComponent%': encodeURIComponent, | |
'%Error%': Error, | |
'%ErrorPrototype%': Error.prototype, | |
'%eval%': eval, // eslint-disable-line no-eval | |
'%EvalError%': EvalError, | |
'%EvalErrorPrototype%': EvalError.prototype, | |
'%Float32Array%': typeof Float32Array === 'undefined' ? undefined : Float32Array, | |
'%Float32ArrayPrototype%': typeof Float32Array === 'undefined' ? undefined : Float32Array.prototype, | |
'%Float64Array%': typeof Float64Array === 'undefined' ? undefined : Float64Array, | |
'%Float64ArrayPrototype%': typeof Float64Array === 'undefined' ? undefined : Float64Array.prototype, | |
'%Function%': Function, | |
'%FunctionPrototype%': Function.prototype, | |
'%Generator%': generator ? getProto(generator()) : undefined, | |
'%GeneratorFunction%': generatorFunction, | |
'%GeneratorPrototype%': generatorFunction ? generatorFunction.prototype : undefined, | |
'%Int8Array%': typeof Int8Array === 'undefined' ? undefined : Int8Array, | |
'%Int8ArrayPrototype%': typeof Int8Array === 'undefined' ? undefined : Int8Array.prototype, | |
'%Int16Array%': typeof Int16Array === 'undefined' ? undefined : Int16Array, | |
'%Int16ArrayPrototype%': typeof Int16Array === 'undefined' ? undefined : Int8Array.prototype, | |
'%Int32Array%': typeof Int32Array === 'undefined' ? undefined : Int32Array, | |
'%Int32ArrayPrototype%': typeof Int32Array === 'undefined' ? undefined : Int32Array.prototype, | |
'%isFinite%': isFinite, | |
'%isNaN%': isNaN, | |
'%IteratorPrototype%': hasSymbols ? getProto(getProto([][Symbol.iterator]())) : undefined, | |
'%JSON%': typeof JSON === 'object' ? JSON : undefined, | |
'%JSONParse%': typeof JSON === 'object' ? JSON.parse : undefined, | |
'%Map%': typeof Map === 'undefined' ? undefined : Map, | |
'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols ? undefined : getProto(new Map()[Symbol.iterator]()), | |
'%MapPrototype%': typeof Map === 'undefined' ? undefined : Map.prototype, | |
'%Math%': Math, | |
'%Number%': Number, | |
'%NumberPrototype%': Number.prototype, | |
'%Object%': Object, | |
'%ObjectPrototype%': Object.prototype, | |
'%ObjProto_toString%': Object.prototype.toString, | |
'%ObjProto_valueOf%': Object.prototype.valueOf, | |
'%parseFloat%': parseFloat, | |
'%parseInt%': parseInt, | |
'%Promise%': typeof Promise === 'undefined' ? undefined : Promise, | |
'%PromisePrototype%': typeof Promise === 'undefined' ? undefined : Promise.prototype, | |
'%PromiseProto_then%': typeof Promise === 'undefined' ? undefined : Promise.prototype.then, | |
'%Promise_all%': typeof Promise === 'undefined' ? undefined : Promise.all, | |
'%Promise_reject%': typeof Promise === 'undefined' ? undefined : Promise.reject, | |
'%Promise_resolve%': typeof Promise === 'undefined' ? undefined : Promise.resolve, | |
'%Proxy%': typeof Proxy === 'undefined' ? undefined : Proxy, | |
'%RangeError%': RangeError, | |
'%RangeErrorPrototype%': RangeError.prototype, | |
'%ReferenceError%': ReferenceError, | |
'%ReferenceErrorPrototype%': ReferenceError.prototype, | |
'%Reflect%': typeof Reflect === 'undefined' ? undefined : Reflect, | |
'%RegExp%': RegExp, | |
'%RegExpPrototype%': RegExp.prototype, | |
'%Set%': typeof Set === 'undefined' ? undefined : Set, | |
'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols ? undefined : getProto(new Set()[Symbol.iterator]()), | |
'%SetPrototype%': typeof Set === 'undefined' ? undefined : Set.prototype, | |
'%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer, | |
'%SharedArrayBufferPrototype%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer.prototype, | |
'%String%': String, | |
'%StringIteratorPrototype%': hasSymbols ? getProto(''[Symbol.iterator]()) : undefined, | |
'%StringPrototype%': String.prototype, | |
'%Symbol%': hasSymbols ? Symbol : undefined, | |
'%SymbolPrototype%': hasSymbols ? Symbol.prototype : undefined, | |
'%SyntaxError%': SyntaxError, | |
'%SyntaxErrorPrototype%': SyntaxError.prototype, | |
'%ThrowTypeError%': ThrowTypeError, | |
'%TypedArray%': TypedArray, | |
'%TypedArrayPrototype%': TypedArray ? TypedArray.prototype : undefined, | |
'%TypeError%': $TypeError, | |
'%TypeErrorPrototype%': $TypeError.prototype, | |
'%Uint8Array%': typeof Uint8Array === 'undefined' ? undefined : Uint8Array, | |
'%Uint8ArrayPrototype%': typeof Uint8Array === 'undefined' ? undefined : Uint8Array.prototype, | |
'%Uint8ClampedArray%': typeof Uint8ClampedArray === 'undefined' ? undefined : Uint8ClampedArray, | |
'%Uint8ClampedArrayPrototype%': typeof Uint8ClampedArray === 'undefined' ? undefined : Uint8ClampedArray.prototype, | |
'%Uint16Array%': typeof Uint16Array === 'undefined' ? undefined : Uint16Array, | |
'%Uint16ArrayPrototype%': typeof Uint16Array === 'undefined' ? undefined : Uint16Array.prototype, | |
'%Uint32Array%': typeof Uint32Array === 'undefined' ? undefined : Uint32Array, | |
'%Uint32ArrayPrototype%': typeof Uint32Array === 'undefined' ? undefined : Uint32Array.prototype, | |
'%URIError%': URIError, | |
'%URIErrorPrototype%': URIError.prototype, | |
'%WeakMap%': typeof WeakMap === 'undefined' ? undefined : WeakMap, | |
'%WeakMapPrototype%': typeof WeakMap === 'undefined' ? undefined : WeakMap.prototype, | |
'%WeakSet%': typeof WeakSet === 'undefined' ? undefined : WeakSet, | |
'%WeakSetPrototype%': typeof WeakSet === 'undefined' ? undefined : WeakSet.prototype | |
}; | |
var bind = require('function-bind'); | |
var $replace = bind.call(Function.call, String.prototype.replace); | |
/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */ | |
var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g; | |
var reEscapeChar = /\\(\\)?/g; /** Used to match backslashes in property paths. */ | |
var stringToPath = function stringToPath(string) { | |
var result = []; | |
$replace(string, rePropName, function (match, number, quote, subString) { | |
result[result.length] = quote ? $replace(subString, reEscapeChar, '$1') : (number || match); | |
}); | |
return result; | |
}; | |
/* end adaptation */ | |
var getBaseIntrinsic = function getBaseIntrinsic(name, allowMissing) { | |
if (!(name in INTRINSICS)) { | |
throw new SyntaxError('intrinsic ' + name + ' does not exist!'); | |
} | |
// istanbul ignore if // hopefully this is impossible to test :-) | |
if (typeof INTRINSICS[name] === 'undefined' && !allowMissing) { | |
throw new $TypeError('intrinsic ' + name + ' exists, but is not available. Please file an issue!'); | |
} | |
return INTRINSICS[name]; | |
}; | |
module.exports = function GetIntrinsic(name, allowMissing) { | |
if (typeof name !== 'string' || name.length === 0) { | |
throw new TypeError('intrinsic name must be a non-empty string'); | |
} | |
if (arguments.length > 1 && typeof allowMissing !== 'boolean') { | |
throw new TypeError('"allowMissing" argument must be a boolean'); | |
} | |
var parts = stringToPath(name); | |
var value = getBaseIntrinsic('%' + (parts.length > 0 ? parts[0] : '') + '%', allowMissing); | |
for (var i = 1; i < parts.length; i += 1) { | |
if (value != null) { | |
if ($gOPD && (i + 1) >= parts.length) { | |
var desc = $gOPD(value, parts[i]); | |
if (!allowMissing && !(parts[i] in value)) { | |
throw new $TypeError('base intrinsic for ' + name + ' exists, but the property is not available.'); | |
} | |
// By convention, when a data property is converted to an accessor | |
// property to emulate a data property that does not suffer from | |
// the override mistake, that accessor's getter is marked with | |
// an `originalValue` property. Here, when we detect this, we | |
// uphold the illusion by pretending to see that original data | |
// property, i.e., returning the value rather than the getter | |
// itself. | |
value = desc && 'get' in desc && !('originalValue' in desc.get) ? desc.get : value[parts[i]]; | |
} else { | |
value = value[parts[i]]; | |
} | |
} | |
} | |
return value; | |
}; | |
},{"function-bind":56,"has-symbols":57}],50:[function(require,module,exports){ | |
'use strict'; | |
var bind = require('function-bind'); | |
var GetIntrinsic = require('../GetIntrinsic'); | |
var $apply = GetIntrinsic('%Function.prototype.apply%'); | |
var $call = GetIntrinsic('%Function.prototype.call%'); | |
var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply); | |
var $defineProperty = GetIntrinsic('%Object.defineProperty%', true); | |
if ($defineProperty) { | |
try { | |
$defineProperty({}, 'a', { value: 1 }); | |
} catch (e) { | |
// IE 8 has a broken defineProperty | |
$defineProperty = null; | |
} | |
} | |
module.exports = function callBind() { | |
return $reflectApply(bind, $call, arguments); | |
}; | |
var applyBind = function applyBind() { | |
return $reflectApply(bind, $apply, arguments); | |
}; | |
if ($defineProperty) { | |
$defineProperty(module.exports, 'apply', { value: applyBind }); | |
} else { | |
module.exports.apply = applyBind; | |
} | |
},{"../GetIntrinsic":49,"function-bind":56}],51:[function(require,module,exports){ | |
'use strict'; | |
var GetIntrinsic = require('../GetIntrinsic'); | |
var callBind = require('./callBind'); | |
var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf')); | |
module.exports = function callBoundIntrinsic(name, allowMissing) { | |
var intrinsic = GetIntrinsic(name, !!allowMissing); | |
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.')) { | |
return callBind(intrinsic); | |
} | |
return intrinsic; | |
}; | |
},{"../GetIntrinsic":49,"./callBind":50}],52:[function(require,module,exports){ | |
'use strict'; | |
var GetIntrinsic = require('../GetIntrinsic'); | |
var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%'); | |
if ($gOPD) { | |
try { | |
$gOPD([], 'length'); | |
} catch (e) { | |
// IE 8 has a broken gOPD | |
$gOPD = null; | |
} | |
} | |
module.exports = $gOPD; | |
},{"../GetIntrinsic":49}],53:[function(require,module,exports){ | |
// Copyright Joyent, Inc. and other Node 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. | |
'use strict'; | |
var R = typeof Reflect === 'object' ? Reflect : null | |
var ReflectApply = R && typeof R.apply === 'function' | |
? R.apply | |
: function ReflectApply(target, receiver, args) { | |
return Function.prototype.apply.call(target, receiver, args); | |
} | |
var ReflectOwnKeys | |
if (R && typeof R.ownKeys === 'function') { | |
ReflectOwnKeys = R.ownKeys | |
} else if (Object.getOwnPropertySymbols) { | |
ReflectOwnKeys = function ReflectOwnKeys(target) { | |
return Object.getOwnPropertyNames(target) | |
.concat(Object.getOwnPropertySymbols(target)); | |
}; | |
} else { | |
ReflectOwnKeys = function ReflectOwnKeys(target) { | |
return Object.getOwnPropertyNames(target); | |
}; | |
} | |
function ProcessEmitWarning(warning) { | |
if (console && console.warn) console.warn(warning); | |
} | |
var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { | |
return value !== value; | |
} | |
function EventEmitter() { | |
EventEmitter.init.call(this); | |
} | |
module.exports = EventEmitter; | |
module.exports.once = once; | |
// Backwards-compat with node 0.10.x | |
EventEmitter.EventEmitter = EventEmitter; | |
EventEmitter.prototype._events = undefined; | |
EventEmitter.prototype._eventsCount = 0; | |
EventEmitter.prototype._maxListeners = undefined; | |
// By default EventEmitters will print a warning if more than 10 listeners are | |
// added to it. This is a useful default which helps finding memory leaks. | |
var defaultMaxListeners = 10; | |
function checkListener(listener) { | |
if (typeof listener !== 'function') { | |
throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); | |
} | |
} | |
Object.defineProperty(EventEmitter, 'defaultMaxListeners', { | |
enumerable: true, | |
get: function() { | |
return defaultMaxListeners; | |
}, | |
set: function(arg) { | |
if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { | |
throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); | |
} | |
defaultMaxListeners = arg; | |
} | |
}); | |
EventEmitter.init = function() { | |
if (this._events === undefined || | |
this._events === Object.getPrototypeOf(this)._events) { | |
this._events = Object.create(null); | |
this._eventsCount = 0; | |
} | |
this._maxListeners = this._maxListeners || undefined; | |
}; | |
// Obviously not all Emitters should be limited to 10. This function allows | |
// that to be increased. Set to zero for unlimited. | |
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { | |
if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { | |
throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); | |
} | |
this._maxListeners = n; | |
return this; | |
}; | |
function _getMaxListeners(that) { | |
if (that._maxListeners === undefined) | |
return EventEmitter.defaultMaxListeners; | |
return that._maxListeners; | |
} | |
EventEmitter.prototype.getMaxListeners = function getMaxListeners() { | |
return _getMaxListeners(this); | |
}; | |
EventEmitter.prototype.emit = function emit(type) { | |
var args = []; | |
for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); | |
var doError = (type === 'error'); | |
var events = this._events; | |
if (events !== undefined) | |
doError = (doError && events.error === undefined); | |
else if (!doError) | |
return false; | |
// If there is no 'error' event listener then throw. | |
if (doError) { | |
var er; | |
if (args.length > 0) | |
er = args[0]; | |
if (er instanceof Error) { | |
// Note: The comments on the `throw` lines are intentional, they show | |
// up in Node's output if this results in an unhandled exception. | |
throw er; // Unhandled 'error' event | |
} | |
// At least give some kind of context to the user | |
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); | |
err.context = er; | |
throw err; // Unhandled 'error' event | |
} | |
var handler = events[type]; | |
if (handler === undefined) | |
return false; | |
if (typeof handler === 'function') { | |
ReflectApply(handler, this, args); | |
} else { | |
var len = handler.length; | |
var listeners = arrayClone(handler, len); | |
for (var i = 0; i < len; ++i) | |
ReflectApply(listeners[i], this, args); | |
} | |
return true; | |
}; | |
function _addListener(target, type, listener, prepend) { | |
var m; | |
var events; | |
var existing; | |
checkListener(listener); | |
events = target._events; | |
if (events === undefined) { | |
events = target._events = Object.create(null); | |
target._eventsCount = 0; | |
} else { | |
// To avoid recursion in the case that type === "newListener"! Before | |
// adding it to the listeners, first emit "newListener". | |
if (events.newListener !== undefined) { | |
target.emit('newListener', type, | |
listener.listener ? listener.listener : listener); | |
// Re-assign `events` because a newListener handler could have caused the | |
// this._events to be assigned to a new object | |
events = target._events; | |
} | |
existing = events[type]; | |
} | |
if (existing === undefined) { | |
// Optimize the case of one listener. Don't need the extra array object. | |
existing = events[type] = listener; | |
++target._eventsCount; | |
} else { | |
if (typeof existing === 'function') { | |
// Adding the second element, need to change to array. | |
existing = events[type] = | |
prepend ? [listener, existing] : [existing, listener]; | |
// If we've already got an array, just append. | |
} else if (prepend) { | |
existing.unshift(listener); | |
} else { | |
existing.push(listener); | |
} | |
// Check for listener leak | |
m = _getMaxListeners(target); | |
if (m > 0 && existing.length > m && !existing.warned) { | |
existing.warned = true; | |
// No error code for this since it is a Warning | |
// eslint-disable-next-line no-restricted-syntax | |
var w = new Error('Possible EventEmitter memory leak detected. ' + | |
existing.length + ' ' + String(type) + ' listeners ' + | |
'added. Use emitter.setMaxListeners() to ' + | |
'increase limit'); | |
w.name = 'MaxListenersExceededWarning'; | |
w.emitter = target; | |
w.type = type; | |
w.count = existing.length; | |
ProcessEmitWarning(w); | |
} | |
} | |
return target; | |
} | |
EventEmitter.prototype.addListener = function addListener(type, listener) { | |
return _addListener(this, type, listener, false); | |
}; | |
EventEmitter.prototype.on = EventEmitter.prototype.addListener; | |
EventEmitter.prototype.prependListener = | |
function prependListener(type, listener) { | |
return _addListener(this, type, listener, true); | |
}; | |
function onceWrapper() { | |
if (!this.fired) { | |
this.target.removeListener(this.type, this.wrapFn); | |
this.fired = true; | |
if (arguments.length === 0) | |
return this.listener.call(this.target); | |
return this.listener.apply(this.target, arguments); | |
} | |
} | |
function _onceWrap(target, type, listener) { | |
var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; | |
var wrapped = onceWrapper.bind(state); | |
wrapped.listener = listener; | |
state.wrapFn = wrapped; | |
return wrapped; | |
} | |
EventEmitter.prototype.once = function once(type, listener) { | |
checkListener(listener); | |
this.on(type, _onceWrap(this, type, listener)); | |
return this; | |
}; | |
EventEmitter.prototype.prependOnceListener = | |
function prependOnceListener(type, listener) { | |
checkListener(listener); | |
this.prependListener(type, _onceWrap(this, type, listener)); | |
return this; | |
}; | |
// Emits a 'removeListener' event if and only if the listener was removed. | |
EventEmitter.prototype.removeListener = | |
function removeListener(type, listener) { | |
var list, events, position, i, originalListener; | |
checkListener(listener); | |
events = this._events; | |
if (events === undefined) | |
return this; | |
list = events[type]; | |
if (list === undefined) | |
return this; | |
if (list === listener || list.listener === listener) { | |
if (--this._eventsCount === 0) | |
this._events = Object.create(null); | |
else { | |
delete events[type]; | |
if (events.removeListener) | |
this.emit('removeListener', type, list.listener || listener); | |
} | |
} else if (typeof list !== 'function') { | |
position = -1; | |
for (i = list.length - 1; i >= 0; i--) { | |
if (list[i] === listener || list[i].listener === listener) { | |
originalListener = list[i].listener; | |
position = i; | |
break; | |
} | |
} | |
if (position < 0) | |
return this; | |
if (position === 0) | |
list.shift(); | |
else { | |
spliceOne(list, position); | |
} | |
if (list.length === 1) | |
events[type] = list[0]; | |
if (events.removeListener !== undefined) | |
this.emit('removeListener', type, originalListener || listener); | |
} | |
return this; | |
}; | |
EventEmitter.prototype.off = EventEmitter.prototype.removeListener; | |
EventEmitter.prototype.removeAllListeners = | |
function removeAllListeners(type) { | |
var listeners, events, i; | |
events = this._events; | |
if (events === undefined) | |
return this; | |
// not listening for removeListener, no need to emit | |
if (events.removeListener === undefined) { | |
if (arguments.length === 0) { | |
this._events = Object.create(null); | |
this._eventsCount = 0; | |
} else if (events[type] !== undefined) { | |
if (--this._eventsCount === 0) | |
this._events = Object.create(null); | |
else | |
delete events[type]; | |
} | |
return this; | |
} | |
// emit removeListener for all listeners on all events | |
if (arguments.length === 0) { | |
var keys = Object.keys(events); | |
var key; | |
for (i = 0; i < keys.length; ++i) { | |
key = keys[i]; | |
if (key === 'removeListener') continue; | |
this.removeAllListeners(key); | |
} | |
this.removeAllListeners('removeListener'); | |
this._events = Object.create(null); | |
this._eventsCount = 0; | |
return this; | |
} | |
listeners = events[type]; | |
if (typeof listeners === 'function') { | |
this.removeListener(type, listeners); | |
} else if (listeners !== undefined) { | |
// LIFO order | |
for (i = listeners.length - 1; i >= 0; i--) { | |
this.removeListener(type, listeners[i]); | |
} | |
} | |
return this; | |
}; | |
function _listeners(target, type, unwrap) { | |
var events = target._events; | |
if (events === undefined) | |
return []; | |
var evlistener = events[type]; | |
if (evlistener === undefined) | |
return []; | |
if (typeof evlistener === 'function') | |
return unwrap ? [evlistener.listener || evlistener] : [evlistener]; | |
return unwrap ? | |
unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); | |
} | |
EventEmitter.prototype.listeners = function listeners(type) { | |
return _listeners(this, type, true); | |
}; | |
EventEmitter.prototype.rawListeners = function rawListeners(type) { | |
return _listeners(this, type, false); | |
}; | |
EventEmitter.listenerCount = function(emitter, type) { | |
if (typeof emitter.listenerCount === 'function') { | |
return emitter.listenerCount(type); | |
} else { | |
return listenerCount.call(emitter, type); | |
} | |
}; | |
EventEmitter.prototype.listenerCount = listenerCount; | |
function listenerCount(type) { | |
var events = this._events; | |
if (events !== undefined) { | |
var evlistener = events[type]; | |
if (typeof evlistener === 'function') { | |
return 1; | |
} else if (evlistener !== undefined) { | |
return evlistener.length; | |
} | |
} | |
return 0; | |
} | |
EventEmitter.prototype.eventNames = function eventNames() { | |
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; | |
}; | |
function arrayClone(arr, n) { | |
var copy = new Array(n); | |
for (var i = 0; i < n; ++i) | |
copy[i] = arr[i]; | |
return copy; | |
} | |
function spliceOne(list, index) { | |
for (; index + 1 < list.length; index++) | |
list[index] = list[index + 1]; | |
list.pop(); | |
} | |
function unwrapListeners(arr) { | |
var ret = new Array(arr.length); | |
for (var i = 0; i < ret.length; ++i) { | |
ret[i] = arr[i].listener || arr[i]; | |
} | |
return ret; | |
} | |
function once(emitter, name) { | |
return new Promise(function (resolve, reject) { | |
function eventListener() { | |
if (errorListener !== undefined) { | |
emitter.removeListener('error', errorListener); | |
} | |
resolve([].slice.call(arguments)); | |
}; | |
var errorListener; | |
// Adding an error listener is not optional because | |
// if an error is thrown on an event emitter we cannot | |
// guarantee that the actual event we are waiting will | |
// be fired. The result could be a silent way to create | |
// memory or file descriptor leaks, which is something | |
// we should avoid. | |
if (name !== 'error') { | |
errorListener = function errorListener(err) { | |
emitter.removeListener(name, eventListener); | |
reject(err); | |
}; | |
emitter.once('error', errorListener); | |
} | |
emitter.once(name, eventListener); | |
}); | |
} | |
},{}],54:[function(require,module,exports){ | |
var hasOwn = Object.prototype.hasOwnProperty; | |
var toString = Object.prototype.toString; | |
module.exports = function forEach (obj, fn, ctx) { | |
if (toString.call(fn) !== '[object Function]') { | |
throw new TypeError('iterator must be a function'); | |
} | |
var l = obj.length; | |
if (l === +l) { | |
for (var i = 0; i < l; i++) { | |
fn.call(ctx, obj[i], i, obj); | |
} | |
} else { | |
for (var k in obj) { | |
if (hasOwn.call(obj, k)) { | |
fn.call(ctx, obj[k], k, obj); | |
} | |
} | |
} | |
}; | |
},{}],55:[function(require,module,exports){ | |
'use strict'; | |
/* eslint no-invalid-this: 1 */ | |
var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible '; | |
var slice = Array.prototype.slice; | |
var toStr = Object.prototype.toString; | |
var funcType = '[object Function]'; | |
module.exports = function bind(that) { | |
var target = this; | |
if (typeof target !== 'function' || toStr.call(target) !== funcType) { | |
throw new TypeError(ERROR_MESSAGE + target); | |
} | |
var args = slice.call(arguments, 1); | |
var bound; | |
var binder = function () { | |
if (this instanceof bound) { | |
var result = target.apply( | |
this, | |
args.concat(slice.call(arguments)) | |
); | |
if (Object(result) === result) { | |
return result; | |
} | |
return this; | |
} else { | |
return target.apply( | |
that, | |
args.concat(slice.call(arguments)) | |
); | |
} | |
}; | |
var boundLength = Math.max(0, target.length - args.length); | |
var boundArgs = []; | |
for (var i = 0; i < boundLength; i++) { | |
boundArgs.push('$' + i); | |
} | |
bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder); | |
if (target.prototype) { | |
var Empty = function Empty() {}; | |
Empty.prototype = target.prototype; | |
bound.prototype = new Empty(); | |
Empty.prototype = null; | |
} | |
return bound; | |
}; | |
},{}],56:[function(require,module,exports){ | |
'use strict'; | |
var implementation = require('./implementation'); | |
module.exports = Function.prototype.bind || implementation; | |
},{"./implementation":55}],57:[function(require,module,exports){ | |
(function (global){(function (){ | |
'use strict'; | |
var origSymbol = global.Symbol; | |
var hasSymbolSham = require('./shams'); | |
module.exports = function hasNativeSymbols() { | |
if (typeof origSymbol !== 'function') { return false; } | |
if (typeof Symbol !== 'function') { return false; } | |
if (typeof origSymbol('foo') !== 'symbol') { return false; } | |
if (typeof Symbol('bar') !== 'symbol') { return false; } | |
return hasSymbolSham(); | |
}; | |
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"./shams":58}],58:[function(require,module,exports){ | |
'use strict'; | |
/* eslint complexity: [2, 18], max-statements: [2, 33] */ | |
module.exports = function hasSymbols() { | |
if (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; } | |
if (typeof Symbol.iterator === 'symbol') { return true; } | |
var obj = {}; | |
var sym = Symbol('test'); | |
var symObj = Object(sym); | |
if (typeof sym === 'string') { return false; } | |
if (Object.prototype.toString.call(sym) !== '[object Symbol]') { return false; } | |
if (Object.prototype.toString.call(symObj) !== '[object Symbol]') { return false; } | |
// temp disabled per https://github.com/ljharb/object.assign/issues/17 | |
// if (sym instanceof Symbol) { return false; } | |
// temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4 | |
// if (!(symObj instanceof Symbol)) { return false; } | |
// if (typeof Symbol.prototype.toString !== 'function') { return false; } | |
// if (String(sym) !== Symbol.prototype.toString.call(sym)) { return false; } | |
var symVal = 42; | |
obj[sym] = symVal; | |
for (sym in obj) { return false; } // eslint-disable-line no-restricted-syntax | |
if (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; } | |
if (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; } | |
var syms = Object.getOwnPropertySymbols(obj); | |
if (syms.length !== 1 || syms[0] !== sym) { return false; } | |
if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; } | |
if (typeof Object.getOwnPropertyDescriptor === 'function') { | |
var descriptor = Object.getOwnPropertyDescriptor(obj, sym); | |
if (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; } | |
} | |
return true; | |
}; | |
},{}],59:[function(require,module,exports){ | |
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */ | |
exports.read = function (buffer, offset, isLE, mLen, nBytes) { | |
var e, m | |
var eLen = (nBytes * 8) - mLen - 1 | |
var eMax = (1 << eLen) - 1 | |
var eBias = eMax >> 1 | |
var nBits = -7 | |
var i = isLE ? (nBytes - 1) : 0 | |
var d = isLE ? -1 : 1 | |
var s = buffer[offset + i] | |
i += d | |
e = s & ((1 << (-nBits)) - 1) | |
s >>= (-nBits) | |
nBits += eLen | |
for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} | |
m = e & ((1 << (-nBits)) - 1) | |
e >>= (-nBits) | |
nBits += mLen | |
for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} | |
if (e === 0) { | |
e = 1 - eBias | |
} else if (e === eMax) { | |
return m ? NaN : ((s ? -1 : 1) * Infinity) | |
} else { | |
m = m + Math.pow(2, mLen) | |
e = e - eBias | |
} | |
return (s ? -1 : 1) * m * Math.pow(2, e - mLen) | |
} | |
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { | |
var e, m, c | |
var eLen = (nBytes * 8) - mLen - 1 | |
var eMax = (1 << eLen) - 1 | |
var eBias = eMax >> 1 | |
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) | |
var i = isLE ? 0 : (nBytes - 1) | |
var d = isLE ? 1 : -1 | |
var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 | |
value = Math.abs(value) | |
if (isNaN(value) || value === Infinity) { | |
m = isNaN(value) ? 1 : 0 | |
e = eMax | |
} else { | |
e = Math.floor(Math.log(value) / Math.LN2) | |
if (value * (c = Math.pow(2, -e)) < 1) { | |
e-- | |
c *= 2 | |
} | |
if (e + eBias >= 1) { | |
value += rt / c | |
} else { | |
value += rt * Math.pow(2, 1 - eBias) | |
} | |
if (value * c >= 2) { | |
e++ | |
c /= 2 | |
} | |
if (e + eBias >= eMax) { | |
m = 0 | |
e = eMax | |
} else if (e + eBias >= 1) { | |
m = ((value * c) - 1) * Math.pow(2, mLen) | |
e = e + eBias | |
} else { | |
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) | |
e = 0 | |
} | |
} | |
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} | |
e = (e << mLen) | m | |
eLen += mLen | |
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} | |
buffer[offset + i - d] |= s * 128 | |
} | |
},{}],60:[function(require,module,exports){ | |
if (typeof Object.create === 'function') { | |
// implementation from standard node.js 'util' module | |
module.exports = function inherits(ctor, superCtor) { | |
if (superCtor) { | |
ctor.super_ = superCtor | |
ctor.prototype = Object.create(superCtor.prototype, { | |
constructor: { | |
value: ctor, | |
enumerable: false, | |
writable: true, | |
configurable: true | |
} | |
}) | |
} | |
}; | |
} else { | |
// old school shim for old browsers | |
module.exports = function inherits(ctor, superCtor) { | |
if (superCtor) { | |
ctor.super_ = superCtor | |
var TempCtor = function () {} | |
TempCtor.prototype = superCtor.prototype | |
ctor.prototype = new TempCtor() | |
ctor.prototype.constructor = ctor | |
} | |
} | |
} | |
},{}],61:[function(require,module,exports){ | |
'use strict'; | |
var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol'; | |
var toStr = Object.prototype.toString; | |
var isStandardArguments = function isArguments(value) { | |
if (hasToStringTag && value && typeof value === 'object' && Symbol.toStringTag in value) { | |
return false; | |
} | |
return toStr.call(value) === '[object Arguments]'; | |
}; | |
var isLegacyArguments = function isArguments(value) { | |
if (isStandardArguments(value)) { | |
return true; | |
} | |
return value !== null && | |
typeof value === 'object' && | |
typeof value.length === 'number' && | |
value.length >= 0 && | |
toStr.call(value) !== '[object Array]' && | |
toStr.call(value.callee) === '[object Function]'; | |
}; | |
var supportsStandardArguments = (function () { | |
return isStandardArguments(arguments); | |
}()); | |
isStandardArguments.isLegacyArguments = isLegacyArguments; // for tests | |
module.exports = supportsStandardArguments ? isStandardArguments : isLegacyArguments; | |
},{}],62:[function(require,module,exports){ | |
'use strict'; | |
var toStr = Object.prototype.toString; | |
var fnToStr = Function.prototype.toString; | |
var isFnRegex = /^\s*(?:function)?\*/; | |
var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol'; | |
var getProto = Object.getPrototypeOf; | |
var getGeneratorFunc = function () { // eslint-disable-line consistent-return | |
if (!hasToStringTag) { | |
return false; | |
} | |
try { | |
return Function('return function*() {}')(); | |
} catch (e) { | |
} | |
}; | |
var generatorFunc = getGeneratorFunc(); | |
var GeneratorFunction = generatorFunc ? getProto(generatorFunc) : {}; | |
module.exports = function isGeneratorFunction(fn) { | |
if (typeof fn !== 'function') { | |
return false; | |
} | |
if (isFnRegex.test(fnToStr.call(fn))) { | |
return true; | |
} | |
if (!hasToStringTag) { | |
var str = toStr.call(fn); | |
return str === '[object GeneratorFunction]'; | |
} | |
return getProto(fn) === GeneratorFunction; | |
}; | |
},{}],63:[function(require,module,exports){ | |
(function (global){(function (){ | |
'use strict'; | |
var forEach = require('foreach'); | |
var availableTypedArrays = require('available-typed-arrays'); | |
var callBound = require('es-abstract/helpers/callBound'); | |
var $toString = callBound('Object.prototype.toString'); | |
var hasSymbols = require('has-symbols')(); | |
var hasToStringTag = hasSymbols && typeof Symbol.toStringTag === 'symbol'; | |
var typedArrays = availableTypedArrays(); | |
var $indexOf = callBound('Array.prototype.indexOf', true) || function indexOf(array, value) { | |
for (var i = 0; i < array.length; i += 1) { | |
if (array[i] === value) { | |
return i; | |
} | |
} | |
return -1; | |
}; | |
var $slice = callBound('String.prototype.slice'); | |
var toStrTags = {}; | |
var gOPD = require('es-abstract/helpers/getOwnPropertyDescriptor'); | |
var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof'); | |
if (hasToStringTag && gOPD && getPrototypeOf) { | |
forEach(typedArrays, function (typedArray) { | |
var arr = new global[typedArray](); | |
if (!(Symbol.toStringTag in arr)) { | |
throw new EvalError('this engine has support for Symbol.toStringTag, but ' + typedArray + ' does not have the property! Please report this.'); | |
} | |
var proto = getPrototypeOf(arr); | |
var descriptor = gOPD(proto, Symbol.toStringTag); | |
if (!descriptor) { | |
var superProto = getPrototypeOf(proto); | |
descriptor = gOPD(superProto, Symbol.toStringTag); | |
} | |
toStrTags[typedArray] = descriptor.get; | |
}); | |
} | |
var tryTypedArrays = function tryAllTypedArrays(value) { | |
var anyTrue = false; | |
forEach(toStrTags, function (getter, typedArray) { | |
if (!anyTrue) { | |
try { | |
anyTrue = getter.call(value) === typedArray; | |
} catch (e) { /**/ } | |
} | |
}); | |
return anyTrue; | |
}; | |
module.exports = function isTypedArray(value) { | |
if (!value || typeof value !== 'object') { return false; } | |
if (!hasToStringTag) { | |
var tag = $slice($toString(value), 8, -1); | |
return $indexOf(typedArrays, tag) > -1; | |
} | |
if (!gOPD) { return false; } | |
return tryTypedArrays(value); | |
}; | |
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"available-typed-arrays":46,"es-abstract/helpers/callBound":51,"es-abstract/helpers/getOwnPropertyDescriptor":52,"foreach":54,"has-symbols":57}],64:[function(require,module,exports){ | |
exports.endianness = function () { return 'LE' }; | |
exports.hostname = function () { | |
if (typeof location !== 'undefined') { | |
return location.hostname | |
} | |
else return ''; | |
}; | |
exports.loadavg = function () { return [] }; | |
exports.uptime = function () { return 0 }; | |
exports.freemem = function () { | |
return Number.MAX_VALUE; | |
}; | |
exports.totalmem = function () { | |
return Number.MAX_VALUE; | |
}; | |
exports.cpus = function () { return [] }; | |
exports.type = function () { return 'Browser' }; | |
exports.release = function () { | |
if (typeof navigator !== 'undefined') { | |
return navigator.appVersion; | |
} | |
return ''; | |
}; | |
exports.networkInterfaces | |
= exports.getNetworkInterfaces | |
= function () { return {} }; | |
exports.arch = function () { return 'javascript' }; | |
exports.platform = function () { return 'browser' }; | |
exports.tmpdir = exports.tmpDir = function () { | |
return '/tmp'; | |
}; | |
exports.EOL = '\n'; | |
exports.homedir = function () { | |
return '/' | |
}; | |
},{}],65:[function(require,module,exports){ | |
// shim for using process in browser | |
var process = module.exports = {}; | |
// cached from whatever global is present so that test runners that stub it | |
// don't break things. But we need to wrap it in a try catch in case it is | |
// wrapped in strict mode code which doesn't define any globals. It's inside a | |
// function because try/catches deoptimize in certain engines. | |
var cachedSetTimeout; | |
var cachedClearTimeout; | |
function defaultSetTimout() { | |
throw new Error('setTimeout has not been defined'); | |
} | |
function defaultClearTimeout () { | |
throw new Error('clearTimeout has not been defined'); | |
} | |
(function () { | |
try { | |
if (typeof setTimeout === 'function') { | |
cachedSetTimeout = setTimeout; | |
} else { | |
cachedSetTimeout = defaultSetTimout; | |
} | |
} catch (e) { | |
cachedSetTimeout = defaultSetTimout; | |
} | |
try { | |
if (typeof clearTimeout === 'function') { | |
cachedClearTimeout = clearTimeout; | |
} else { | |
cachedClearTimeout = defaultClearTimeout; | |
} | |
} catch (e) { | |
cachedClearTimeout = defaultClearTimeout; | |
} | |
} ()) | |
function runTimeout(fun) { | |
if (cachedSetTimeout === setTimeout) { | |
//normal enviroments in sane situations | |
return setTimeout(fun, 0); | |
} | |
// if setTimeout wasn't available but was latter defined | |
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { | |
cachedSetTimeout = setTimeout; | |
return setTimeout(fun, 0); | |
} | |
try { | |
// when when somebody has screwed with setTimeout but no I.E. maddness | |
return cachedSetTimeout(fun, 0); | |
} catch(e){ | |
try { | |
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally | |
return cachedSetTimeout.call(null, fun, 0); | |
} catch(e){ | |
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error | |
return cachedSetTimeout.call(this, fun, 0); | |
} | |
} | |
} | |
function runClearTimeout(marker) { | |
if (cachedClearTimeout === clearTimeout) { | |
//normal enviroments in sane situations | |
return clearTimeout(marker); | |
} | |
// if clearTimeout wasn't available but was latter defined | |
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { | |
cachedClearTimeout = clearTimeout; | |
return clearTimeout(marker); | |
} | |
try { | |
// when when somebody has screwed with setTimeout but no I.E. maddness | |
return cachedClearTimeout(marker); | |
} catch (e){ | |
try { | |
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally | |
return cachedClearTimeout.call(null, marker); | |
} catch (e){ | |
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. | |
// Some versions of I.E. have different rules for clearTimeout vs setTimeout | |
return cachedClearTimeout.call(this, marker); | |
} | |
} | |
} | |
var queue = []; | |
var draining = false; | |
var currentQueue; | |
var queueIndex = -1; | |
function cleanUpNextTick() { | |
if (!draining || !currentQueue) { | |
return; | |
} | |
draining = false; | |
if (currentQueue.length) { | |
queue = currentQueue.concat(queue); | |
} else { | |
queueIndex = -1; | |
} | |
if (queue.length) { | |
drainQueue(); | |
} | |
} | |
function drainQueue() { | |
if (draining) { | |
return; | |
} | |
var timeout = runTimeout(cleanUpNextTick); | |
draining = true; | |
var len = queue.length; | |
while(len) { | |
currentQueue = queue; | |
queue = []; | |
while (++queueIndex < len) { | |
if (currentQueue) { | |
currentQueue[queueIndex].run(); | |
} | |
} | |
queueIndex = -1; | |
len = queue.length; | |
} | |
currentQueue = null; | |
draining = false; | |
runClearTimeout(timeout); | |
} | |
process.nextTick = function (fun) { | |
var args = new Array(arguments.length - 1); | |
if (arguments.length > 1) { | |
for (var i = 1; i < arguments.length; i++) { | |
args[i - 1] = arguments[i]; | |
} | |
} | |
queue.push(new Item(fun, args)); | |
if (queue.length === 1 && !draining) { | |
runTimeout(drainQueue); | |
} | |
}; | |
// v8 likes predictible objects | |
function Item(fun, array) { | |
this.fun = fun; | |
this.array = array; | |
} | |
Item.prototype.run = function () { | |
this.fun.apply(null, this.array); | |
}; | |
process.title = 'browser'; | |
process.browser = true; | |
process.env = {}; | |
process.argv = []; | |
process.version = ''; // empty string to avoid regexp issues | |
process.versions = {}; | |
function noop() {} | |
process.on = noop; | |
process.addListener = noop; | |
process.once = noop; | |
process.off = noop; | |
process.removeListener = noop; | |
process.removeAllListeners = noop; | |
process.emit = noop; | |
process.prependListener = noop; | |
process.prependOnceListener = noop; | |
process.listeners = function (name) { return [] } | |
process.binding = function (name) { | |
throw new Error('process.binding is not supported'); | |
}; | |
process.cwd = function () { return '/' }; | |
process.chdir = function (dir) { | |
throw new Error('process.chdir is not supported'); | |
}; | |
process.umask = function() { return 0; }; | |
},{}],66:[function(require,module,exports){ | |
module.exports = function isBuffer(arg) { | |
return arg && typeof arg === 'object' | |
&& typeof arg.copy === 'function' | |
&& typeof arg.fill === 'function' | |
&& typeof arg.readUInt8 === 'function'; | |
} | |
},{}],67:[function(require,module,exports){ | |
// Currently in sync with Node.js lib/internal/util/types.js | |
// https://github.com/nodejs/node/commit/112cc7c27551254aa2b17098fb774867f05ed0d9 | |
'use strict'; | |
var isArgumentsObject = require('is-arguments'); | |
var isGeneratorFunction = require('is-generator-function'); | |
var whichTypedArray = require('which-typed-array'); | |
var isTypedArray = require('is-typed-array'); | |
function uncurryThis(f) { | |
return f.call.bind(f); | |
} | |
var BigIntSupported = typeof BigInt !== 'undefined'; | |
var SymbolSupported = typeof Symbol !== 'undefined'; | |
var ObjectToString = uncurryThis(Object.prototype.toString); | |
var numberValue = uncurryThis(Number.prototype.valueOf); | |
var stringValue = uncurryThis(String.prototype.valueOf); | |
var booleanValue = uncurryThis(Boolean.prototype.valueOf); | |
if (BigIntSupported) { | |
var bigIntValue = uncurryThis(BigInt.prototype.valueOf); | |
} | |
if (SymbolSupported) { | |
var symbolValue = uncurryThis(Symbol.prototype.valueOf); | |
} | |
function checkBoxedPrimitive(value, prototypeValueOf) { | |
if (typeof value !== 'object') { | |
return false; | |
} | |
try { | |
prototypeValueOf(value); | |
return true; | |
} catch(e) { | |
return false; | |
} | |
} | |
exports.isArgumentsObject = isArgumentsObject; | |
exports.isGeneratorFunction = isGeneratorFunction; | |
exports.isTypedArray = isTypedArray; | |
// Taken from here and modified for better browser support | |
// https://github.com/sindresorhus/p-is-promise/blob/cda35a513bda03f977ad5cde3a079d237e82d7ef/index.js | |
function isPromise(input) { | |
return ( | |
( | |
typeof Promise !== 'undefined' && | |
input instanceof Promise | |
) || | |
( | |
input !== null && | |
typeof input === 'object' && | |
typeof input.then === 'function' && | |
typeof input.catch === 'function' | |
) | |
); | |
} | |
exports.isPromise = isPromise; | |
function isArrayBufferView(value) { | |
if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) { | |
return ArrayBuffer.isView(value); | |
} | |
return ( | |
isTypedArray(value) || | |
isDataView(value) | |
); | |
} | |
exports.isArrayBufferView = isArrayBufferView; | |
function isUint8Array(value) { | |
return whichTypedArray(value) === 'Uint8Array'; | |
} | |
exports.isUint8Array = isUint8Array; | |
function isUint8ClampedArray(value) { | |
return whichTypedArray(value) === 'Uint8ClampedArray'; | |
} | |
exports.isUint8ClampedArray = isUint8ClampedArray; | |
function isUint16Array(value) { | |
return whichTypedArray(value) === 'Uint16Array'; | |
} | |
exports.isUint16Array = isUint16Array; | |
function isUint32Array(value) { | |
return whichTypedArray(value) === 'Uint32Array'; | |
} | |
exports.isUint32Array = isUint32Array; | |
function isInt8Array(value) { | |
return whichTypedArray(value) === 'Int8Array'; | |
} | |
exports.isInt8Array = isInt8Array; | |
function isInt16Array(value) { | |
return whichTypedArray(value) === 'Int16Array'; | |
} | |
exports.isInt16Array = isInt16Array; | |
function isInt32Array(value) { | |
return whichTypedArray(value) === 'Int32Array'; | |
} | |
exports.isInt32Array = isInt32Array; | |
function isFloat32Array(value) { | |
return whichTypedArray(value) === 'Float32Array'; | |
} | |
exports.isFloat32Array = isFloat32Array; | |
function isFloat64Array(value) { | |
return whichTypedArray(value) === 'Float64Array'; | |
} | |
exports.isFloat64Array = isFloat64Array; | |
function isBigInt64Array(value) { | |
return whichTypedArray(value) === 'BigInt64Array'; | |
} | |
exports.isBigInt64Array = isBigInt64Array; | |
function isBigUint64Array(value) { | |
return whichTypedArray(value) === 'BigUint64Array'; | |
} | |
exports.isBigUint64Array = isBigUint64Array; | |
function isMapToString(value) { | |
return ObjectToString(value) === '[object Map]'; | |
} | |
isMapToString.working = ( | |
typeof Map !== 'undefined' && | |
isMapToString(new Map()) | |
); | |
function isMap(value) { | |
if (typeof Map === 'undefined') { | |
return false; | |
} | |
return isMapToString.working | |
? isMapToString(value) | |
: value instanceof Map; | |
} | |
exports.isMap = isMap; | |
function isSetToString(value) { | |
return ObjectToString(value) === '[object Set]'; | |
} | |
isSetToString.working = ( | |
typeof Set !== 'undefined' && | |
isSetToString(new Set()) | |
); | |
function isSet(value) { | |
if (typeof Set === 'undefined') { | |
return false; | |
} | |
return isSetToString.working | |
? isSetToString(value) | |
: value instanceof Set; | |
} | |
exports.isSet = isSet; | |
function isWeakMapToString(value) { | |
return ObjectToString(value) === '[object WeakMap]'; | |
} | |
isWeakMapToString.working = ( | |
typeof WeakMap !== 'undefined' && | |
isWeakMapToString(new WeakMap()) | |
); | |
function isWeakMap(value) { | |
if (typeof WeakMap === 'undefined') { | |
return false; | |
} | |
return isWeakMapToString.working | |
? isWeakMapToString(value) | |
: value instanceof WeakMap; | |
} | |
exports.isWeakMap = isWeakMap; | |
function isWeakSetToString(value) { | |
return ObjectToString(value) === '[object WeakSet]'; | |
} | |
isWeakSetToString.working = ( | |
typeof WeakSet !== 'undefined' && | |
isWeakSetToString(new WeakSet()) | |
); | |
function isWeakSet(value) { | |
return isWeakSetToString(value); | |
} | |
exports.isWeakSet = isWeakSet; | |
function isArrayBufferToString(value) { | |
return ObjectToString(value) === '[object ArrayBuffer]'; | |
} | |
isArrayBufferToString.working = ( | |
typeof ArrayBuffer !== 'undefined' && | |
isArrayBufferToString(new ArrayBuffer()) | |
); | |
function isArrayBuffer(value) { | |
if (typeof ArrayBuffer === 'undefined') { | |
return false; | |
} | |
return isArrayBufferToString.working | |
? isArrayBufferToString(value) | |
: value instanceof ArrayBuffer; | |
} | |
exports.isArrayBuffer = isArrayBuffer; | |
function isDataViewToString(value) { | |
return ObjectToString(value) === '[object DataView]'; | |
} | |
isDataViewToString.working = ( | |
typeof ArrayBuffer !== 'undefined' && | |
typeof DataView !== 'undefined' && | |
isDataViewToString(new DataView(new ArrayBuffer(1), 0, 1)) | |
); | |
function isDataView(value) { | |
if (typeof DataView === 'undefined') { | |
return false; | |
} | |
return isDataViewToString.working | |
? isDataViewToString(value) | |
: value instanceof DataView; | |
} | |
exports.isDataView = isDataView; | |
function isSharedArrayBufferToString(value) { | |
return ObjectToString(value) === '[object SharedArrayBuffer]'; | |
} | |
isSharedArrayBufferToString.working = ( | |
typeof SharedArrayBuffer !== 'undefined' && | |
isSharedArrayBufferToString(new SharedArrayBuffer()) | |
); | |
function isSharedArrayBuffer(value) { | |
if (typeof SharedArrayBuffer === 'undefined') { | |
return false; | |
} | |
return isSharedArrayBufferToString.working | |
? isSharedArrayBufferToString(value) | |
: value instanceof SharedArrayBuffer; | |
} | |
exports.isSharedArrayBuffer = isSharedArrayBuffer; | |
function isAsyncFunction(value) { | |
return ObjectToString(value) === '[object AsyncFunction]'; | |
} | |
exports.isAsyncFunction = isAsyncFunction; | |
function isMapIterator(value) { | |
return ObjectToString(value) === '[object Map Iterator]'; | |
} | |
exports.isMapIterator = isMapIterator; | |
function isSetIterator(value) { | |
return ObjectToString(value) === '[object Set Iterator]'; | |
} | |
exports.isSetIterator = isSetIterator; | |
function isGeneratorObject(value) { | |
return ObjectToString(value) === '[object Generator]'; | |
} | |
exports.isGeneratorObject = isGeneratorObject; | |
function isWebAssemblyCompiledModule(value) { | |
return ObjectToString(value) === '[object WebAssembly.Module]'; | |
} | |
exports.isWebAssemblyCompiledModule = isWebAssemblyCompiledModule; | |
function isNumberObject(value) { | |
return checkBoxedPrimitive(value, numberValue); | |
} | |
exports.isNumberObject = isNumberObject; | |
function isStringObject(value) { | |
return checkBoxedPrimitive(value, stringValue); | |
} | |
exports.isStringObject = isStringObject; | |
function isBooleanObject(value) { | |
return checkBoxedPrimitive(value, booleanValue); | |
} | |
exports.isBooleanObject = isBooleanObject; | |
function isBigIntObject(value) { | |
return BigIntSupported && checkBoxedPrimitive(value, bigIntValue); | |
} | |
exports.isBigIntObject = isBigIntObject; | |
function isSymbolObject(value) { | |
return SymbolSupported && checkBoxedPrimitive(value, symbolValue); | |
} | |
exports.isSymbolObject = isSymbolObject; | |
function isBoxedPrimitive(value) { | |
return ( | |
isNumberObject(value) || | |
isStringObject(value) || | |
isBooleanObject(value) || | |
isBigIntObject(value) || | |
isSymbolObject(value) | |
); | |
} | |
exports.isBoxedPrimitive = isBoxedPrimitive; | |
function isAnyArrayBuffer(value) { | |
return typeof Uint8Array !== 'undefined' && ( | |
isArrayBuffer(value) || | |
isSharedArrayBuffer(value) | |
); | |
} | |
exports.isAnyArrayBuffer = isAnyArrayBuffer; | |
['isProxy', 'isExternal', 'isModuleNamespaceObject'].forEach(function(method) { | |
Object.defineProperty(exports, method, { | |
enumerable: false, | |
value: function() { | |
throw new Error(method + ' is not supported in userland'); | |
} | |
}); | |
}); | |
},{"is-arguments":61,"is-generator-function":62,"is-typed-array":63,"which-typed-array":69}],68:[function(require,module,exports){ | |
(function (process){(function (){ | |
// Copyright Joyent, Inc. and other Node 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. | |
var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors || | |
function getOwnPropertyDescriptors(obj) { | |
var keys = Object.keys(obj); | |
var descriptors = {}; | |
for (var i = 0; i < keys.length; i++) { | |
descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]); | |
} | |
return descriptors; | |
}; | |
var formatRegExp = /%[sdj%]/g; | |
exports.format = function(f) { | |
if (!isString(f)) { | |
var objects = []; | |
for (var i = 0; i < arguments.length; i++) { | |
objects.push(inspect(arguments[i])); | |
} | |
return objects.join(' '); | |
} | |
var i = 1; | |
var args = arguments; | |
var len = args.length; | |
var str = String(f).replace(formatRegExp, function(x) { | |
if (x === '%%') return '%'; | |
if (i >= len) return x; | |
switch (x) { | |
case '%s': return String(args[i++]); | |
case '%d': return Number(args[i++]); | |
case '%j': | |
try { | |
return JSON.stringify(args[i++]); | |
} catch (_) { | |
return '[Circular]'; | |
} | |
default: | |
return x; | |
} | |
}); | |
for (var x = args[i]; i < len; x = args[++i]) { | |
if (isNull(x) || !isObject(x)) { | |
str += ' ' + x; | |
} else { | |
str += ' ' + inspect(x); | |
} | |
} | |
return str; | |
}; | |
// Mark that a method should not be used. | |
// Returns a modified function which warns once by default. | |
// If --no-deprecation is set, then it is a no-op. | |
exports.deprecate = function(fn, msg) { | |
if (typeof process !== 'undefined' && process.noDeprecation === true) { | |
return fn; | |
} | |
// Allow for deprecating things in the process of starting up. | |
if (typeof process === 'undefined') { | |
return function() { | |
return exports.deprecate(fn, msg).apply(this, arguments); | |
}; | |
} | |
var warned = false; | |
function deprecated() { | |
if (!warned) { | |
if (process.throwDeprecation) { | |
throw new Error(msg); | |
} else if (process.traceDeprecation) { | |
console.trace(msg); | |
} else { | |
console.error(msg); | |
} | |
warned = true; | |
} | |
return fn.apply(this, arguments); | |
} | |
return deprecated; | |
}; | |
var debugs = {}; | |
var debugEnvRegex = /^$/; | |
if (process.env.NODE_DEBUG) { | |
var debugEnv = process.env.NODE_DEBUG; | |
debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&') | |
.replace(/\*/g, '.*') | |
.replace(/,/g, '$|^') | |
.toUpperCase(); | |
debugEnvRegex = new RegExp('^' + debugEnv + '$', 'i'); | |
} | |
exports.debuglog = function(set) { | |
set = set.toUpperCase(); | |
if (!debugs[set]) { | |
if (debugEnvRegex.test(set)) { | |
var pid = process.pid; | |
debugs[set] = function() { | |
var msg = exports.format.apply(exports, arguments); | |
console.error('%s %d: %s', set, pid, msg); | |
}; | |
} else { | |
debugs[set] = function() {}; | |
} | |
} | |
return debugs[set]; | |
}; | |
/** | |
* Echos the value of a value. Trys to print the value out | |
* in the best way possible given the different types. | |
* | |
* @param {Object} obj The object to print out. | |
* @param {Object} opts Optional options object that alters the output. | |
*/ | |
/* legacy: obj, showHidden, depth, colors*/ | |
function inspect(obj, opts) { | |
// default options | |
var ctx = { | |
seen: [], | |
stylize: stylizeNoColor | |
}; | |
// legacy... | |
if (arguments.length >= 3) ctx.depth = arguments[2]; | |
if (arguments.length >= 4) ctx.colors = arguments[3]; | |
if (isBoolean(opts)) { | |
// legacy... | |
ctx.showHidden = opts; | |
} else if (opts) { | |
// got an "options" object | |
exports._extend(ctx, opts); | |
} | |
// set default options | |
if (isUndefined(ctx.showHidden)) ctx.showHidden = false; | |
if (isUndefined(ctx.depth)) ctx.depth = 2; | |
if (isUndefined(ctx.colors)) ctx.colors = false; | |
if (isUndefined(ctx.customInspect)) ctx.customInspect = true; | |
if (ctx.colors) ctx.stylize = stylizeWithColor; | |
return formatValue(ctx, obj, ctx.depth); | |
} | |
exports.inspect = inspect; | |
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics | |
inspect.colors = { | |
'bold' : [1, 22], | |
'italic' : [3, 23], | |
'underline' : [4, 24], | |
'inverse' : [7, 27], | |
'white' : [37, 39], | |
'grey' : [90, 39], | |
'black' : [30, 39], | |
'blue' : [34, 39], | |
'cyan' : [36, 39], | |
'green' : [32, 39], | |
'magenta' : [35, 39], | |
'red' : [31, 39], | |
'yellow' : [33, 39] | |
}; | |
// Don't use 'blue' not visible on cmd.exe | |
inspect.styles = { | |
'special': 'cyan', | |
'number': 'yellow', | |
'boolean': 'yellow', | |
'undefined': 'grey', | |
'null': 'bold', | |
'string': 'green', | |
'date': 'magenta', | |
// "name": intentionally not styling | |
'regexp': 'red' | |
}; | |
function stylizeWithColor(str, styleType) { | |
var style = inspect.styles[styleType]; | |
if (style) { | |
return '\u001b[' + inspect.colors[style][0] + 'm' + str + | |
'\u001b[' + inspect.colors[style][1] + 'm'; | |
} else { | |
return str; | |
} | |
} | |
function stylizeNoColor(str, styleType) { | |
return str; | |
} | |
function arrayToHash(array) { | |
var hash = {}; | |
array.forEach(function(val, idx) { | |
hash[val] = true; | |
}); | |
return hash; | |
} | |
function formatValue(ctx, value, recurseTimes) { | |
// Provide a hook for user-specified inspect functions. | |
// Check that value is an object with an inspect function on it | |
if (ctx.customInspect && | |
value && | |
isFunction(value.inspect) && | |
// Filter out the util module, it's inspect function is special | |
value.inspect !== exports.inspect && | |
// Also filter out any prototype objects using the circular check. | |
!(value.constructor && value.constructor.prototype === value)) { | |
var ret = value.inspect(recurseTimes, ctx); | |
if (!isString(ret)) { | |
ret = formatValue(ctx, ret, recurseTimes); | |
} | |
return ret; | |
} | |
// Primitive types cannot have properties | |
var primitive = formatPrimitive(ctx, value); | |
if (primitive) { | |
return primitive; | |
} | |
// Look up the keys of the object. | |
var keys = Object.keys(value); | |
var visibleKeys = arrayToHash(keys); | |
if (ctx.showHidden) { | |
keys = Object.getOwnPropertyNames(value); | |
} | |
// IE doesn't make error fields non-enumerable | |
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx | |
if (isError(value) | |
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { | |
return formatError(value); | |
} | |
// Some type of object without properties can be shortcutted. | |
if (keys.length === 0) { | |
if (isFunction(value)) { | |
var name = value.name ? ': ' + value.name : ''; | |
return ctx.stylize('[Function' + name + ']', 'special'); | |
} | |
if (isRegExp(value)) { | |
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); | |
} | |
if (isDate(value)) { | |
return ctx.stylize(Date.prototype.toString.call(value), 'date'); | |
} | |
if (isError(value)) { | |
return formatError(value); | |
} | |
} | |
var base = '', array = false, braces = ['{', '}']; | |
// Make Array say that they are Array | |
if (isArray(value)) { | |
array = true; | |
braces = ['[', ']']; | |
} | |
// Make functions say that they are functions | |
if (isFunction(value)) { | |
var n = value.name ? ': ' + value.name : ''; | |
base = ' [Function' + n + ']'; | |
} | |
// Make RegExps say that they are RegExps | |
if (isRegExp(value)) { | |
base = ' ' + RegExp.prototype.toString.call(value); | |
} | |
// Make dates with properties first say the date | |
if (isDate(value)) { | |
base = ' ' + Date.prototype.toUTCString.call(value); | |
} | |
// Make error with message first say the error | |
if (isError(value)) { | |
base = ' ' + formatError(value); | |
} | |
if (keys.length === 0 && (!array || value.length == 0)) { | |
return braces[0] + base + braces[1]; | |
} | |
if (recurseTimes < 0) { | |
if (isRegExp(value)) { | |
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); | |
} else { | |
return ctx.stylize('[Object]', 'special'); | |
} | |
} | |
ctx.seen.push(value); | |
var output; | |
if (array) { | |
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); | |
} else { | |
output = keys.map(function(key) { | |
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); | |
}); | |
} | |
ctx.seen.pop(); | |
return reduceToSingleString(output, base, braces); | |
} | |
function formatPrimitive(ctx, value) { | |
if (isUndefined(value)) | |
return ctx.stylize('undefined', 'undefined'); | |
if (isString(value)) { | |
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') | |
.replace(/'/g, "\\'") | |
.replace(/\\"/g, '"') + '\''; | |
return ctx.stylize(simple, 'string'); | |
} | |
if (isNumber(value)) | |
return ctx.stylize('' + value, 'number'); | |
if (isBoolean(value)) | |
return ctx.stylize('' + value, 'boolean'); | |
// For some reason typeof null is "object", so special case here. | |
if (isNull(value)) | |
return ctx.stylize('null', 'null'); | |
} | |
function formatError(value) { | |
return '[' + Error.prototype.toString.call(value) + ']'; | |
} | |
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { | |
var output = []; | |
for (var i = 0, l = value.length; i < l; ++i) { | |
if (hasOwnProperty(value, String(i))) { | |
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, | |
String(i), true)); | |
} else { | |
output.push(''); | |
} | |
} | |
keys.forEach(function(key) { | |
if (!key.match(/^\d+$/)) { | |
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, | |
key, true)); | |
} | |
}); | |
return output; | |
} | |
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { | |
var name, str, desc; | |
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; | |
if (desc.get) { | |
if (desc.set) { | |
str = ctx.stylize('[Getter/Setter]', 'special'); | |
} else { | |
str = ctx.stylize('[Getter]', 'special'); | |
} | |
} else { | |
if (desc.set) { | |
str = ctx.stylize('[Setter]', 'special'); | |
} | |
} | |
if (!hasOwnProperty(visibleKeys, key)) { | |
name = '[' + key + ']'; | |
} | |
if (!str) { | |
if (ctx.seen.indexOf(desc.value) < 0) { | |
if (isNull(recurseTimes)) { | |
str = formatValue(ctx, desc.value, null); | |
} else { | |
str = formatValue(ctx, desc.value, recurseTimes - 1); | |
} | |
if (str.indexOf('\n') > -1) { | |
if (array) { | |
str = str.split('\n').map(function(line) { | |
return ' ' + line; | |
}).join('\n').substr(2); | |
} else { | |
str = '\n' + str.split('\n').map(function(line) { | |
return ' ' + line; | |
}).join('\n'); | |
} | |
} | |
} else { | |
str = ctx.stylize('[Circular]', 'special'); | |
} | |
} | |
if (isUndefined(name)) { | |
if (array && key.match(/^\d+$/)) { | |
return str; | |
} | |
name = JSON.stringify('' + key); | |
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { | |
name = name.substr(1, name.length - 2); | |
name = ctx.stylize(name, 'name'); | |
} else { | |
name = name.replace(/'/g, "\\'") | |
.replace(/\\"/g, '"') | |
.replace(/(^"|"$)/g, "'"); | |
name = ctx.stylize(name, 'string'); | |
} | |
} | |
return name + ': ' + str; | |
} | |
function reduceToSingleString(output, base, braces) { | |
var numLinesEst = 0; | |
var length = output.reduce(function(prev, cur) { | |
numLinesEst++; | |
if (cur.indexOf('\n') >= 0) numLinesEst++; | |
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; | |
}, 0); | |
if (length > 60) { | |
return braces[0] + | |
(base === '' ? '' : base + '\n ') + | |
' ' + | |
output.join(',\n ') + | |
' ' + | |
braces[1]; | |
} | |
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; | |
} | |
// NOTE: These type checking functions intentionally don't use `instanceof` | |
// because it is fragile and can be easily faked with `Object.create()`. | |
exports.types = require('./support/types'); | |
function isArray(ar) { | |
return Array.isArray(ar); | |
} | |
exports.isArray = isArray; | |
function isBoolean(arg) { | |
return typeof arg === 'boolean'; | |
} | |
exports.isBoolean = isBoolean; | |
function isNull(arg) { | |
return arg === null; | |
} | |
exports.isNull = isNull; | |
function isNullOrUndefined(arg) { | |
return arg == null; | |
} | |
exports.isNullOrUndefined = isNullOrUndefined; | |
function isNumber(arg) { | |
return typeof arg === 'number'; | |
} | |
exports.isNumber = isNumber; | |
function isString(arg) { | |
return typeof arg === 'string'; | |
} | |
exports.isString = isString; | |
function isSymbol(arg) { | |
return typeof arg === 'symbol'; | |
} | |
exports.isSymbol = isSymbol; | |
function isUndefined(arg) { | |
return arg === void 0; | |
} | |
exports.isUndefined = isUndefined; | |
function isRegExp(re) { | |
return isObject(re) && objectToString(re) === '[object RegExp]'; | |
} | |
exports.isRegExp = isRegExp; | |
exports.types.isRegExp = isRegExp; | |
function isObject(arg) { | |
return typeof arg === 'object' && arg !== null; | |
} | |
exports.isObject = isObject; | |
function isDate(d) { | |
return isObject(d) && objectToString(d) === '[object Date]'; | |
} | |
exports.isDate = isDate; | |
exports.types.isDate = isDate; | |
function isError(e) { | |
return isObject(e) && | |
(objectToString(e) === '[object Error]' || e instanceof Error); | |
} | |
exports.isError = isError; | |
exports.types.isNativeError = isError; | |
function isFunction(arg) { | |
return typeof arg === 'function'; | |
} | |
exports.isFunction = isFunction; | |
function isPrimitive(arg) { | |
return arg === null || | |
typeof arg === 'boolean' || | |
typeof arg === 'number' || | |
typeof arg === 'string' || | |
typeof arg === 'symbol' || // ES6 symbol | |
typeof arg === 'undefined'; | |
} | |
exports.isPrimitive = isPrimitive; | |
exports.isBuffer = require('./support/isBuffer'); | |
function objectToString(o) { | |
return Object.prototype.toString.call(o); | |
} | |
function pad(n) { | |
return n < 10 ? '0' + n.toString(10) : n.toString(10); | |
} | |
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', | |
'Oct', 'Nov', 'Dec']; | |
// 26 Feb 16:19:34 | |
function timestamp() { | |
var d = new Date(); | |
var time = [pad(d.getHours()), | |
pad(d.getMinutes()), | |
pad(d.getSeconds())].join(':'); | |
return [d.getDate(), months[d.getMonth()], time].join(' '); | |
} | |
// log is just a thin wrapper to console.log that prepends a timestamp | |
exports.log = function() { | |
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); | |
}; | |
/** | |
* Inherit the prototype methods from one constructor into another. | |
* | |
* The Function.prototype.inherits from lang.js rewritten as a standalone | |
* function (not on Function.prototype). NOTE: If this file is to be loaded | |
* during bootstrapping this function needs to be rewritten using some native | |
* functions as prototype setup using normal JavaScript does not work as | |
* expected during bootstrapping (see mirror.js in r114903). | |
* | |
* @param {function} ctor Constructor function which needs to inherit the | |
* prototype. | |
* @param {function} superCtor Constructor function to inherit prototype from. | |
*/ | |
exports.inherits = require('inherits'); | |
exports._extend = function(origin, add) { | |
// Don't do anything if add isn't an object | |
if (!add || !isObject(add)) return origin; | |
var keys = Object.keys(add); | |
var i = keys.length; | |
while (i--) { | |
origin[keys[i]] = add[keys[i]]; | |
} | |
return origin; | |
}; | |
function hasOwnProperty(obj, prop) { | |
return Object.prototype.hasOwnProperty.call(obj, prop); | |
} | |
var kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined; | |
exports.promisify = function promisify(original) { | |
if (typeof original !== 'function') | |
throw new TypeError('The "original" argument must be of type Function'); | |
if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) { | |
var fn = original[kCustomPromisifiedSymbol]; | |
if (typeof fn !== 'function') { | |
throw new TypeError('The "util.promisify.custom" argument must be of type Function'); | |
} | |
Object.defineProperty(fn, kCustomPromisifiedSymbol, { | |
value: fn, enumerable: false, writable: false, configurable: true | |
}); | |
return fn; | |
} | |
function fn() { | |
var promiseResolve, promiseReject; | |
var promise = new Promise(function (resolve, reject) { | |
promiseResolve = resolve; | |
promiseReject = reject; | |
}); | |
var args = []; | |
for (var i = 0; i < arguments.length; i++) { | |
args.push(arguments[i]); | |
} | |
args.push(function (err, value) { | |
if (err) { | |
promiseReject(err); | |
} else { | |
promiseResolve(value); | |
} | |
}); | |
try { | |
original.apply(this, args); | |
} catch (err) { | |
promiseReject(err); | |
} | |
return promise; | |
} | |
Object.setPrototypeOf(fn, Object.getPrototypeOf(original)); | |
if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, { | |
value: fn, enumerable: false, writable: false, configurable: true | |
}); | |
return Object.defineProperties( | |
fn, | |
getOwnPropertyDescriptors(original) | |
); | |
} | |
exports.promisify.custom = kCustomPromisifiedSymbol | |
function callbackifyOnRejected(reason, cb) { | |
// `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M). | |
// Because `null` is a special error value in callbacks which means "no error | |
// occurred", we error-wrap so the callback consumer can distinguish between | |
// "the promise rejected with null" or "the promise fulfilled with undefined". | |
if (!reason) { | |
var newReason = new Error('Promise was rejected with a falsy value'); | |
newReason.reason = reason; | |
reason = newReason; | |
} | |
return cb(reason); | |
} | |
function callbackify(original) { | |
if (typeof original !== 'function') { | |
throw new TypeError('The "original" argument must be of type Function'); | |
} | |
// We DO NOT return the promise as it gives the user a false sense that | |
// the promise is actually somehow related to the callback's execution | |
// and that the callback throwing will reject the promise. | |
function callbackified() { | |
var args = []; | |
for (var i = 0; i < arguments.length; i++) { | |
args.push(arguments[i]); | |
} | |
var maybeCb = args.pop(); | |
if (typeof maybeCb !== 'function') { | |
throw new TypeError('The last argument must be of type Function'); | |
} | |
var self = this; | |
var cb = function() { | |
return maybeCb.apply(self, arguments); | |
}; | |
// In true node style we process the callback on `nextTick` with all the | |
// implications (stack, `uncaughtException`, `async_hooks`) | |
original.apply(this, args) | |
.then(function(ret) { process.nextTick(cb.bind(null, null, ret)) }, | |
function(rej) { process.nextTick(callbackifyOnRejected.bind(null, rej, cb)) }); | |
} | |
Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original)); | |
Object.defineProperties(callbackified, | |
getOwnPropertyDescriptors(original)); | |
return callbackified; | |
} | |
exports.callbackify = callbackify; | |
}).call(this)}).call(this,require('_process')) | |
},{"./support/isBuffer":66,"./support/types":67,"_process":65,"inherits":60}],69:[function(require,module,exports){ | |
(function (global){(function (){ | |
'use strict'; | |
var forEach = require('foreach'); | |
var availableTypedArrays = require('available-typed-arrays'); | |
var callBound = require('es-abstract/helpers/callBound'); | |
var $toString = callBound('Object.prototype.toString'); | |
var hasSymbols = require('has-symbols')(); | |
var hasToStringTag = hasSymbols && typeof Symbol.toStringTag === 'symbol'; | |
var typedArrays = availableTypedArrays(); | |
var $slice = callBound('String.prototype.slice'); | |
var toStrTags = {}; | |
var gOPD = require('es-abstract/helpers/getOwnPropertyDescriptor'); | |
var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof'); | |
if (hasToStringTag && gOPD && getPrototypeOf) { | |
forEach(typedArrays, function (typedArray) { | |
if (typeof global[typedArray] === 'function') { | |
var arr = new global[typedArray](); | |
if (!(Symbol.toStringTag in arr)) { | |
throw new EvalError('this engine has support for Symbol.toStringTag, but ' + typedArray + ' does not have the property! Please report this.'); | |
} | |
var proto = getPrototypeOf(arr); | |
var descriptor = gOPD(proto, Symbol.toStringTag); | |
if (!descriptor) { | |
var superProto = getPrototypeOf(proto); | |
descriptor = gOPD(superProto, Symbol.toStringTag); | |
} | |
toStrTags[typedArray] = descriptor.get; | |
} | |
}); | |
} | |
var tryTypedArrays = function tryAllTypedArrays(value) { | |
var foundName = false; | |
forEach(toStrTags, function (getter, typedArray) { | |
if (!foundName) { | |
try { | |
var name = getter.call(value); | |
if (name === typedArray) { | |
foundName = name; | |
} | |
} catch (e) {} | |
} | |
}); | |
return foundName; | |
}; | |
var isTypedArray = require('is-typed-array'); | |
module.exports = function whichTypedArray(value) { | |
if (!isTypedArray(value)) { return false; } | |
if (!hasToStringTag) { return $slice($toString(value), 8, -1); } | |
return tryTypedArrays(value); | |
}; | |
}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"available-typed-arrays":46,"es-abstract/helpers/callBound":51,"es-abstract/helpers/getOwnPropertyDescriptor":52,"foreach":54,"has-symbols":57,"is-typed-array":63}],"natural":[function(require,module,exports){ | |
/* | |
Copyright (c) 2011, Chris Umbel | |
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. | |
*/ | |
exports.SoundEx = require('./phonetics/soundex'); | |
exports.Metaphone = require('./phonetics/metaphone'); | |
exports.DoubleMetaphone = require('./phonetics/double_metaphone'); | |
exports.SoundExDM = require('./phonetics/dm_soundex'); | |
exports.PorterStemmer = require('./stemmers/porter_stemmer'); | |
/*exports.PorterStemmerFa = require('./stemmers/porter_stemmer_fa'); | |
exports.PorterStemmerFr = require('./stemmers/porter_stemmer_fr'); | |
exports.PorterStemmerRu = require('./stemmers/porter_stemmer_ru'); | |
exports.PorterStemmerEs = require('./stemmers/porter_stemmer_es'); | |
exports.PorterStemmerIt = require('./stemmers/porter_stemmer_it'); | |
exports.PorterStemmerNo = require('./stemmers/porter_stemmer_no'); | |
exports.PorterStemmerSv = require('./stemmers/porter_stemmer_sv'); | |
exports.PorterStemmerPt = require('./stemmers/porter_stemmer_pt'); | |
exports.PorterStemmerNl = require('./stemmers/porter_stemmer_nl');*/ | |
exports.LancasterStemmer = require('./stemmers/lancaster_stemmer'); | |
// StemmerFr and StemmerPl are not stemmers. A Polish stemmer is | |
// not available, and for French PorterStemmerFr should be used. | |
//exports.StemmerFr = require('./stemmers/stemmer_fr'); | |
//exports.StemmerPl = require('./stemmers/stemmer_pl'); | |
//exports.StemmerJa = require('./stemmers/stemmer_ja'); | |
/*exports.StemmerId = require('./stemmers/indonesian/stemmer_id'); | |
exports.AggressiveTokenizerNl = require('./tokenizers/aggressive_tokenizer_nl'); | |
exports.AggressiveTokenizerFa = require('./tokenizers/aggressive_tokenizer_fa'); | |
exports.AggressiveTokenizerFr = require('./tokenizers/aggressive_tokenizer_fr'); | |
exports.AggressiveTokenizerRu = require('./tokenizers/aggressive_tokenizer_ru'); | |
exports.AggressiveTokenizerEs = require('./tokenizers/aggressive_tokenizer_es'); | |
exports.AggressiveTokenizerIt = require('./tokenizers/aggressive_tokenizer_it'); | |
exports.AggressiveTokenizerPl = require('./tokenizers/aggressive_tokenizer_pl'); | |
exports.AggressiveTokenizerPt = require('./tokenizers/aggressive_tokenizer_pt'); | |
exports.AggressiveTokenizerNo = require('./tokenizers/aggressive_tokenizer_no'); | |
exports.AggressiveTokenizerSv = require('./tokenizers/aggressive_tokenizer_sv'); | |
exports.AggressiveTokenizerVi = require('./tokenizers/aggressive_tokenizer_vi'); | |
exports.AggressiveTokenizerId = require('./tokenizers/aggressive_tokenizer_id');*/ | |
exports.AggressiveTokenizer = require('./tokenizers/aggressive_tokenizer'); | |
exports.CaseTokenizer = require('./tokenizers/tokenizer_case'); | |
exports.RegexpTokenizer = require('./tokenizers/regexp_tokenizer').RegexpTokenizer; | |
exports.OrthographyTokenizer = require('./tokenizers/regexp_tokenizer').OrthographyTokenizer; | |
exports.WordTokenizer = require('./tokenizers/regexp_tokenizer').WordTokenizer; | |
exports.WordPunctTokenizer = require('./tokenizers/regexp_tokenizer').WordPunctTokenizer; | |
//exports.TreebankWordTokenizer = require('./tokenizers/treebank_word_tokenizer'); | |
//exports.TokenizerJa = require('./tokenizers/tokenizer_ja'); | |
exports.SentenceTokenizer = require('./tokenizers/sentence_tokenizer'); | |
exports.BayesClassifier = require('./classifiers/bayes_classifier'); | |
exports.LogisticRegressionClassifier = require('./classifiers/logistic_regression_classifier'); | |
exports.NounInflector = require('./inflectors/noun_inflector'); | |
//exports.NounInflectorFr = require('./inflectors/fr/noun_inflector'); | |
//exports.NounInflectorJa = require('./inflectors/ja/noun_inflector'); | |
exports.PresentVerbInflector = require('./inflectors/present_verb_inflector'); | |
exports.CountInflector = require('./inflectors/count_inflector'); | |
//exports.WordNet = require('./wordnet/wordnet'); | |
exports.TfIdf = require('./tfidf/tfidf'); | |
exports.Trie = require('./trie/trie'); | |
exports.SentenceAnalyzer = require('./analyzers/sentence_analyzer'); | |
exports.stopwords = require('./util/stopwords').words; | |
exports.ShortestPathTree = require('./util/shortest_path_tree'); | |
//exports.Spellcheck = require('./spellcheck/spellcheck'); | |
exports.LongestPathTree = require('./util/longest_path_tree'); | |
exports.EdgeWeightedDigraph = require('./util/edge_weighted_digraph'); | |
//exports.NGrams = require('./ngrams/ngrams'); | |
//exports.NGramsZH = require('./ngrams/ngrams_zh'); | |
exports.JaroWinklerDistance = require('./distance/jaro-winkler_distance'); | |
exports.LevenshteinDistance = require('./distance/levenshtein_distance').LevenshteinDistance; | |
exports.DamerauLevenshteinDistance = require('./distance/levenshtein_distance').DamerauLevenshteinDistance; | |
exports.DiceCoefficient = require('./distance/dice_coefficient'); | |
exports.HammingDistance = require('./distance/hamming_distance'); | |
exports.normalize = require('./normalizers/normalizer').normalize_tokens; | |
//exports.normalize_ja = require('./normalizers/normalizer_ja').normalize_ja; | |
exports.removeDiacritics = require('./normalizers/remove_diacritics'); | |
//exports.transliterate_ja = require('./transliterators/ja'); | |
//exports.BrillPOSTagger = require('./brill_pos_tagger/lib/Brill_POS_Tagger'); | |
//exports.BrillPOSTrainer = require('./brill_pos_tagger/lib/Brill_POS_Trainer'); | |
//exports.BrillPOSTester = require('./brill_pos_tagger/lib/Brill_POS_Tester'); | |
//exports.Lexicon = require('./brill_pos_tagger/lib/Lexicon'); | |
//exports.RuleSet = require('./brill_pos_tagger/lib/RuleSet'); | |
//exports.RuleTemplates = require('./brill_pos_tagger/lib/RuleTemplates'); | |
//exports.RuleTemplate = require('./brill_pos_tagger/lib/RuleTemplate'); | |
//exports.Corpus = require('./brill_pos_tagger/lib/Corpus'); | |
/* | |
exports.MaxEntClassifier = require('./classifiers/maxent/Classifier'); | |
exports.Context = require('./classifiers/maxent/Context'); | |
exports.Feature = require('./classifiers/maxent/Feature'); | |
exports.FeatureSet = require('./classifiers/maxent/FeatureSet'); | |
exports.Sample = require('./classifiers/maxent/Sample'); | |
exports.Element = require('./classifiers/maxent/Element'); | |
exports.SE_Element = require('./classifiers/maxent/SimpleExample/SE_Element'); | |
exports.Sentence = require('./brill_pos_tagger/lib/Sentence'); | |
exports.GISScaler = require('./classifiers/maxent/GISScaler'); | |
exports.POS_Element = require('./classifiers/maxent/POS/POS_Element'); | |
exports.ME_Sentence = require('./classifiers/maxent/POS/ME_Sentence'); | |
exports.ME_Corpus = require('./classifiers/maxent/POS/ME_Corpus'); | |
*/ | |
//exports.SentimentAnalyzer = require('./sentiment/SentimentAnalyzer'); //adds like 7mb for some reason? | |
},{"./analyzers/sentence_analyzer":4,"./classifiers/bayes_classifier":5,"./classifiers/logistic_regression_classifier":7,"./distance/dice_coefficient":8,"./distance/hamming_distance":9,"./distance/jaro-winkler_distance":10,"./distance/levenshtein_distance":11,"./inflectors/count_inflector":12,"./inflectors/noun_inflector":14,"./inflectors/present_verb_inflector":15,"./normalizers/normalizer":17,"./normalizers/remove_diacritics":18,"./phonetics/dm_soundex":19,"./phonetics/double_metaphone":20,"./phonetics/metaphone":21,"./phonetics/soundex":23,"./stemmers/lancaster_stemmer":25,"./stemmers/porter_stemmer":26,"./tfidf/tfidf":28,"./tokenizers/aggressive_tokenizer":29,"./tokenizers/regexp_tokenizer":31,"./tokenizers/sentence_tokenizer":32,"./tokenizers/tokenizer_case":34,"./trie/trie":35,"./util/edge_weighted_digraph":37,"./util/longest_path_tree":38,"./util/shortest_path_tree":39,"./util/stopwords":40}]},{},[]); |
how would I generate this file with the recent natural version?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If I wish to update it to the most recent version of natural, how should I proceed? Any tips? Also, which modules were removed to reduce size, and which ones were removed due to incompatibility? Is this information available?